|
@@ -109,11 +109,12 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|
|
|
|
|
|
|
// save the macro name
|
|
// save the macro name
|
|
|
const int defAtom = atomStrings.getAddAtom(ppToken->name);
|
|
const int defAtom = atomStrings.getAddAtom(ppToken->name);
|
|
|
|
|
+ TSourceLoc defineLoc = ppToken->loc; // because ppToken might go to the next line before we report errors
|
|
|
|
|
|
|
|
// gather parameters to the macro, between (...)
|
|
// gather parameters to the macro, between (...)
|
|
|
token = scanToken(ppToken);
|
|
token = scanToken(ppToken);
|
|
|
- if (token == '(' && ! ppToken->space) {
|
|
|
|
|
- mac.emptyArgs = 1;
|
|
|
|
|
|
|
+ if (token == '(' && !ppToken->space) {
|
|
|
|
|
+ mac.functionLike = 1;
|
|
|
do {
|
|
do {
|
|
|
token = scanToken(ppToken);
|
|
token = scanToken(ppToken);
|
|
|
if (mac.args.size() == 0 && token == ')')
|
|
if (mac.args.size() == 0 && token == ')')
|
|
@@ -123,7 +124,6 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|
|
|
|
|
|
|
return token;
|
|
return token;
|
|
|
}
|
|
}
|
|
|
- mac.emptyArgs = 0;
|
|
|
|
|
const int argAtom = atomStrings.getAddAtom(ppToken->name);
|
|
const int argAtom = atomStrings.getAddAtom(ppToken->name);
|
|
|
|
|
|
|
|
// check for duplication of parameter name
|
|
// check for duplication of parameter name
|
|
@@ -149,7 +149,6 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// record the definition of the macro
|
|
// record the definition of the macro
|
|
|
- TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
|
|
|
|
|
while (token != '\n' && token != EndOfInput) {
|
|
while (token != '\n' && token != EndOfInput) {
|
|
|
mac.body.putToken(token, ppToken);
|
|
mac.body.putToken(token, ppToken);
|
|
|
token = scanToken(ppToken);
|
|
token = scanToken(ppToken);
|
|
@@ -164,7 +163,9 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|
|
// Already defined -- need to make sure they are identical:
|
|
// Already defined -- need to make sure they are identical:
|
|
|
// "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number,
|
|
// "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number,
|
|
|
// ordering, spelling, and white-space separation, where all white-space separations are considered identical."
|
|
// ordering, spelling, and white-space separation, where all white-space separations are considered identical."
|
|
|
- if (existing->args.size() != mac.args.size() || existing->emptyArgs != mac.emptyArgs)
|
|
|
|
|
|
|
+ if (existing->functionLike != mac.functionLike)
|
|
|
|
|
+ parseContext.ppError(defineLoc, "Macro redefined; function-like versus object-like:", "#define", atomStrings.getString(defAtom));
|
|
|
|
|
+ else if (existing->args.size() != mac.args.size())
|
|
|
parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", atomStrings.getString(defAtom));
|
|
parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", atomStrings.getString(defAtom));
|
|
|
else {
|
|
else {
|
|
|
if (existing->args != mac.args)
|
|
if (existing->args != mac.args)
|
|
@@ -1190,14 +1191,20 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b
|
|
|
|
|
|
|
|
TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error
|
|
TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error
|
|
|
in->mac = macro;
|
|
in->mac = macro;
|
|
|
- if (macro->args.size() > 0 || macro->emptyArgs) {
|
|
|
|
|
- int token = scanToken(ppToken);
|
|
|
|
|
|
|
+ if (macro->functionLike) {
|
|
|
|
|
+ // We don't know yet if this will be a successful call of a
|
|
|
|
|
+ // function-like macro; need to look for a '(', but without trashing
|
|
|
|
|
+ // the passed in ppToken, until we know we are no longer speculative.
|
|
|
|
|
+ TPpToken parenToken;
|
|
|
|
|
+ int token = scanToken(&parenToken);
|
|
|
if (newLineOkay) {
|
|
if (newLineOkay) {
|
|
|
while (token == '\n')
|
|
while (token == '\n')
|
|
|
- token = scanToken(ppToken);
|
|
|
|
|
|
|
+ token = scanToken(&parenToken);
|
|
|
}
|
|
}
|
|
|
if (token != '(') {
|
|
if (token != '(') {
|
|
|
- UngetToken(token, ppToken);
|
|
|
|
|
|
|
+ // Function-like macro called with object-like syntax: okay, don't expand.
|
|
|
|
|
+ // (We ate exactly one token that might not be white space; put it back.
|
|
|
|
|
+ UngetToken(token, &parenToken);
|
|
|
delete in;
|
|
delete in;
|
|
|
return MacroExpandNotStarted;
|
|
return MacroExpandNotStarted;
|
|
|
}
|
|
}
|