diff --git a/simplecpp.cpp b/simplecpp.cpp index d37c0aa7..d45d7f34 100644 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -1700,14 +1700,19 @@ namespace simplecpp { return invalidHashHash(loc, macroName, "Combining '\\"+ tokenA->str()+ "' and '"+ strAB.substr(tokenA->str().size()) + "' yields universal character '\\" + strAB + "'. This is undefined behavior according to C standard chapter 5.1.1.2, paragraph 4."); } }; + + bool expandsTok(const Token *tok) const + { + return expandedToks.find(tok) != expandedToks.end(); + } private: /** Create new token where Token::macro is set for replaced tokens */ Token *newMacroToken(const TokenString &str, const Location &loc, bool replaced, const Token *expandedFromToken=nullptr) const { - Token *tok = new Token(str,loc); + Token * const tok = new Token(str,loc); if (replaced) tok->macro = nameTokDef->str(); if (expandedFromToken) - tok->setExpandedFrom(expandedFromToken, this); + const_cast(this)->addExpandedTok(tok); return tok; } @@ -2199,7 +2204,7 @@ namespace simplecpp { return true; for (const Token *partok = parametertokens[argnr]->next; partok != parametertokens[argnr + 1U];) { const MacroMap::const_iterator it = macros.find(partok->str()); - if (it != macros.end() && !partok->isExpandedFrom(&it->second) && (partok->str() == name() || expandedmacros.find(partok->str()) == expandedmacros.end())) { + if (it != macros.end() && !it->second.expandsTok(partok) && (partok->str() == name() || expandedmacros.find(partok->str()) == expandedmacros.end())) { std::set expandedmacros2(expandedmacros); // temporary amnesia to allow reexpansion of currently expanding macros during argument evaluation expandedmacros2.erase(name()); partok = it->second.expand(output, loc, partok, macros, std::move(expandedmacros2)); @@ -2370,6 +2375,11 @@ namespace simplecpp { return (it != expandedmacros.end()); } + void addExpandedTok(const Token *tok) + { + expandedToks.insert(tok); + } + /** name token in definition */ const Token *nameTokDef; @@ -2403,6 +2413,8 @@ namespace simplecpp { /** was the value of this macro actually defined in the code? */ bool valueDefinedInCode_; + + std::set expandedToks; }; } diff --git a/simplecpp.h b/simplecpp.h index 78609af3..56c7e088 100644 --- a/simplecpp.h +++ b/simplecpp.h @@ -172,16 +172,6 @@ namespace simplecpp { return tok; } - void setExpandedFrom(const Token *tok, const Macro* m) { - mExpandedFrom = tok->mExpandedFrom; - mExpandedFrom.insert(m); - if (tok->whitespaceahead) - whitespaceahead = true; - } - bool isExpandedFrom(const Macro* m) const { - return mExpandedFrom.find(m) != mExpandedFrom.end(); - } - void printAll() const; void printOut() const; private: diff --git a/test.cpp b/test.cpp index 26e3b95b..5fbb9809 100644 --- a/test.cpp +++ b/test.cpp @@ -892,6 +892,14 @@ static void define_define_23() // #403 crash (infinite recursion) ASSERT_EQUALS("\n\n\n\nYdieZ ( void ) ;", preprocess(code)); } +static void define_define_24() +{ + const char code[] = "#define A0(a, b) ((a) + (b))\n" + "#define A1(a, b) ((a) > (b)) ? A0((a) - (b), (b)) : A0((b) - (a), (a))\n" + " A1(a, b);"; + ASSERT_EQUALS("\n\n( ( a ) > ( b ) ) ? ( ( ( a ) - ( b ) ) + ( ( b ) ) ) : ( ( ( b ) - ( a ) ) + ( ( a ) ) ) ;", preprocess(code)); +} + static void define_va_args_1() { const char code[] = "#define A(fmt...) dostuff(fmt)\n" @@ -3382,6 +3390,7 @@ int main(int argc, char **argv) TEST_CASE(define_define_21); TEST_CASE(define_define_22); // #400 TEST_CASE(define_define_23); // #403 - crash, infinite recursion + TEST_CASE(define_define_24); TEST_CASE(define_va_args_1); TEST_CASE(define_va_args_2); TEST_CASE(define_va_args_3);