diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index b778727cf..40cbdbc50 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -26,6 +26,7 @@ #include "symboldatabase.h" #include "templatesimplifier.h" #include "timer.h" +#include "checknullpointer.h" // isUpper #include #include @@ -3447,6 +3448,36 @@ void Tokenizer::removeMacrosInGlobalScope() tok->deleteNext(); } + if (Token::Match(tok, "[;{}] %type% (") && CheckNullPointer::isUpper(tok->next()->str())) { + unsigned int par = 0; + const Token *tok2; + for (tok2 = tok; tok2; tok2 = tok2->next()) { + if (tok2->str() == "(") + ++par; + else if (tok2->str() == ")") { + if (par <= 1) + break; + --par; + } + } + + // remove unknown macros before namespace|class|struct|union + if (Token::Match(tok2, ") namespace|class|struct|union")) { + Token::eraseTokens(tok, tok2->next()); + continue; + } + + // remove unknown macros before foo::foo( + if (Token::Match(tok2, ") %type% :: %type%")) { + const Token *tok3 = tok2->next(); + while (Token::Match(tok3, "%type% :: %type% ::")) + tok3 = tok3->tokAt(2); + if (Token::Match(tok3, "%type% :: %type% (") && tok3->str() == tok3->strAt(2)) + Token::eraseTokens(tok, tok2->next()); + continue; + } + } + if (tok->str() == "{") tok = tok->link(); } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 967aaa88a..3573788a7 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -6514,6 +6514,10 @@ private: ASSERT_EQUALS("void f ( ) { }", tokenizeAndStringify("void f() NOTHROW { }")); ASSERT_EQUALS("struct Foo { } ;", tokenizeAndStringify("struct __declspec(dllexport) Foo {};")); ASSERT_EQUALS("ABA ( ) namespace { }", tokenizeAndStringify("ABA() namespace { }")); + + // #3750 + ASSERT_EQUALS("; foo :: foo ( ) { }", + tokenizeAndStringify("; AB(foo*) foo::foo() { }")); } void multipleAssignment() {