From 929a54e1b0494515cb7cee1155ba08783ff2a0d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 9 Sep 2010 19:40:36 +0200 Subject: [PATCH] Fixed #2038 (memleak false positive with assignment expression in arguments) --- lib/tokenize.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++ lib/tokenize.h | 4 ++++ test/testtokenize.cpp | 8 ++++++++ 3 files changed, 56 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 2ac8387b8..a6724ca8c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2042,6 +2042,9 @@ bool Tokenizer::tokenize(std::istream &code, // Split up variable declarations. simplifyVarDecl(); + // f(x=g()) => x=g(); f(x) + simplifyAssignmentInFunctionCall(); + simplifyVariableMultipleAssign(); // Remove redundant parantheses @@ -5250,6 +5253,8 @@ void Tokenizer::simplifyStdType() void Tokenizer::simplifyIfAssign() { + // See also simplifyFunctionAssign + for (Token *tok = _tokens; tok; tok = tok->next()) { if (!Token::Match(tok->next(), "if|while ( !| (| %var% =") && @@ -8217,6 +8222,45 @@ void Tokenizer::simplifyKeyword() } } +void Tokenizer::simplifyAssignmentInFunctionCall() +{ + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (tok->str() == "(") + tok = tok->link(); + else if (Token::Match(tok, "[;{}] %var% ( %var% =") && Token::simpleMatch(tok->tokAt(2)->link(), ") ;")) + { + const std::string funcname(tok->strAt(1)); + const Token * const vartok = tok->tokAt(3); + + // Goto ',' or ')'.. + for (Token *tok2 = tok->tokAt(4); tok2; tok2 = tok2->next()) + { + if (tok2->str() == "(") + tok2 = tok2->link(); + else if (tok2->str() == ";") + break; + else if (tok2->str() == ")" || tok2->str() == ",") + { + tok2 = tok2->previous(); + + tok2->insertToken(vartok->str()); + tok2->next()->varId(vartok->varId()); + + tok2->insertToken("("); + Token::createMutualLinks(tok2->next(), tok->tokAt(2)->link()); + + tok2->insertToken(funcname); + tok2->insertToken(";"); + + Token::eraseTokens(tok, vartok); + break; + } + } + } + } +} + // Remove __asm.. void Tokenizer::simplifyAsm() { diff --git a/lib/tokenize.h b/lib/tokenize.h index 6e0a85e64..3ccebf7c1 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -136,6 +136,10 @@ public: */ std::map _classInfoList; + /** Simplify assignment in function call "f(x=g());" => "x=g();f(x);" + */ + void simplifyAssignmentInFunctionCall(); + /** * Simplify constant calculations such as "1+2" => "3" * @return true if modifications to token-list are done. diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index e486e1e0c..8063b0182 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -261,6 +261,9 @@ private: TEST_CASE(sql); TEST_CASE(simplifyLogicalOperators); + + // foo(p = new char[10]); => p = new char[10]; foo(p); + simplifyAssignmentInFunctionCall(); } @@ -4555,6 +4558,11 @@ private: ASSERT_EQUALS("if ( ! b )", tokenizeAndStringify("if (not b)")); ASSERT_EQUALS("if ( a != b )", tokenizeAndStringify("if (a not_eq b)")); } + + void simplifyAssignmentInFunctionCall() + { + ASSERT_EQUALS("; x = g ( ) ; f ( x ) ;", tokenizeAndStringify(";f(x=g());")); + } }; REGISTER_TEST(TestTokenizer)