From 1375a60e3f120fbc1832f6be46845f0f268229c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 31 Jan 2010 16:29:12 +0100 Subject: [PATCH] Fixed #1004 (improve check: Unintialized variable not detected when using a reference (&)) --- lib/tokenize.cpp | 62 +++++++++++++++++++++++++++++++++++-- lib/tokenize.h | 3 ++ test/testsimplifytokens.cpp | 33 ++++++++++++++++++-- 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 7cf1f6027..9388a444b 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2466,6 +2466,9 @@ bool Tokenizer::simplifyTokenList() } } + // simplify references + simplifyReference(); + simplifyStd(); simplifyNamespaces(); @@ -4285,7 +4288,8 @@ bool Tokenizer::simplifyKnownVariables() Token::Match(tok2, "%var% = %str% ;") || Token::Match(tok2, "%var% [ ] = %str% ;") || Token::Match(tok2, "%var% = %bool% ;") || - Token::Match(tok2, "%var% = %var% ;"))) + Token::Match(tok2, "%var% = %var% ;") || + Token::Match(tok2, "%var% = & %var% ;"))) { const unsigned int varid = tok2->varId(); if (varid == 0) @@ -4294,12 +4298,16 @@ bool Tokenizer::simplifyKnownVariables() if (tok2->str() == tok2->strAt(2)) continue; - const bool pointeralias(tok2->tokAt(2)->isName()); + const bool pointeralias(tok2->tokAt(2)->isName() || tok2->tokAt(2)->str() == "&"); std::string value(tok2->strAt(2)); if (value == "]") value = tok2->strAt(4); + else if (value == "&") + value = tok2->strAt(3); Token* bailOutFromLoop = 0; + if (Token::simpleMatch(tok2->next(), "= &")) + tok2 = tok2->tokAt(3); int indentlevel3 = indentlevel; // indentlevel for tok3 for (Token *tok3 = tok2->next(); tok3; tok3 = tok3->next()) { @@ -4311,7 +4319,14 @@ bool Tokenizer::simplifyKnownVariables() { --indentlevel3; if (indentlevel3 < indentlevel) + { + if (Token::Match(tok2->tokAt(-3), "%var% = & %var% ;")) + { + tok2 = tok2->tokAt(-4); + Token::eraseTokens(tok2, tok2->tokAt(5)); + } break; + } } if (pointeralias && Token::Match(tok3, ("!!= " + value).c_str())) @@ -4430,6 +4445,12 @@ bool Tokenizer::simplifyKnownVariables() { tok3->next()->str(value); } + + else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid)) + { + tok3->deleteNext(); + tok3->next()->str(value); + } } } } @@ -4547,6 +4568,43 @@ bool Tokenizer::simplifyRedundantParanthesis() return ret; } +void Tokenizer::simplifyReference() +{ + for (Token *tok = _tokens; tok; tok = tok->next()) + { + // starting executable scope.. + if (Token::Match(tok, ") const| {")) + { + // replace references in this scope.. + if (tok->next()->str() != "{") + tok = tok->next(); + Token * const end = tok->next()->link(); + for (Token *tok2 = tok; tok2 && tok2 != end; tok2 = tok2->next()) + { + // found a reference.. + if (Token::Match(tok2, "[;{}] %type% & %var% (|= %var% )| ;")) + { + const unsigned int ref_id = tok2->tokAt(3)->varId(); + if (!ref_id) + continue; + + // replace reference in the code.. + for (Token *tok3 = tok2->tokAt(7); tok3 && tok3 != end; tok3 = tok3->next()) + { + if (tok3->varId() == ref_id) + { + tok3->str(tok2->strAt(5)); + tok3->varId(tok2->tokAt(5)->varId()); + } + } + + Token::eraseTokens(tok2, tok2->tokAt(7)); + } + } + } + } +} + bool Tokenizer::simplifyCalculations() { bool ret = false; diff --git a/lib/tokenize.h b/lib/tokenize.h index 4205f1ee8..10d33df7d 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -295,6 +295,9 @@ private: */ bool simplifyRedundantParanthesis(); + /** Simplify references */ + void simplifyReference(); + /** * Simplify functions like "void f(x) int x; {" * into "void f(int x) {" diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index d5ce7875a..3104c6ad0 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -169,7 +169,8 @@ private: TEST_CASE(reverseArraySyntax) TEST_CASE(simplify_numeric_condition) - TEST_CASE(pointeralias); + TEST_CASE(pointeralias1); + TEST_CASE(pointeralias2); TEST_CASE(reduceConstness); @@ -187,6 +188,9 @@ private: // Tokenizer::simplifyInitVar TEST_CASE(simplifyInitVar); + + // Tokenizer::simplifyReference + TEST_CASE(simplifyReference); } std::string tok(const char code[], bool simplify = true) @@ -3094,7 +3098,7 @@ private: } - void pointeralias() + void pointeralias1() { { const char code[] = "void f()\n" @@ -3179,6 +3183,23 @@ private: } } + void pointeralias2() + { + const char code[] = "void f()\n" + "{\n" + " int i;\n" + " int *p = &i;\n" + " return *p;\n" + "}\n"; + const char expected[] = "void f ( ) " + "{ " + "int i ; " + "; ; " + "return i ; " + "}"; + ASSERT_EQUALS(expected, tok(code)); + } + void reduceConstness() { @@ -3279,6 +3300,14 @@ private: ASSERT_EQUALS("void a ( ) { ; ; }", tok(code)); } } + + void simplifyReference() + { + ASSERT_EQUALS("void f ( ) { int a ; ; a ++ ; }", + tok("void f() { int a; int &b(a); b++; }")); + ASSERT_EQUALS("void f ( ) { int a ; a ++ ; }", + tok("void f() { int a; int &b = a; b++; }")); + } }; REGISTER_TEST(TestSimplifyTokens)