diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 60673fad7..44e856b10 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1593,6 +1593,9 @@ bool Tokenizer::tokenize(std::istream &code, } } + // remove MACRO in variable declaration: MACRO int x; + removeMacroInVarDecl(); + // Combine wide strings for (Token *tok = list.front(); tok; tok = tok->next()) { while (tok->str() == "L" && tok->next() && tok->next()->type() == Token::eString) { @@ -3475,6 +3478,35 @@ void Tokenizer::removeMacrosInGlobalScope() } //--------------------------------------------------------------------------- +void Tokenizer::removeMacroInVarDecl() +{ + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "[;{}] %var% (") && tok->next()->isUpperCaseName()) { + // goto ')' paranthesis + const Token *tok2 = tok; + int parlevel = 0; + while (tok2) { + if (tok2->str() == "(") + ++parlevel; + else if (tok2->str() == ")") { + if (--parlevel <= 0) + break; + } + tok2 = tok2->next(); + } + tok2 = tok2 ? tok2->next() : NULL; + + // check if this is a variable declaration.. + const Token *tok3 = tok2; + while (tok3 && tok3->isUpperCaseName()) + tok3 = tok3->next(); + if (tok3 && (tok3->isStandardType() || Token::Match(tok3,"const|static|struct|union|class"))) + Token::eraseTokens(tok,tok2); + } + } +} +//--------------------------------------------------------------------------- + void Tokenizer::removeRedundantAssignment() { for (Token *tok = list.front(); tok; tok = tok->next()) { diff --git a/lib/tokenize.h b/lib/tokenize.h index 002ddcf77..0b561a0d3 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -172,6 +172,9 @@ public: /** Remove macros in global scope */ void removeMacrosInGlobalScope(); + /** Remove unknown macro in variable declarations: PROGMEM char x; */ + void removeMacroInVarDecl(); + /** Remove redundant assignment */ void removeRedundantAssignment(); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 3f6eca46e..f34053068 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -442,6 +442,7 @@ private: // Some simple cleanups of unhandled macros in the global scope TEST_CASE(removeMacrosInGlobalScope); + TEST_CASE(removeMacroInVarDecl); // a = b = 0; TEST_CASE(multipleAssignment); @@ -7031,6 +7032,19 @@ private: tokenizeAndStringify("; CONST struct ABC abc ;")); } + void removeMacroInVarDecl() { // #4304 + // only remove macros with parentheses (those hurt most) + ASSERT_EQUALS("void f ( ) { PROGMEM int x ; }", tokenizeAndStringify("void f() { PROGMEM int x ; }")); + ASSERT_EQUALS("void f ( ) { int x ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") int x ; }")); + + // various variable declarations + ASSERT_EQUALS("void f ( ) { CONST int x ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") CONST int x ; }")); + ASSERT_EQUALS("void f ( ) { char a [ 4 ] ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") char a[4]; }")); + ASSERT_EQUALS("void f ( ) { const char a [ 4 ] ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") const char a[4]; }")); + ASSERT_EQUALS("void f ( ) { struct ABC abc ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") struct ABC abc; }")); + ASSERT_EQUALS("void f ( ) { CONST struct ABC abc ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") CONST struct ABC abc; }")); + } + void multipleAssignment() { ASSERT_EQUALS("a = b = 0 ;", tokenizeAndStringify("a=b=0;")); }