diff --git a/lib/astutils.cpp b/lib/astutils.cpp index d389687ce..20e0529f4 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -281,8 +281,15 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token cond2->astOperand2() && cond2->astOperand2()->hasKnownIntValue()) { const ValueFlow::Value &rhsValue1 = cond1->astOperand2()->values().front(); const ValueFlow::Value &rhsValue2 = cond2->astOperand2()->values().front(); - if (comp1 == "<" && cond2->str() == "==") - return (rhsValue1.intvalue < rhsValue2.intvalue); + bool secondAlwaysFalse = false; + + if (comp1 == "<" || comp1 == "<=") + secondAlwaysFalse = Token::Match(cond2, "==|>|>=") && (rhsValue1.intvalue < rhsValue2.intvalue); + else if (comp1 == ">=" || comp1 == ">") + secondAlwaysFalse = Token::Match(cond2, "==|<|<=") && (rhsValue1.intvalue > rhsValue2.intvalue); + + if (secondAlwaysFalse) + return true; } } diff --git a/test/testcondition.cpp b/test/testcondition.cpp index eb9cf4886..09939bcbe 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -76,6 +76,7 @@ private: TEST_CASE(modulo); TEST_CASE(oppositeInnerCondition); + TEST_CASE(oppositeInnerCondition2); TEST_CASE(clarifyCondition1); // if (a = b() < 0) TEST_CASE(clarifyCondition2); // if (a & b == c) @@ -1584,6 +1585,120 @@ private: ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n", errout.str()); } + void oppositeInnerCondition2() { + // first comparison: < + check("void f(int x) {\n" + "\n" + " if (x<4) {\n" + " if (x==5) {}\n" // <- Warning + " }\n" + "\n" + " if (x<4) {\n" + " if (x!=5) {}\n" // <- TODO + " }\n" + "\n" + " if (x<4) {\n" + " if (x>5) {}\n" // <- Warning + " }\n" + "\n" + " if (x<4) {\n" + " if (x>=5) {}\n" // <- Warning + " }\n" + "\n" + " if (x<4) {\n" + " if (x<5) {}\n" + " }\n" + "\n" + " if (x<4) {\n" + " if (x<=5) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n" + "[test.cpp:11] -> [test.cpp:12]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n" + "[test.cpp:15] -> [test.cpp:16]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n" + , errout.str()); + + check("void f(int x) {\n" + "\n" + " if (x<5) {\n" + " if (x==4) {}\n" + " }\n" + "\n" + " if (x<5) {\n" + " if (x!=4) {}\n" + " }\n" + "\n" + " if (x<5) {\n" + " if (x>4) {}\n" // <- TODO + " }\n" + "\n" + " if (x<5) {\n" + " if (x>=4) {}\n" + " }\n" + "\n" + " if (x<5) {\n" + " if (x<4) {}\n" + " }\n" + "\n" + " if (x<5) {\n" + " if (x<=4) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // first comparison: > + check("void f(int x) {\n" + "\n" + " if (x>4) {\n" + " if (x==5) {}\n" + " }\n" + "\n" + " if (x>4) {\n" + " if (x>5) {}\n" + " }\n" + "\n" + " if (x>4) {\n" + " if (x>=5) {}\n" // <- TODO + " }\n" + "\n" + " if (x>4) {\n" + " if (x<5) {}\n" // <- TODO + " }\n" + "\n" + " if (x>4) {\n" + " if (x<=5) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void f(int x) {\n" + "\n" + " if (x>5) {\n" + " if (x==4) {}\n" // <- Warning + " }\n" + "\n" + " if (x>5) {\n" + " if (x>4) {}\n" // <- TODO + " }\n" + "\n" + " if (x>5) {\n" + " if (x>=4) {}\n" // <- TODO + " }\n" + "\n" + " if (x>5) {\n" + " if (x<4) {}\n" // <- Warning + " }\n" + "\n" + " if (x>5) {\n" + " if (x<=4) {}\n" // <- Warning + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n" + "[test.cpp:15] -> [test.cpp:16]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n" + "[test.cpp:19] -> [test.cpp:20]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n" + , errout.str()); + } + // clarify conditions with = and comparison void clarifyCondition1() { check("void f() {\n"