Fix double expansion of macro arguments.

This adds a new fullyExpanded flag that makes sure that macro arguments
only get expanded once. This can happen either in PrescanMacroArg, or, if
there is token pasting or a function-like macro name has been passed as
an argument and may need to be expanded when used as a function.
This commit is contained in:
Arcady Goldmints-Orlov 2023-02-23 11:01:37 -05:00 committed by arcady-lunarg
parent 14e5a04e70
commit c43008e829
6 changed files with 39 additions and 15 deletions

View file

@ -102,6 +102,7 @@ public:
i64val = 0;
loc.init();
name[0] = 0;
fullyExpanded = false;
}
// Used for comparing macro definitions, so checks what is relevant for that.
@ -117,6 +118,8 @@ public:
// True if a space (for white space or a removed comment) should also be
// recognized, in front of the token returned:
bool space;
bool fullyExpanded;
// Numeric value of the token:
union {
int ival;
@ -475,16 +478,27 @@ protected:
//
// From PpTokens.cpp
//
void pushTokenStreamInput(TokenStream&, bool pasting = false);
void pushTokenStreamInput(TokenStream&, bool pasting = false, bool expanded = false);
void UngetToken(int token, TPpToken*);
class tTokenInput : public tInput {
public:
tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) :
tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting, bool expanded) :
tInput(pp),
tokens(t),
lastTokenPastes(prepasting) { }
virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); }
lastTokenPastes(prepasting),
preExpanded(expanded) { }
virtual int scan(TPpToken *ppToken) override {
int token = tokens->getToken(pp->parseContext, ppToken);
ppToken->fullyExpanded = preExpanded;
if (tokens->atEnd() && token == PpAtomIdentifier) {
int macroAtom = pp->atomStrings.getAtom(ppToken->name);
MacroSymbol* macro = macroAtom == 0 ? nullptr : pp->lookupMacroDef(macroAtom);
if (macro && macro->functionLike)
ppToken->fullyExpanded = false;
}
return token;
}
virtual int getch() override { assert(0); return EndOfInput; }
virtual void ungetch() override { assert(0); }
virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); }
@ -492,6 +506,7 @@ protected:
protected:
TokenStream* tokens;
bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token
bool preExpanded;
};
class tUngotTokenInput : public tInput {