From f99e83ece060aed66278e47557fe19abe3e77a35 Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Sat, 12 Oct 2019 05:39:14 -0400 Subject: [PATCH] Fix #9411 (new daca crash related to using namespace) (#2264) --- lib/symboldatabase.cpp | 19 +++++++++++++++-- lib/tokenize.cpp | 2 +- test/testsymboldatabase.cpp | 42 +++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 54668f038..65c9942c0 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2030,8 +2030,23 @@ static bool usingNamespace(const Scope *scope, const Token *first, const Token * if (offset) { while (scope) { for (const auto & info : scope->usingList) { - if (name == qualifiedName(info.scope)) - return true; + if (info.scope) { + if (name == qualifiedName(info.scope)) + return true; + } + // no scope so get name from using + else { + const Token *start = info.start->tokAt(2); + std::string nsName; + while (start && start->str() != ";") { + if (!nsName.empty()) + nsName += " "; + nsName += start->str(); + start = start->next(); + } + if (nsName == name) + return true; + } } scope = scope->nestedIn; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 2b3df5086..fc0a73729 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2877,7 +2877,7 @@ void Tokenizer::calculateScopes() if (Token::Match(tok, "using namespace %name% ::|<|;")) { std::string usingNamespaceName; for (const Token* namespaceNameToken = tok->tokAt(2); - !Token::simpleMatch(namespaceNameToken, ";"); + namespaceNameToken && namespaceNameToken->str() != ";"; namespaceNameToken = namespaceNameToken->next()) { usingNamespaceName += namespaceNameToken->str(); usingNamespaceName += " "; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index e0808027f..514923c57 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -303,6 +303,7 @@ private: TEST_CASE(symboldatabase78); // #9147 TEST_CASE(symboldatabase79); // #9392 TEST_CASE(symboldatabase80); // #9389 + TEST_CASE(symboldatabase81); // #9411 TEST_CASE(createSymbolDatabaseFindAllScopes1); @@ -4349,6 +4350,47 @@ private: } } + void symboldatabase81() { // #9411 + { + GET_SYMBOL_DB("namespace Terminal {\n" + " class Complete {\n" + " public:\n" + " std::string act(const Parser::Action *act);\n" + " };\n" + "}\n" + "using namespace std;\n" + "using namespace Parser;\n" + "using namespace Terminal;\n" + "string Complete::act(const Action *act) { }"); + ASSERT(db->scopeList.size() == 4); + ASSERT(db->functionScopes.size() == 1); + const Scope *scope = db->findScopeByName("Complete"); + ASSERT(scope); + ASSERT(scope->functionList.size() == 1); + ASSERT(scope->functionList.front().name() == "act"); + ASSERT(scope->functionList.front().hasBody() == true); + } + { + GET_SYMBOL_DB("namespace Terminal {\n" + " class Complete {\n" + " public:\n" + " std::string act(const Foo::Parser::Action *act);\n" + " };\n" + "}\n" + "using namespace std;\n" + "using namespace Foo::Parser;\n" + "using namespace Terminal;\n" + "string Complete::act(const Action *act) { }"); + ASSERT(db->scopeList.size() == 4); + ASSERT(db->functionScopes.size() == 1); + const Scope *scope = db->findScopeByName("Complete"); + ASSERT(scope); + ASSERT(scope->functionList.size() == 1); + ASSERT(scope->functionList.front().name() == "act"); + ASSERT(scope->functionList.front().hasBody() == true); + } + } + void createSymbolDatabaseFindAllScopes1() { GET_SYMBOL_DB("void f() { union {int x; char *p;} a={0}; }"); ASSERT(db->scopeList.size() == 3);