Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #3069 (False positive: Memory leak: data)

  • Loading branch information...
commit 46b5d5bd00e07d89541fd57216e8a7d0bcf81378 1 parent d098ed6
@danmar authored
Showing with 135 additions and 0 deletions.
  1. +102 −0 lib/tokenize.cpp
  2. +7 −0 lib/tokenize.h
  3. +26 −0 test/testsimplifytokens.cpp
View
102 lib/tokenize.cpp
@@ -4755,6 +4755,9 @@ bool Tokenizer::simplifyTokenList()
modified |= simplifyCalculations();
}
+ // simplify redundant for
+ removeRedundantFor();
+
// Remove redundant parentheses in return..
for (Token *tok = _tokens; tok; tok = tok->next())
{
@@ -5004,6 +5007,105 @@ bool Tokenizer::removeReduntantConditions()
return ret;
}
+void Tokenizer::removeRedundantFor()
+{
+ for (Token *tok = _tokens; tok; tok = tok->next())
+ {
+ if (Token::Match(tok, "[;{}] for ( %var% = %num% ; %var% < %num% ; ++| %var% ++| ) {"))
+ {
+ // Same variable name..
+ const std::string varname(tok->tokAt(3)->str());
+ const unsigned int varid(tok->tokAt(3)->varId());
+ if (varname != tok->tokAt(7)->str())
+ continue;
+ const Token *vartok = tok->tokAt(11);
+ if (vartok->str() == "++")
+ vartok = vartok->next();
+ if (varname != vartok->str())
+ continue;
+
+ // Check that the difference of the numeric values is 1
+ const MathLib::bigint num1(MathLib::toLongNumber(tok->strAt(5)));
+ const MathLib::bigint num2(MathLib::toLongNumber(tok->strAt(9)));
+ if (num1 + 1 != num2)
+ continue;
+
+ // check how loop variable is used in loop..
+ bool read = false;
+ bool write = false;
+ unsigned int indentlevel = 0;
+ for (const Token *tok2 = tok->tokAt(2)->link(); tok2; tok2 = tok2->next())
+ {
+ if (tok2->str() == "{")
+ ++indentlevel;
+ else if (tok2->str() == "}")
+ {
+ if (indentlevel <= 1)
+ break;
+ --indentlevel;
+ }
+
+ if (tok2->str() == varname)
+ {
+ if (tok2->previous()->isArithmeticalOp() &&
+ tok2->next() &&
+ (tok2->next()->isArithmeticalOp() || tok2->next()->str() == ";"))
+ {
+ read = true;
+ }
+ else
+ {
+ read = write = true;
+ break;
+ }
+ }
+ }
+
+ // Simplify loop if loop variable isn't written
+ if (!write)
+ {
+ // remove "for ("
+ tok->deleteNext();
+ tok->deleteNext();
+
+ // If loop variable is read then keep assignment before
+ // loop body..
+ if (read)
+ {
+ // goto ";"
+ tok = tok->tokAt(4);
+ }
+ else
+ {
+ // remove "x = 0 ;"
+ tok->deleteNext();
+ tok->deleteNext();
+ tok->deleteNext();
+ tok->deleteNext();
+ }
+
+ // remove "x < 1 ; x ++ )"
+ tok->deleteNext();
+ tok->deleteNext();
+ tok->deleteNext();
+ tok->deleteNext();
+ tok->deleteNext();
+ tok->deleteNext();
+ tok->deleteNext();
+
+ // Add assignment after the loop body so the loop variable
+ // get the correct end value
+ Token *tok2 = tok->next()->link();
+ tok2->insertToken(";");
+ tok2->insertToken(MathLib::toString(num2));
+ tok2->insertToken("=");
+ tok2->insertToken(varname);
+ tok2->next()->varId(varid);
+ }
+ }
+ }
+}
+
void Tokenizer::removeRedundantSemicolons()
{
View
7 lib/tokenize.h
@@ -360,6 +360,13 @@ class Tokenizer
bool removeReduntantConditions();
/**
+ * Remove redundant for:
+ * "for (x=0;x<1;x++) { }" => "{ x = 1; }"
+ */
+ void removeRedundantFor();
+
+
+ /**
* Reduces "; ;" to ";", except in "( ; ; )"
*/
void removeRedundantSemicolons();
View
26 test/testsimplifytokens.cpp
@@ -376,6 +376,11 @@ class TestSimplifyTokens : public TestFixture
TEST_CASE(simplifyVarDecl1); // ticket # 2682 segmentation fault
TEST_CASE(simplifyVarDecl2); // ticket # 2834 segmentation fault
TEST_CASE(return_strncat); // ticket # 2860 Returning value of strncat() reported as memory leak
+
+ // #3069 : for loop with 1 iteration
+ // for (x=0;x<1;x++) { .. }
+ // The for is redundant
+ TEST_CASE(removeRedundantFor);
}
std::string tok(const char code[], bool simplify = true)
@@ -7385,6 +7390,27 @@ class TestSimplifyTokens : public TestFixture
"return temp ; "
"}", tok(code, true));
}
+
+ void removeRedundantFor() // ticket #3069
+ {
+ {
+ const char code[] = "void f() {"
+ " for(x=0;x<1;x++) {"
+ " y = 1;"
+ " }"
+ "}";
+ ASSERT_EQUALS("void f ( ) { { y = 1 ; } x = 1 ; }", tok(code, true));
+ }
+
+ {
+ const char code[] = "void f() {"
+ " for(x=0;x<1;x++) {"
+ " y = 1 + x;"
+ " }"
+ "}";
+ ASSERT_EQUALS("void f ( ) { x = 0 ; { y = 1 + x ; } x = 1 ; }", tok(code, true));
+ }
+ }
};
REGISTER_TEST(TestSimplifyTokens)
Please sign in to comment.
Something went wrong with that request. Please try again.