From 4d045879aa61ab1d2f7736e138b5e2bad3b4f30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 11 Jan 2014 20:25:49 +0100 Subject: [PATCH] value flow: fixed fp when while condition contains variable that is changed in loop body --- lib/valueflow.cpp | 21 +++++++++++++++++++++ test/testvalueflow.cpp | 13 +++++++++++++ 2 files changed, 34 insertions(+) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 675258db6..9a1d7199b 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -141,6 +141,27 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog continue; } + // bailout: while-condition, variable is changed in while loop + for (const Token *tok2 = tok; tok2; tok2 = tok2->previous()) { + if (tok2->str() == ")") + tok2 = tok2->link(); + else if (tok2->str() == "(") { + if (Token::Match(tok2->previous(), "for|while (") && Token::Match(tok2->link(), ") {")) { + const Token *start = tok2->link()->next(); + const Token *end = start->link(); + if (Token::findmatch(start,"++|--| %varid% ++|--|=",end,varid)) + varid = 0U; + } + break; + } + } + if (varid == 0U) { + if (settings->debugwarnings) + bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + " used in loop "); + continue; + } + + // extra logic for unsigned variables 'i>=1' => possible value can also be 0 const ValueFlow::Value val(tok, num); ValueFlow::Value val2; if (var && num==1U && Token::Match(tok,"<=|>=")) { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 78324fb1f..27274cef5 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -138,6 +138,19 @@ private: ASSERT_EQUALS(false, testValueOfX(std::string("void setx(int &x);")+code, 2U, 1)); ASSERT_EQUALS(false, testValueOfX(code, 2U, 1)); + // while, for, do-while + code = "void f(int x) {\n" + " a = x;\n" // x can be 37 + " while (x == 37) {}\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 2U, 37)); + + code = "void f(int x) {\n" + " a = x;\n" // don't assume that x can be 37 + " while (x != 37) { x++; }\n" + "}"; + ASSERT_EQUALS(false, testValueOfX(code, 2U, 37)); + // bailout: ?: bailout("void f(int x) {\n" " y = ((x<0) ? x : ((x==2)?3:4));\n"