Skip to content

Commit 0fa51dc

Browse files
author
Your Name
committed
Fix test case with recursive scans
1 parent 36e6e12 commit 0fa51dc

2 files changed

Lines changed: 48 additions & 26 deletions

File tree

simplecpp.cpp

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,38 +2090,33 @@ namespace simplecpp {
20902090
}
20912091

20922092
const Token *recursiveExpandToken(TokenList &output, TokenList &temp, const Location &loc, const Token *tok, const MacroMap &macros, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> &parametertokens) const {
2093-
if (!temp.cback() || !temp.cback()->name || !tok->next || tok->next->op != '(') {
2094-
output.takeTokens(temp);
2095-
return tok->next;
2096-
}
2093+
// Loop: the expansion result may itself end with the name of a function-like
2094+
// macro whose arguments are supplied by the tokens that follow it.
2095+
while (true) {
2096+
if (!temp.cback() || !temp.cback()->name || !tok->next || tok->next->op != '(' || !sameline(tok, tok->next))
2097+
break;
20972098

2098-
if (!sameline(tok, tok->next)) {
2099-
output.takeTokens(temp);
2100-
return tok->next;
2101-
}
2099+
const MacroMap::const_iterator it = macros.find(temp.cback()->str());
2100+
if (it == macros.end() || expandedmacros.find(temp.cback()->str()) != expandedmacros.end())
2101+
break;
21022102

2103-
const MacroMap::const_iterator it = macros.find(temp.cback()->str());
2104-
if (it == macros.end() || expandedmacros.find(temp.cback()->str()) != expandedmacros.end()) {
2105-
output.takeTokens(temp);
2106-
return tok->next;
2107-
}
2103+
const Macro &calledMacro = it->second;
2104+
if (!calledMacro.functionLike() || temp.cback()->isExpandedFrom(&calledMacro))
2105+
break;
21082106

2109-
const Macro &calledMacro = it->second;
2110-
if (!calledMacro.functionLike()) {
2107+
TokenList temp2(files);
2108+
temp2.push_back(new Token(temp.cback()->str(), tok->location));
2109+
2110+
const Token * const tok2 = appendTokens(temp2, loc, tok->next, macros, expandedmacros, parametertokens);
2111+
if (!tok2)
2112+
break;
21112113
output.takeTokens(temp);
2112-
return tok->next;
2114+
output.deleteToken(output.back());
2115+
calledMacro.expand(temp, loc, temp2.cfront(), macros, expandedmacros);
2116+
tok = tok2;
21132117
}
2114-
2115-
TokenList temp2(files);
2116-
temp2.push_back(new Token(temp.cback()->str(), tok->location));
2117-
2118-
const Token * const tok2 = appendTokens(temp2, loc, tok->next, macros, expandedmacros, parametertokens);
2119-
if (!tok2)
2120-
return tok->next;
21212118
output.takeTokens(temp);
2122-
output.deleteToken(output.back());
2123-
calledMacro.expand(output, loc, temp2.cfront(), macros, expandedmacros);
2124-
return tok2->next;
2119+
return tok->next;
21252120
}
21262121

21272122
const Token *expandToken(TokenList &output, const Location &loc, const Token *tok, const MacroMap &macros, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> &parametertokens) const {

test.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,31 @@ static void define23() // #40
909909
"unsigned A , B ;", preprocess(code));
910910
}
911911

912+
static void define24()
913+
{
914+
// an expansion result that is a function-like macro name must be rescanned
915+
// repeatedly against the tokens that follow it
916+
const char code[] = "#define a(b, c) c\n"
917+
"#define d() a\n"
918+
"#define g(e) h(e, ) h(e, )\n"
919+
"#define h(e, b) d()(, e)()\n"
920+
"#define i()\n"
921+
"g(i)\n";
922+
ASSERT_EQUALS("", preprocess(code));
923+
}
924+
925+
static void define25()
926+
{
927+
// a macro name that came from expanding that same macro must not be
928+
// re-expanded when rescanned with the tokens that follow it
929+
const char code[] = "#define f() f\n"
930+
"#define wrap(x) x()\n"
931+
"wrap(f())\n";
932+
ASSERT_EQUALS("\n"
933+
"\n"
934+
"f ( )", preprocess(code));
935+
}
936+
912937

913938
static void define_invalid_1()
914939
{
@@ -4096,6 +4121,8 @@ static void runTests(int argc, char **argv, Input input)
40964121
TEST_CASE(define21); // #66
40974122
TEST_CASE(define22); // #40
40984123
TEST_CASE(define23); // #40
4124+
TEST_CASE(define24);
4125+
TEST_CASE(define25);
40994126
TEST_CASE(define_invalid_1);
41004127
TEST_CASE(define_invalid_2);
41014128
TEST_CASE(define_invalid_3);

0 commit comments

Comments
 (0)