Fix issue 10053: False positive: Same value on both branches of ternary operator (#2962)

This commit is contained in:
Paul Fultz II 2020-12-23 06:37:28 -06:00 committed by GitHub
parent d1139db960
commit e12a733ee9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 9 deletions

View File

@ -741,26 +741,51 @@ static void findTokenValue(const Token* const tok, std::function<bool(const Valu
f(*x);
}
bool isEqualKnownValue(const Token * const tok1, const Token * const tok2)
static bool isSameLifetime(const Token * const tok1, const Token * const tok2)
{
ValueFlow::Value v1 = getLifetimeObjValue(tok1);
ValueFlow::Value v2 = getLifetimeObjValue(tok2);
if (!v1.isLifetimeValue() || !v2.isLifetimeValue())
return false;
return v1.tokvalue == v2.tokvalue;
}
static bool compareKnownValue(const Token * const tok1, const Token * const tok2, std::function<bool(const ValueFlow::Value&, const ValueFlow::Value&, bool)> compare)
{
bool result = false;
bool sameLifetime = isSameLifetime(tok1, tok2);
findTokenValue(tok1, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v1) {
if (v1.isNonValue() || v1.isContainerSizeValue())
return;
findTokenValue(tok2, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v2) {
result = v1.equalValue(v2);
if (v1.valueType == v2.valueType) {
result = compare(v1, v2, sameLifetime);
}
});
});
return result;
}
bool isEqualKnownValue(const Token * const tok1, const Token * const tok2)
{
return compareKnownValue(tok1, tok2, [&](const ValueFlow::Value& v1, const ValueFlow::Value& v2, bool sameLifetime) {
bool r = v1.equalValue(v2);
if (v1.isIteratorValue()) {
r &= sameLifetime;
}
return r;
});
}
bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2)
{
bool result = false;
findTokenValue(tok1, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v1) {
findTokenValue(tok2, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v2) {
result = !v1.equalValue(v2);
});
return compareKnownValue(tok1, tok2, [&](const ValueFlow::Value& v1, const ValueFlow::Value& v2, bool sameLifetime) {
bool r = v1.equalValue(v2);
if (v1.isIteratorValue()) {
r &= sameLifetime;
}
return !r;
});
return result;
}
static bool isSameConstantValue(bool macro, const Token * const tok1, const Token * const tok2)

View File

@ -399,6 +399,6 @@ std::string lifetimeType(const Token *tok, const ValueFlow::Value *val);
std::string lifetimeMessage(const Token *tok, const ValueFlow::Value *val, ValueFlow::Value::ErrorPath &errorPath);
ValueFlow::Value getLifetimeObjValue(const Token *tok, bool inconclusive = false);
CPPCHECKLIB ValueFlow::Value getLifetimeObjValue(const Token *tok, bool inconclusive = false);
#endif // valueflowH

View File

@ -5340,6 +5340,23 @@ private:
check("int f8(int a) {return (a == (int)1) ? 1 : 1; }");
ASSERT_EQUALS("[test.cpp:1]: (style) Same value in both branches of ternary operator.\n", errout.str());
check("struct Foo {\n"
" std::vector<int> bar{1,2,3};\n"
" std::vector<int> baz{4,5,6};\n"
"};\n"
"void f() {\n"
" Foo foo;\n"
" it = true ? foo.bar.begin() : foo.baz.begin();\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void f(bool b) {\n"
" std::vector<int> bar{1,2,3};\n"
" std::vector<int> baz{4,5,6};\n"
" std::vector<int> v = b ? bar : baz;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void duplicateExpressionTemplate() { // #6930