From 847bb44bddb25ad054bca5303972e313b3e220cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 16 Jun 2014 16:39:41 +0200 Subject: [PATCH] ValueFlow: Improved analysis after condition when ! operator is used --- lib/valueflow.cpp | 56 +++++++++++++++++++++++++++++++----------- test/testvalueflow.cpp | 11 ++++++++- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 5b9635fa2..7d0da70b6 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -753,35 +753,61 @@ static void valueFlowAfterAssign(TokenList *tokenlist, ErrorLogger *errorLogger, static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings) { for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { - // Comparison - if (!tok->isComparisonOp() || !Token::Match(tok,"==|!=|>=|<=")) - continue; - - if (!tok->astOperand1() || !tok->astOperand2()) - continue; - const Token *vartok, *numtok; - if (tok->astOperand1()->isName()) { + + // Comparison + if (Token::Match(tok,"==|!=|>=|<=")) { + if (!tok->astOperand1() || !tok->astOperand2()) + continue; + if (tok->astOperand1()->isName()) { + vartok = tok->astOperand1(); + numtok = tok->astOperand2(); + } else { + vartok = tok->astOperand2(); + numtok = tok->astOperand1(); + } + if (!vartok->isName() || !numtok->isNumber()) + continue; + } else if (tok->str() == "!") { vartok = tok->astOperand1(); - numtok = tok->astOperand2(); + numtok = nullptr; + if (!vartok || !vartok->isName()) + continue; } else { - vartok = tok->astOperand2(); - numtok = tok->astOperand1(); - } - if (!vartok->isName() || !numtok->isNumber()) continue; + } const unsigned int varid = vartok->varId(); if (varid == 0U) continue; const Variable *var = vartok->variable(); if (!var || !(var->isLocal() || var->isArgument())) continue; - std::list values = numtok->values; + std::list values; + values.push_back(ValueFlow::Value(tok, numtok ? MathLib::toLongNumber(numtok->str()) : 0LL)); const Token *top = tok->astTop(); if (top && Token::simpleMatch(top->previous(), "if (")) { + // does condition reassign variable? + std::stack tokens; + tokens.push(top); + while (!tokens.empty()) { + const Token *tok2 = tokens.top(); + tokens.pop(); + if (!tok2) + continue; + tokens.push(tok2->astOperand1()); + tokens.push(tok2->astOperand2()); + if (tok2->str() == "=" && Token::Match(tok2->astOperand1(), "%varid%", varid)) + break; + } + if (!tokens.empty()) { + if (settings->debugwarnings) + bailout(tokenlist, errorLogger, tok, "assignment in condition"); + continue; + } + Token *startToken = nullptr; - if (Token::Match(tok, "==|>=|<=") && Token::simpleMatch(top->link(), ") {")) + if (Token::Match(tok, "==|>=|<=|!") && Token::simpleMatch(top->link(), ") {")) startToken = top->link()->next(); else if (tok->str() == "!=" && Token::simpleMatch(top->link()->linkAt(1), "} else {")) startToken = top->link()->linkAt(1)->tokAt(2); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index f773c2389..9b7008954 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -488,7 +488,8 @@ private: " if (abc) {}\n" "}\n"); ASSERT_EQUALS("[test.cpp:2]: (debug) ValueFlow bailout: assignment of abc\n" - "[test.cpp:8]: (debug) ValueFlow bailout: variable abc stopping on goto label\n", + "[test.cpp:8]: (debug) ValueFlow bailout: variable abc stopping on goto label\n" + "[test.cpp:3]: (debug) ValueFlow bailout: variable abc. noreturn conditional scope.\n", errout.str()); } @@ -750,6 +751,14 @@ private: " else a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); + + // ! + code = "void f(int x) {\n" + " if (!x) { a = x; }\n" + " else a = x;\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); + } void valueFlowBitAnd() {