diff options
-rw-r--r-- | Lex/MacroExpander.cpp | 17 | ||||
-rw-r--r-- | test/Preprocessor/macro_paste_commaext.c | 13 |
2 files changed, 29 insertions, 1 deletions
diff --git a/Lex/MacroExpander.cpp b/Lex/MacroExpander.cpp index 8dbec64330..9d4b07216a 100644 --- a/Lex/MacroExpander.cpp +++ b/Lex/MacroExpander.cpp @@ -409,6 +409,19 @@ void MacroExpander::ExpandFunctionArguments() { const Token *ArgToks = ActualArgs->getUnexpArgument(ArgNo); unsigned NumToks = MacroArgs::getArgLength(ArgToks); if (NumToks) { // Not an empty argument? + // If this is the GNU ", ## __VA_ARG__" extension, and we just learned + // that __VA_ARG__ expands to multiple tokens, avoid a pasting error when + // the expander trys to paste ',' with the first token of the __VA_ARG__ + // expansion. + if (PasteBefore && ResultToks.size() >= 2 && + ResultToks[ResultToks.size()-2].is(tok::comma) && + (unsigned)ArgNo == Macro->getNumArgs()-1 && + Macro->isVariadic()) { + // Remove the paste operator, report use of the extension. + PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma); + ResultToks.pop_back(); + } + ResultToks.append(ArgToks, ArgToks+NumToks); // If the next token was supposed to get leading whitespace, ensure it has @@ -447,6 +460,8 @@ void MacroExpander::ExpandFunctionArguments() { !ResultToks.empty() && ResultToks.back().is(tok::comma)) { // Never add a space, even if the comma, ##, or arg had a space. NextTokGetsSpace = false; + // Remove the paste operator, report use of the extension. + PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma); ResultToks.pop_back(); } continue; @@ -615,7 +630,7 @@ void MacroExpander::PasteTokens(Token &Tok) { // Turn ## into 'other' to avoid # ## # from looking like a paste operator. if (Result.is(tok::hashhash)) Result.setKind(tok::unknown); - // FIXME: Turn __VARRGS__ into "not a token"? + // FIXME: Turn __VA_ARGS__ into "not a token"? // Transfer properties of the LHS over the the Result. Result.setFlagValue(Token::StartOfLine , Tok.isAtStartOfLine()); diff --git a/test/Preprocessor/macro_paste_commaext.c b/test/Preprocessor/macro_paste_commaext.c new file mode 100644 index 0000000000..0fcd90d68d --- /dev/null +++ b/test/Preprocessor/macro_paste_commaext.c @@ -0,0 +1,13 @@ +// RUN: clang %s -E | grep 'V);' && +// RUN: clang %s -E | grep 'W, 1, 2);' +// RUN: clang %s -E | grep 'X, 1, 2);' +// RUN: clang %s -E | grep 'Y, );' +// RUN: clang %s -E | grep 'Z, );' + +#define debug(format, ...) format, ## __VA_ARGS__) +debug(V); +debug(W, 1, 2); +debug(X, 1, 2 ); +debug(Y, ); +debug(Z,); + |