From: Chris Lattner Date: Tue, 29 Jan 2008 07:54:23 +0000 (+0000) Subject: Fix a bug where we would incorrectly emit a "cannot paste" error X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=71a3a8d50643c450823d3fbcf3307a3d7db1a265;p=clang Fix a bug where we would incorrectly emit a "cannot paste" error message when handling the GNU ", ## __VA_ARGS__" extension. While I'm at it, flag uses of this as extensions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46503 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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,); +