forked from OSchip/llvm-project
[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
This commit is contained in:
parent
acc43d197d
commit
34461a626e
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue