From e12a733ee97cb225bb1c60222b664c1f1abd7043 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Wed, 23 Dec 2020 06:37:28 -0600 Subject: [PATCH] Fix issue 10053: False positive: Same value on both branches of ternary operator (#2962) --- lib/astutils.cpp | 41 +++++++++++++++++++++++++++++++++-------- lib/valueflow.h | 2 +- test/testother.cpp | 17 +++++++++++++++++ 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 2e8ac921c..0dcc49807 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -741,26 +741,51 @@ static void findTokenValue(const Token* const tok, std::function 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) diff --git a/lib/valueflow.h b/lib/valueflow.h index edbc5ea71..e799d69ad 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -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 diff --git a/test/testother.cpp b/test/testother.cpp index 16b365d6c..cfe2ddb8b 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -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 bar{1,2,3};\n" + " std::vector 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 bar{1,2,3};\n" + " std::vector baz{4,5,6};\n" + " std::vector v = b ? bar : baz;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void duplicateExpressionTemplate() { // #6930