diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 375330487..34c02870a 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -24,6 +24,7 @@ #include "settings.h" #include "errorlogger.h" #include "check.h" +#include "checknullpointer.h" // isUpper #include #include @@ -95,6 +96,34 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti tok = tok2; } + // Namespace and unknown macro (#3854) + else if (Token::Match(tok, "namespace %var% %type% (") && + _tokenizer->isCPP() && + CheckNullPointer::isUpper(tok->strAt(2)) && + Token::simpleMatch(tok->linkAt(3), ") {")) { + scopeList.push_back(Scope(this, tok, scope)); + + Scope *new_scope = &scopeList.back(); + access[new_scope] = Public; + + const Token *tok2 = tok->linkAt(3)->next(); + + new_scope->classStart = tok2; + new_scope->classEnd = tok2->link(); + + // make sure we have valid code + if (!new_scope->classEnd) { + scopeList.pop_back(); + break; + } + + // make the new scope the current scope + scope = &scopeList.back(); + scope->nestedIn->nestedList.push_back(scope); + + tok = tok2; + } + // forward declaration else if (Token::Match(tok, "class|struct %var% ;")) { // fill the classAndStructTypes set.. diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 1c0eca125..5d8da391d 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -114,6 +114,7 @@ private: TEST_CASE(namespaces1); TEST_CASE(namespaces2); + TEST_CASE(namespaces3); // #3854 - unknown macro TEST_CASE(tryCatch1); @@ -865,6 +866,13 @@ private: ASSERT_EQUALS(true, function->hasBody); } + void namespaces3() { // #3854 - namespace with unknown macro + GET_SYMBOL_DB("namespace fred UNKNOWN_MACRO(default) {\n" + "}\n"); + ASSERT_EQUALS(2U, db->scopeList.size()); + ASSERT_EQUALS(Scope::eGlobal, db->scopeList.front().type); + ASSERT_EQUALS(Scope::eNamespace, db->scopeList.back().type); + } void tryCatch1() { const std::string str("void foo() {\n"