diff options
| author | Ehsan Akhgari <ehsan.akhgari@gmail.com> | 2016-01-22 19:26:44 +0000 |
|---|---|---|
| committer | Ehsan Akhgari <ehsan.akhgari@gmail.com> | 2016-01-22 19:26:44 +0000 |
| commit | 34461a626e4fcc72e2facf7dedf8c84cf13e39d2 (patch) | |
| tree | 7000fb233aed24e6e36faca36a59a0b00e22d620 | |
| parent | acc43d197d7986f4749eeeb85a4c76caa870d452 (diff) | |
| download | bcm5719-llvm-34461a626e4fcc72e2facf7dedf8c84cf13e39d2.tar.gz bcm5719-llvm-34461a626e4fcc72e2facf7dedf8c84cf13e39d2.zip | |
[MSVC Compat] Accept elided commas in macro function arguments
Summary:
This fixes PR25875. When the trailing comma in a macro argument list is
elided, we need to treat it similarly to the case where a variadic macro
misses one actual argument.
Reviewers: rnk, rsmith
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D15670
llvm-svn: 258530
| -rw-r--r-- | clang/include/clang/Lex/Token.h | 6 | ||||
| -rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Lex/TokenLexer.cpp | 17 | ||||
| -rw-r--r-- | clang/test/Preprocessor/microsoft-ext.c | 9 |
4 files changed, 32 insertions, 7 deletions
diff --git a/clang/include/clang/Lex/Token.h b/clang/include/clang/Lex/Token.h index 7ba22b2f626..d34f1cf9ee9 100644 --- a/clang/include/clang/Lex/Token.h +++ b/clang/include/clang/Lex/Token.h @@ -85,6 +85,7 @@ public: IgnoredComma = 0x80, // This comma is not a macro argument separator (MS). StringifiedInMacro = 0x100, // This string or character literal is formed by // macro stringizing or charizing operator. + CommaAfterElided = 0x200, // The comma following this token was elided (MS). }; tok::TokenKind getKind() const { return Kind; } @@ -297,6 +298,11 @@ public: bool stringifiedInMacro() const { return (Flags & StringifiedInMacro) ? true : false; } + + /// Returns true if the comma after this token was elided. + bool commaAfterElided() const { + return (Flags & CommaAfterElided) ? true : false; + } }; /// \brief Information about the conditional stack (\#if directives) diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 18348df0a39..11b4a0b3d8c 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -723,6 +723,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // heap allocations in the common case. SmallVector<Token, 64> ArgTokens; bool ContainsCodeCompletionTok = false; + bool FoundElidedComma = false; SourceLocation TooManyArgsLoc; @@ -765,6 +766,10 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // If we found the ) token, the macro arg list is done. if (NumParens-- == 0) { MacroEnd = Tok.getLocation(); + if (!ArgTokens.empty() && + ArgTokens.back().commaAfterElided()) { + FoundElidedComma = true; + } break; } } else if (Tok.is(tok::l_paren)) { @@ -909,7 +914,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // then we have an empty "()" argument empty list. This is fine, even if // the macro expects one argument (the argument is just empty). isVarargsElided = MI->isVariadic(); - } else if (MI->isVariadic() && + } else if ((FoundElidedComma || MI->isVariadic()) && (NumActuals+1 == MinArgsExpected || // A(x, ...) -> A(X) (NumActuals == 0 && MinArgsExpected == 2))) {// A(x,...) -> A() // Varargs where the named vararg parameter is missing: OK as extension. diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index ed2b8cdabd1..3f66b7f9b76 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -154,12 +154,17 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs( // Remove the comma. ResultToks.pop_back(); - // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"), - // then removal of the comma should produce a placemarker token (in C99 - // terms) which we model by popping off the previous ##, giving us a plain - // "X" when __VA_ARGS__ is empty. - if (!ResultToks.empty() && ResultToks.back().is(tok::hashhash)) - ResultToks.pop_back(); + if (!ResultToks.empty()) { + // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"), + // then removal of the comma should produce a placemarker token (in C99 + // terms) which we model by popping off the previous ##, giving us a plain + // "X" when __VA_ARGS__ is empty. + if (ResultToks.back().is(tok::hashhash)) + ResultToks.pop_back(); + + // Remember that this comma was elided. + ResultToks.back().setFlag(Token::CommaAfterElided); + } // Never add a space, even if the comma, ##, or arg had a space. NextTokGetsSpace = false; diff --git a/clang/test/Preprocessor/microsoft-ext.c b/clang/test/Preprocessor/microsoft-ext.c index b03f6775429..cb3cf4f1537 100644 --- a/clang/test/Preprocessor/microsoft-ext.c +++ b/clang/test/Preprocessor/microsoft-ext.c @@ -34,3 +34,12 @@ ACTION_TEMPLATE(InvokeArgument, MAKE_FUNC(MAK, ER, int a, _COMMA, int b); // CHECK: void func(int a , int b) {} + +#define macro(a, b) (a - b) +void function(int a); +#define COMMA_ELIDER(...) \ + macro(x, __VA_ARGS__); \ + function(x, __VA_ARGS__); +COMMA_ELIDER(); +// CHECK: (x - ); +// CHECK: function(x); |

