Fix issue 10053: False positive: Same value on both branches of ternary operator (#2962)
This commit is contained in:
parent
d1139db960
commit
e12a733ee9
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue