From 5cdbe0f42dde35ac79263b0c29bf39ee6dfc82b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 17 Aug 2014 10:40:22 +0200 Subject: [PATCH] ValueFlow: Improved value flow after for loop --- lib/tokenize.cpp | 9 ++---- lib/valueflow.cpp | 54 ++++++++++++++++++++++++++++++----- test/testtokenize.cpp | 65 ------------------------------------------ test/testvalueflow.cpp | 22 ++++++++++++++ 4 files changed, 71 insertions(+), 79 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8efb4262c..c0d2eb608 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6388,16 +6388,13 @@ bool Tokenizer::simplifyKnownVariables() // parse the block of code.. int indentlevel = 0; Token *tok2 = tok; - bool forhead = false; for (; tok2; tok2 = tok2->next()) { if (Token::Match(tok2, "[;{}] float|double %var% ;")) { floatvars.insert(tok2->tokAt(2)->varId()); } - if (tok2->str() == "{") { - forhead = false; + if (tok2->str() == "{") ++indentlevel; - } else if (tok2->str() == "}") { --indentlevel; @@ -6406,7 +6403,7 @@ bool Tokenizer::simplifyKnownVariables() } else if (Token::simpleMatch(tok2, "for (")) - forhead = true; + tok2 = tok2->next()->link(); else if (tok2->previous()->str() != "*" && !Token::Match(tok2->tokAt(-2), "* --|++") && (Token::Match(tok2, "%var% = %bool%|%char%|%num%|%str%|%var% ;") || @@ -6441,8 +6438,6 @@ bool Tokenizer::simplifyKnownVariables() if (Token::Match(tok3->tokAt(-2), "for ( %type%")) continue; } - if (forhead && Token::Match(tok2->previous(), ", %var% =")) - continue; // struct name.. if (Token::Match(tok2, "%varid% = &| %varid%", tok2->varId())) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index eaa609f4f..94c31fbf1 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1160,7 +1160,7 @@ static void execute(const Token *expr, *error = true; } -static bool valueFlowForLoop1(const Token *tok, unsigned int * const varid, MathLib::bigint * const num1, MathLib::bigint * const num2) +static bool valueFlowForLoop1(const Token *tok, unsigned int * const varid, MathLib::bigint * const num1, MathLib::bigint * const num2, MathLib::bigint * const numAfter) { tok = tok->tokAt(2); if (!Token::Match(tok,"%type%| %var% =")) @@ -1190,6 +1190,7 @@ static bool valueFlowForLoop1(const Token *tok, unsigned int * const varid, Math if (!num2tok) return false; *num2 = MathLib::toLongNumber(num2tok->str()) - ((tok->str()=="<=") ? 0 : 1); + *numAfter = MathLib::toLongNumber(num2tok->str()) + ((tok->str()=="<=") ? 1 : 0); if (!num1tok) *num1 = *num2; while (tok && tok->str() != ";") @@ -1201,7 +1202,8 @@ static bool valueFlowForLoop1(const Token *tok, unsigned int * const varid, Math static bool valueFlowForLoop2(const Token *tok, std::map *memory1, - std::map *memory2) + std::map *memory2, + std::map *memoryAfter) { const Token *firstExpression = tok->next()->astOperand2()->astOperand1(); const Token *secondExpression = tok->next()->astOperand2()->astOperand2()->astOperand1(); @@ -1243,8 +1245,10 @@ static bool valueFlowForLoop2(const Token *tok, } memory1->swap(startMemory); - if (!error) + if (!error) { memory2->swap(endMemory); + memoryAfter->swap(programMemory); + } return true; } @@ -1326,6 +1330,39 @@ static void valueFlowForLoopSimplify(Token * const bodyStart, const unsigned int } } +static void valueFlowForLoopSimplifyAfter(Token *fortok, unsigned int varid, const MathLib::bigint num, TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings) +{ + const Token *vartok = nullptr; + for (const Token *tok = fortok; tok; tok = tok->next()) { + if (tok->varId() == varid) { + vartok = tok; + break; + } + } + if (!vartok || !vartok->variable()) + return; + + const Variable *var = vartok->variable(); + const Token *endToken = nullptr; + if (var->isLocal()) + endToken = var->typeStartToken()->scope()->classEnd; + else + endToken = fortok->scope()->classEnd; + + std::list values; + values.push_back(num); + + valueFlowForward(fortok->linkAt(1)->linkAt(1), + endToken, + var, + varid, + values, + false, + tokenlist, + errorLogger, + settings); +} + static void valueFlowForLoop(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings) { for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { @@ -1337,19 +1374,22 @@ static void valueFlowForLoop(TokenList *tokenlist, ErrorLogger *errorLogger, con Token * const bodyStart = tok->linkAt(1)->next(); unsigned int varid(0); - MathLib::bigint num1(0), num2(0); + MathLib::bigint num1(0), num2(0), numAfter(0); - if (valueFlowForLoop1(tok, &varid, &num1, &num2)) { + if (valueFlowForLoop1(tok, &varid, &num1, &num2, &numAfter)) { valueFlowForLoopSimplify(bodyStart, varid, num1, tokenlist, errorLogger, settings); valueFlowForLoopSimplify(bodyStart, varid, num2, tokenlist, errorLogger, settings); + valueFlowForLoopSimplifyAfter(tok, varid, numAfter, tokenlist, errorLogger, settings); } else { - std::map mem1, mem2; - if (valueFlowForLoop2(tok, &mem1, &mem2)) { + std::map mem1, mem2, memAfter; + if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter)) { std::map::const_iterator it; for (it = mem1.begin(); it != mem1.end(); ++it) valueFlowForLoopSimplify(bodyStart, it->first, it->second, tokenlist, errorLogger, settings); for (it = mem2.begin(); it != mem2.end(); ++it) valueFlowForLoopSimplify(bodyStart, it->first, it->second, tokenlist, errorLogger, settings); + for (it = memAfter.begin(); it != memAfter.end(); ++it) + valueFlowForLoopSimplifyAfter(tok, it->first, it->second, tokenlist, errorLogger, settings); } } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 3f6a857be..f632eee06 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -165,9 +165,7 @@ private: TEST_CASE(simplifyKnownVariables21); TEST_CASE(simplifyKnownVariables22); TEST_CASE(simplifyKnownVariables23); - TEST_CASE(simplifyKnownVariables24); TEST_CASE(simplifyKnownVariables25); - TEST_CASE(simplifyKnownVariables26); TEST_CASE(simplifyKnownVariables27); TEST_CASE(simplifyKnownVariables28); TEST_CASE(simplifyKnownVariables29); // ticket #1811 @@ -2070,51 +2068,6 @@ private: simplifyKnownVariables(code)); } - void simplifyKnownVariables24() { - { - // This testcase is related to ticket #1596 - const char code[] = "void foo()\n" - "{\n" - " int c;\n" - " for (c=0;c<10;++c) { }\n" - " a[c] = 0;\n" - "}\n"; - - ASSERT_EQUALS( - "void foo ( ) " - "{" - " int c ;" - " for ( c = 0 ; c < 10 ; ++ c ) { }" - " a [ 10 ] = 0 ; " - "}", - simplifyKnownVariables(code)); - } - - { - // #1692 - unknown counter value after for loop - const char code[] = "void foo(const char s[])\n" - "{\n" - " int x[3];\n" - " int i;\n" - " for (i = 0; i < 3; ++i) {\n" - " if (s[i]) break;\n" - " }" - " if (i < 3) x[i] = 0;\n" - "}\n"; - ASSERT_EQUALS( - "void foo ( const char s [ ] ) " - "{" - " int x [ 3 ] ;" - " int i ;" - " for ( i = 0 ; i < 3 ; ++ i ) {" - " if ( s [ i ] ) { break ; }" - " }" - " if ( i < 3 ) { x [ i ] = 0 ; } " - "}", - simplifyKnownVariables(code)); - } - } - void simplifyKnownVariables25() { { // This testcase is related to ticket #1646 @@ -2167,24 +2120,6 @@ private: } } - void simplifyKnownVariables26() { - // This testcase is related to ticket #887 - const char code[] = "void foo()\n" - "{\n" - " int i;\n" - " for (i=0;i<10;++i) { }\n" - " int k = i++;\n" - "}\n"; - ASSERT_EQUALS( - "void foo ( ) " - "{" - " int i ;" - " for ( i = 0 ; i < 10 ; ++ i ) { }" - " int k ; k = 10 ; " - "}", - simplifyKnownVariables(code)); - } - void simplifyKnownVariables27() { // This testcase is related to ticket #1633 const char code[] = "void foo()\n" diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index b8df212c9..e134a55ed 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1123,6 +1123,28 @@ private: ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 4U, 9)); + // After loop + code = "void foo() {\n" + " int x;\n" + " for (x = 0; x < 10; x++) {}\n" + " a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 4U, 10)); + + code = "void foo() {\n" + " int x;\n" + " for (x = 0; 2 * x < 20; x++) {}\n" + " a = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 4U, 10)); + + code = "void foo() {\n" // related with #887 + " int x;\n" + " for (x = 0; x < 20; x++) {}\n" + " a = x++;\n" + "}\n"; + TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 4U, 20)); + // hang code = "void f() {\n" " for(int i = 0; i < 20; i++)\n"