Skip to content
32 changes: 19 additions & 13 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4966,6 +4966,24 @@ static void valueFlowCondition(const ValuePtr<ConditionHandler>& 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<Condition> parse(const Token* tok, const Settings& /*settings*/) const override {

Expand All @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions test/testnullpointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3723,6 +3723,13 @@ class TestNullPointer : public TestFixture {
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() {
Expand Down
1 change: 1 addition & 0 deletions test/testsimplifytokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -1727,6 +1729,7 @@ class TestTokenizer : public TestFixture {
" try { throw 1; }\n"
" catch(...) { --x; }\n"
"}"));
ignore_errout();
}


Expand Down
Loading