From ef81bc363a8a775e760d3cf762a2525ad760bb3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 19 Jun 2014 17:29:41 +0200 Subject: [PATCH] ValueFlow: analysis in condition. --- lib/valueflow.cpp | 31 +++++++++++++++++++++++++++++++ test/testnullpointer.cpp | 2 +- test/testvalueflow.cpp | 13 +++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 32a9b5f51..b9c099cb5 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -815,6 +815,37 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg std::list values; values.push_back(ValueFlow::Value(tok, numtok ? MathLib::toLongNumber(numtok->str()) : 0LL)); + if (Token::Match(tok->astParent(), "%oror%|&&")) { + Token *parent = const_cast(tok->astParent()); + const std::string &op(parent->str()); + + if (parent->astOperand1() == tok && + ((op == "&&" && Token::Match(tok, "==|>=|<=|!")) || + (op == "||" && Token::Match(tok, "%var%|!=")))) { + bool assign = false; + for (; !assign && parent && parent->str() == op; parent = const_cast(parent->astParent())) { + std::stack tokens; + tokens.push(const_cast(parent->astOperand2())); + while (!tokens.empty()) { + Token *rhstok = tokens.top(); + tokens.pop(); + if (!rhstok) + continue; + tokens.push(const_cast(rhstok->astOperand1())); + tokens.push(const_cast(rhstok->astOperand2())); + if (rhstok->varId() == varid) + setTokenValue(rhstok, values.front()); + if (Token::Match(rhstok, "++|--|=") && Token::Match(rhstok->astOperand1(),"%varid%",varid)) { + assign = true; + break; + } + } + while (parent->astParent() && parent == parent->astParent()->astOperand2()) + parent = const_cast(parent->astParent()); + } + } + } + const Token *top = tok->astTop(); if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) { // does condition reassign variable? diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 0606bbbe0..74b34ab77 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -1059,7 +1059,7 @@ private: " p = q;\n" " if (p || *p) { }\n" "}"); - TODO_ASSERT_EQUALS("error", "", errout.str()); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:5]: (warning) Possible null pointer dereference: p - otherwise it is redundant to check it against null.\n", errout.str()); } } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 59de3827c..42bd4427e 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -777,6 +777,19 @@ private: " a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 3)); + + // In condition, after && and || + code = "void f(int x) {\n" + " a = (x != 3 ||\n" + " x);\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 3)); + + code = "void f(int x) {\n" + " a = (x == 4 &&\n" + " x);\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 4)); } void valueFlowBitAnd() {