From bc98f4224b4ae2f4e0cc59ddca11972c203fdba6 Mon Sep 17 00:00:00 2001 From: datadiode Date: Wed, 28 Aug 2024 07:34:10 +0200 Subject: [PATCH] Allow reexpansion of currently expanding macros during argument evaluation. This fixes #31 as reproduced in TEST_CASE(define_define_11) without breaking code from @ydamigos's comment to #225 as reproduced in TEST_CASE(define_define_11a). --- simplecpp.cpp | 33 ++++++--------------------------- test.cpp | 12 ++++++++++++ 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index 3cce780..5a32740 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -102,8 +102,6 @@ static const simplecpp::TokenString ONCE("once"); static const simplecpp::TokenString HAS_INCLUDE("__has_include"); -static const simplecpp::TokenString INNER_COMMA(",,"); - template static std::string toString(T t) { // NOLINTNEXTLINE(misc-const-correctness) - false positive @@ -1622,10 +1620,6 @@ namespace simplecpp { rawtok = rawtok2->next; } output->takeTokens(output2); - for (Token* tok = output->front(); tok; tok = tok->next) { - if (tok->str() == INNER_COMMA) - tok->setstr(","); - } return rawtok; } @@ -1795,25 +1789,9 @@ namespace simplecpp { tok = expandHash(tokens, rawloc, tok, macros, expandedmacros, parametertokens); } else { if (!expandArg(tokens, tok, rawloc, macros, expandedmacros, parametertokens)) { - bool expanded = false; - const MacroMap::const_iterator it = macros.find(tok->str()); - if (it != macros.end() && expandedmacros.find(tok->str()) == expandedmacros.end()) { - const Macro &m = it->second; - if (!m.functionLike()) { - Token* mtok = tokens->back(); - m.expand(tokens, rawloc, tok, macros, expandedmacros); - for (mtok = mtok->next; mtok; mtok = mtok->next) { - if (mtok->op == ',') - mtok->setstr(INNER_COMMA); - } - expanded = true; - } - } - if (!expanded) { - tokens->push_back(new Token(*tok)); - if (tok->macro.empty() && (par > 0 || tok->str() != "(")) - tokens->back()->macro = name(); - } + tokens->push_back(new Token(*tok)); + if (tok->macro.empty() && (par > 0 || tok->str() != "(")) + tokens->back()->macro = name(); } if (tok->op == '(') @@ -2138,9 +2116,10 @@ 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() && !partok->isExpandedFrom(&it->second) && (partok->str() == name() || expandedmacros.find(partok->str()) == expandedmacros.end())) { + std::set expandedmacros; // temporary amnesia to allow reexpansion of currently expanding macros during argument evaluation partok = it->second.expand(output, loc, partok, macros, expandedmacros); - else { + } else { output->push_back(newMacroToken(partok->str(), loc, isReplaced(expandedmacros), partok)); output->back()->macro = partok->macro; partok = partok->next; diff --git a/test.cpp b/test.cpp index d00658a..3e857b2 100644 --- a/test.cpp +++ b/test.cpp @@ -717,6 +717,17 @@ static void define_define_11() ASSERT_EQUALS("\n\n\n\nP2DIR ;", preprocess(code)); } +static void define_define_11a() +{ + const char code[] = "#define A_B_C 0x1\n" + "#define A_ADDRESS 0x00001000U\n" + "#define A ((uint32_t ) A_ADDRESS)\n" + "#define CONCAT(x, y, z) x ## _ ## y ## _ ## z\n" + "#define TEST_MACRO CONCAT(A, B, C)\n" + "TEST_MACRO\n"; + ASSERT_EQUALS("\n\n\n\n\n0x1", preprocess(code)); +} + static void define_define_12() { const char code[] = "#define XY(Z) Z\n" @@ -2855,6 +2866,7 @@ int main(int argc, char **argv) TEST_CASE(define_define_9); // line break in nested macro call TEST_CASE(define_define_10); TEST_CASE(define_define_11); + TEST_CASE(define_define_11a); TEST_CASE(define_define_12); // expand result of ## TEST_CASE(define_define_13); TEST_CASE(define_define_14);