From 78852b08ab8031b08d86e3290636bca3a6601272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 4 Apr 2010 09:17:53 +0200 Subject: [PATCH] Fixed #1566 (false negative: uninitialized variable) --- lib/checkother.cpp | 72 +++++++++++++++++++++++++++++++++++++++++----- lib/checkother.h | 3 +- test/testother.cpp | 9 ++++-- 3 files changed, 73 insertions(+), 11 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index fdddf962d..27c8cc325 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2288,7 +2288,7 @@ private: } if (tok3->varId() == varid) { - varid = 0; // variable is used.. maybe it's initialized. clear the variable id. + varid = 0; // variable is used.. maybe it's initialized. clear the variable id. break; } } @@ -2340,7 +2340,7 @@ public: /** Functions that don't handle uninitialized variables well */ static std::set uvarFunctions; - static void analyseFunctions(const Token * const tokens, std::set &func) + static void analyseFunctions(const Token * const tokens, std::set &func, bool showAll) { for (const Token *tok = tokens; tok; tok = tok->next()) { @@ -2365,9 +2365,67 @@ public: continue; } - if (Token::Match(tok2, "const %type% %var% ,|)") && tok2->next()->isStandardType()) + if (tok2->isStandardType() && Token::Match(tok2, "%type% & %var% ,|)")) { - tok2 = tok2->tokAt(2); + const unsigned int varid(tok2->tokAt(2)->varId()); + + // flags for read/write + bool r = false, w = false; + + // check how the variable is used in the function + unsigned int indentlevel = 0; + for (const Token *tok3 = tok2; tok3; tok3 = tok3->next()) + { + if (tok3->str() == "{") + ++indentlevel; + else if (tok3->str() == "}") + { + if (indentlevel <= 1) + break; + --indentlevel; + } + else if (indentlevel == 0 && tok3->str() == ";") + break; + else if (indentlevel >= 1 && tok3->varId() == varid) + { + if (Token::Match(tok3->previous(), "++|--") || + Token::Match(tok3->next(), "++|--")) + { + r = true; + } + + // --all + else if (showAll) + { + if (!Token::simpleMatch(tok3->next(), "=")) + r = true; + else + { + w = true; + break; + } + } + + else + { + w = true; + break; + } + } + } + + if (!r || w) + break; + + tok2 = tok2->tokAt(3); + continue; + } + + if (Token::Match(tok2, "const %type% &|*| const| %var% ,|)") && tok2->next()->isStandardType()) + { + tok2 = tok2->tokAt(3); + while (tok2->isName()) + tok2 = tok2->next(); continue; } @@ -2389,9 +2447,9 @@ std::set CheckUninitVar::uvarFunctions; /// @} -void CheckOther::analyseFunctions(const Token * const tokens, std::set &func) +void CheckOther::analyseFunctions(const Token * const tokens, std::set &func, bool showAll) { - CheckUninitVar::analyseFunctions(tokens, func); + CheckUninitVar::analyseFunctions(tokens, func, showAll); } @@ -2408,7 +2466,7 @@ void CheckOther::executionPaths() { // no writing if multiple threads are used (TODO: thread safe analysis?) if (_settings->_jobs == 1) - CheckUninitVar::analyseFunctions(_tokenizer->tokens(), CheckUninitVar::uvarFunctions); + CheckUninitVar::analyseFunctions(_tokenizer->tokens(), CheckUninitVar::uvarFunctions, _settings->_showAll); CheckUninitVar c(this); checkExecutionPaths(_tokenizer->tokens(), &c); diff --git a/lib/checkother.h b/lib/checkother.h index 2d5668918..06f6c55db 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -93,8 +93,9 @@ public: * @brief Uninitialized variables: analyse functions to see how they work with uninitialized variables * @param tokens [in] the token list * @param func [out] names of functions that don't handle uninitialized variables well. the function names are added to the set. No clearing is made. + * @param showAll [in] enable --all checking */ - static void analyseFunctions(const Token * const tokens, std::set &func); + static void analyseFunctions(const Token * const tokens, std::set &func, bool showAll); /** @brief Are there C-style pointer casts in a c++ file? */ void warningOldStylePointerCast(); diff --git a/test/testother.cpp b/test/testother.cpp index fe31aad0f..cf01642a5 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -1843,18 +1843,21 @@ private: tokenizer.tokenize(istr, "test.cpp"); std::set f; - CheckOther::analyseFunctions(tokenizer.tokens(), f); + CheckOther::analyseFunctions(tokenizer.tokens(), f, true); std::string ret; for (std::set::const_iterator it = f.begin(); it != f.end(); ++it) - ret += *it + " "; + ret += (ret.empty() ? "" : " ") + *it; return ret; } void uninitvar_func() { // function analysis.. - ASSERT_EQUALS("foo ", analyseFunctions("void foo(int x) { }")); + ASSERT_EQUALS("foo", analyseFunctions("void foo(int x) { }")); + ASSERT_EQUALS("foo", analyseFunctions("void foo(const int &x) { }")); + ASSERT_EQUALS("foo", analyseFunctions("void foo(int &x) { ++x; }")); + ASSERT_EQUALS("", analyseFunctions("void foo(int &x) { x = 0; }")); ASSERT_EQUALS("", analyseFunctions("void foo(s x) { }")); // function calls..