diff --git a/lib/reverseanalyzer.cpp b/lib/reverseanalyzer.cpp index 50aad01fdd9..4afd2556a24 100644 --- a/lib/reverseanalyzer.cpp +++ b/lib/reverseanalyzer.cpp @@ -110,8 +110,11 @@ namespace { { if (Token::simpleMatch(tok->tokAt(-2), "} else {")) tok = tok->linkAt(-2); - if (Token::simpleMatch(tok->previous(), ") {")) + if (Token::simpleMatch(tok->previous(), ") {")) { + if (Token::simpleMatch(tok->linkAt(-1)->astOperand2(), ";")) + return tok->linkAt(-1)->astOperand2(); return tok->linkAt(-1); + } if (Token::simpleMatch(tok->previous(), "do {")) return tok->previous(); return tok; @@ -232,7 +235,7 @@ namespace { if (!Token::Match(assignTop->astOperand1(), "%assign%")) { continueB &= updateRecursive(assignTop->astOperand1()); } - if (!assignTop->astParent()) + if (!assignTop->astParent() || Token::simpleMatch(assignTop->astParent(), ";")) break; assignTop = assignTop->astParent(); } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 74763fde027..cc71510df9e 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4966,6 +4966,24 @@ static void valueFlowCondition(const ValuePtr& handler, handler->afterCondition(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions); } +static const Token* getConditionVariable(const Token* tok) +{ + if (tok->str() == "!") + return tok->astOperand1(); + + if (const Token* parent = tok->astParent()) { + if (Token::Match(parent, "%oror%|&&|?") || + Token::Match(parent->previous(), "if|while (") || + (parent->str() == ";" && Token::simpleMatch(parent->astParent(), ";"))) { + if (Token::simpleMatch(tok, "=")) + return tok->astOperand1(); + if (!Token::Match(tok, "%comp%|%assign%")) + return tok; + } + } + return nullptr; +} + struct SimpleConditionHandler : ConditionHandler { std::vector parse(const Token* tok, const Settings& /*settings*/) const override { @@ -4984,19 +5002,7 @@ struct SimpleConditionHandler : ConditionHandler { if (!conds.empty()) return conds; - const Token* vartok = nullptr; - - if (tok->str() == "!") { - vartok = tok->astOperand1(); - - } else if (tok->astParent() && (Token::Match(tok->astParent(), "%oror%|&&|?") || - Token::Match(tok->astParent()->previous(), "if|while ("))) { - if (Token::simpleMatch(tok, "=")) - vartok = tok->astOperand1(); - else if (!Token::Match(tok, "%comp%|%assign%")) - vartok = tok; - } - + const Token* vartok = getConditionVariable(tok); if (!vartok) return {}; Condition cond; diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index a9ce5ff6f38..d489437e7cf 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -3710,6 +3710,27 @@ class TestNullPointer : public TestFixture { " i++;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("void f(const int* p) {\n" // #6710 + " for (int i = *p; i < 5; ++i) {}\n" + " if (p) {}\n" + "}\n" + "struct S { int a; };\n" + "void g(const S* s) {\n" + " for (int i = s->a; i < 5; ++i) {}\n" + " if (s) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:9] -> [test.cpp:2:19]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. [nullPointerRedundantCheck]\n" + "[test.cpp:8:9] -> [test.cpp:7:18]: (warning) Either the condition 's' is redundant or there is possible null pointer dereference: s. [nullPointerRedundantCheck]\n", + errout_str()); + + check("struct S { int a; };\n" // #6492 + "void h(const S* s) {\n" + " for (int i = s->a; s; ++i) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:24] -> [test.cpp:3:18]: (warning) Either the condition 's' is redundant or there is possible null pointer dereference: s. [nullPointerRedundantCheck]\n", + errout_str()); + } void nullpointerDeadCode() { diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 4e227bfca17..88d1a4b2725 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -2207,6 +2207,7 @@ class TestSimplifyTokens : public TestFixture { "for ( i = 0 ; ( i < sz ) && ( sz > 3 ) ; ++ i ) { }\n" "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code, dinit(TokenizeAndStringifyOptions, $.cpp = false))); + ignore_errout(); } void simplifyKnownVariables49() { // #3691 diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 0798983c079..44a2166cd9b 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -1703,6 +1703,7 @@ class TestTokenizer : public TestFixture { " for ( ; x; )\n" " l1: l2: --x;\n" "}")); + ignore_errout(); // Labels before { ASSERT_EQUALS("void f ( int x ) {\n" @@ -1713,6 +1714,7 @@ class TestTokenizer : public TestFixture { " for ( ; x; )\n" " l1: l2: { -- x; }\n" "}")); + ignore_errout(); // Labels before try/catch ASSERT_EQUALS("void f ( int x ) {\n" @@ -1727,6 +1729,7 @@ class TestTokenizer : public TestFixture { " try { throw 1; }\n" " catch(...) { --x; }\n" "}")); + ignore_errout(); }