diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 19d92ce06..6c1a7e309 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9309,6 +9309,7 @@ void Tokenizer::reportUnknownMacros() } // Report unknown macros in non-executable scopes.. + std::set possible; for (const Token *tok = tokens(); tok; tok = tok->next()) { // Skip executable scopes.. if (tok->str() == "{") { @@ -9317,7 +9318,10 @@ void Tokenizer::reportUnknownMacros() prev = prev->previous(); if (prev && prev->str() == ")") tok = tok->link(); - } + else + possible.clear(); + } else if (tok->str() == "}") + possible.clear(); if (Token::Match(tok, "%name% (") && tok->isUpperCaseName() && Token::simpleMatch(tok->linkAt(1), ") (") && Token::simpleMatch(tok->linkAt(1)->linkAt(1), ") {")) { // A keyword is not an unknown macro @@ -9330,6 +9334,11 @@ void Tokenizer::reportUnknownMacros() if (Token::Match(tok2, "if|switch|for|while|return")) unknownMacroError(tok); } + } else if (Token::Match(tok, "%name% (") && tok->isUpperCaseName() && Token::Match(tok->linkAt(1), ") %name% (") && Token::Match(tok->linkAt(1)->linkAt(2), ") [;{]")) { + if (possible.count(tok->str()) == 0) + possible.insert(tok->str()); + else + unknownMacroError(tok); } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index fc89094cf..30959a316 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -7988,6 +7988,12 @@ private: const char code3[] = "f(\"1\" __stringify(48) \"1\");"; ASSERT_THROW(tokenizeAndStringify(code3), InternalError); + + const char code4[] = "struct Foo {\n" + " virtual MACRO(int) f1() {}\n" + " virtual MACRO(int) f2() {}\n" + "};"; + ASSERT_THROW(tokenizeAndStringify(code4), InternalError); } void findGarbageCode() { // Test Tokenizer::findGarbageCode()