From 765c1ace87eddc49ba3dcf81f00adcfad46f026e Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Sat, 26 Dec 2020 07:45:17 -0500 Subject: [PATCH] fix #10008 (false negative: knownEmptyContainer with alias in namespace and "using namespace") (#2979) --- lib/tokenize.cpp | 33 ++++++++++++++++++++------------- test/testsimplifyusing.cpp | 16 ++++++++++++++++ test/teststl.cpp | 11 +++++++++++ 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index a4a13d21a..0ef905e48 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1696,8 +1696,10 @@ void Tokenizer::simplifyTypedef() namespace { struct ScopeInfo3 { - ScopeInfo3(const std::string &name_, const Token *bodyEnd_) : name(name_), bodyEnd(bodyEnd_) {} + ScopeInfo3(const std::string &name_, const Token *bodyStart_, const Token *bodyEnd_) + : name(name_), bodyStart(bodyStart_), bodyEnd(bodyEnd_) {} const std::string name; + const Token * const bodyStart; const Token * const bodyEnd; std::set usingNamespaces; }; @@ -1716,6 +1718,9 @@ namespace { { if (!tok) return; + if (tok->str() == "{" && !scopeInfo->empty() && tok == scopeInfo->back().bodyStart) + return; + while (tok->str() == "}" && !scopeInfo->empty() && tok == scopeInfo->back().bodyEnd) scopeInfo->pop_back(); if (!Token::Match(tok, "namespace|class|struct|union %name% {|:|::|<")) { @@ -1762,13 +1767,13 @@ namespace { scope = tok1->strAt(-3) + " :: " + scope; tok1 = tok1->tokAt(-2); } - scopeInfo->emplace_back(scope, tok->link()); + scopeInfo->emplace_back(scope, tok, tok->link()); added = true; } } if (all && !added) - scopeInfo->emplace_back("", tok->link()); + scopeInfo->emplace_back("", tok, tok->link()); } return; } @@ -1791,7 +1796,7 @@ namespace { tok = tok->next(); } if (tok && tok->str() == "{") { - scopeInfo->emplace_back(classname,tok->link()); + scopeInfo->emplace_back(classname, tok, tok->link()); } } @@ -1878,14 +1883,16 @@ namespace { return true; // check using namespace - if (!scopeList1.back().usingNamespaces.empty()) { - if (qualification.empty()) { - if (scopeList1.back().usingNamespaces.find(scope) != scopeList1.back().usingNamespaces.end()) - return true; - } else { - for (auto ns : scopeList1.back().usingNamespaces) { - if (scope == ns + " :: " + qualification) + for (std::list::const_reverse_iterator it = scopeList1.crbegin(); it != scopeList1.crend(); ++it) { + if (!it->usingNamespaces.empty()) { + if (qualification.empty()) { + if (it->usingNamespaces.find(scope) != it->usingNamespaces.end()) return true; + } else { + for (auto ns : it->usingNamespaces) { + if (scope == ns + " :: " + qualification) + return true; + } } } } @@ -1945,7 +1952,7 @@ bool Tokenizer::simplifyUsing() }; std::list usingList; - scopeList.emplace_back("", nullptr); + scopeList.emplace_back("", nullptr, nullptr); for (Token *tok = list.front(); tok; tok = tok->next()) { if (mErrorLogger && !list.getFiles().empty()) @@ -1975,7 +1982,7 @@ bool Tokenizer::simplifyUsing() continue; std::list scopeList1; - scopeList1.emplace_back("", nullptr); + scopeList1.emplace_back("", nullptr, nullptr); std::string name = tok->strAt(1); const Token *nameToken = tok->next(); std::string scope = getScopeName(scopeList); diff --git a/test/testsimplifyusing.cpp b/test/testsimplifyusing.cpp index 60d1cd349..58eb8cfb9 100644 --- a/test/testsimplifyusing.cpp +++ b/test/testsimplifyusing.cpp @@ -75,6 +75,7 @@ private: TEST_CASE(simplifyUsing9388); TEST_CASE(simplifyUsing9518); TEST_CASE(simplifyUsing9757); + TEST_CASE(simplifyUsing10008); } std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Native, bool debugwarnings = true) { @@ -647,6 +648,21 @@ private: "switch ( type ) { } }"; ASSERT_EQUALS(exp, tok(code, false)); } + + void simplifyUsing10008() { + const char code[] = "namespace ns {\n" + " using ArrayType = std::vector;\n" + "}\n" + "using namespace ns;\n" + "static void f() {\n" + " const ArrayType arr;\n" + "}"; + const char exp[] = "using namespace ns ; " + "static void f ( ) { " + "const std :: vector < int > arr ; " + "}"; + ASSERT_EQUALS(exp, tok(code, false)); + } }; REGISTER_TEST(TestSimplifyUsing) diff --git a/test/teststl.cpp b/test/teststl.cpp index 439e1a413..7db9d5c4f 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -4741,6 +4741,17 @@ private: "}\n", true); ASSERT_EQUALS("", errout.str()); + + check("namespace ns {\n" + " using ArrayType = std::vector;\n" + "}\n" + "using namespace ns;\n" + "static void f() {\n" + " const ArrayType arr;\n" + " for (const auto &a : arr) {}\n" + "}", + true); + ASSERT_EQUALS("[test.cpp:7]: (style) Iterating over container 'arr' that is always empty.\n", errout.str()); } void checkMutexes() {