aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Lex/MacroInfo.h6
-rw-r--r--lib/Lex/MacroInfo.cpp2
-rw-r--r--lib/Lex/PPDirectives.cpp31
-rw-r--r--lib/Lex/PPMacroExpansion.cpp11
-rw-r--r--lib/Serialization/ASTReader.cpp2
-rw-r--r--lib/Serialization/ASTWriter.cpp1
-rw-r--r--test/Preprocessor/macro_fn.c6
7 files changed, 55 insertions, 4 deletions
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index aba77d580d..aeedd735e3 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -76,6 +76,9 @@ class MacroInfo {
/// it has not yet been redefined or undefined.
bool IsBuiltinMacro : 1;
+ /// \brief Whether this macro contains the sequence ", ## __VA_ARGS__"
+ bool HasCommaPasting : 1;
+
/// \brief True if this macro was loaded from an AST file.
bool IsFromAST : 1;
@@ -253,6 +256,9 @@ public:
/// __LINE__, which requires processing before expansion.
bool isBuiltinMacro() const { return IsBuiltinMacro; }
+ bool hasCommaPasting() const { return HasCommaPasting; }
+ void setHasCommaPasting() { HasCommaPasting = true; }
+
/// isFromAST - Return true if this macro was loaded from an AST file.
bool isFromAST() const { return IsFromAST; }
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index 904f04e4f8..d1875c79d0 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -25,6 +25,7 @@ MacroInfo::MacroInfo(SourceLocation DefLoc)
IsC99Varargs(false),
IsGNUVarargs(false),
IsBuiltinMacro(false),
+ HasCommaPasting(false),
IsFromAST(false),
ChangedAfterLoad(false),
IsDisabled(false),
@@ -50,6 +51,7 @@ MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator)
IsC99Varargs(MI.IsC99Varargs),
IsGNUVarargs(MI.IsGNUVarargs),
IsBuiltinMacro(MI.IsBuiltinMacro),
+ HasCommaPasting(MI.HasCommaPasting),
IsFromAST(MI.IsFromAST),
ChangedAfterLoad(MI.ChangedAfterLoad),
IsDisabled(MI.IsDisabled),
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index b7c1846e82..50b161a172 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -1809,7 +1809,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) {
while (Tok.isNot(tok::eod)) {
LastTok = Tok;
- if (Tok.isNot(tok::hash)) {
+ if (Tok.isNot(tok::hash) && Tok.isNot(tok::hashhash)) {
MI->AddTokenToBody(Tok);
// Get the next token of the macro.
@@ -1817,6 +1817,35 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) {
continue;
}
+ if (Tok.is(tok::hashhash)) {
+
+ // If we see token pasting, check if it looks like the gcc comma
+ // pasting extension. We'll use this information to suppress
+ // diagnostics later on.
+
+ // Get the next token of the macro.
+ LexUnexpandedToken(Tok);
+
+ if (Tok.is(tok::eod)) {
+ MI->AddTokenToBody(LastTok);
+ break;
+ }
+
+ unsigned NumTokens = MI->getNumTokens();
+ if (NumTokens && Tok.getIdentifierInfo() == Ident__VA_ARGS__ &&
+ MI->getReplacementToken(NumTokens-1).is(tok::comma))
+ MI->setHasCommaPasting();
+
+ // Things look ok, add the '##' and param name tokens to the macro.
+ MI->AddTokenToBody(LastTok);
+ MI->AddTokenToBody(Tok);
+ LastTok = Tok;
+
+ // Get the next token of the macro.
+ LexUnexpandedToken(Tok);
+ continue;
+ }
+
// Get the next token of the macro.
LexUnexpandedToken(Tok);
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index eee4342e27..de98d5019d 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -619,9 +619,14 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
// Varargs where the named vararg parameter is missing: OK as extension.
// #define A(x, ...)
// A("blah")
- Diag(Tok, diag::ext_missing_varargs_arg);
- Diag(MI->getDefinitionLoc(), diag::note_macro_here)
- << MacroName.getIdentifierInfo();
+ //
+ // If the macro contains the comma pasting extension, the diagnostic
+ // is suppressed; we know we'll get another diagnostic later.
+ if (!MI->hasCommaPasting()) {
+ Diag(Tok, diag::ext_missing_varargs_arg);
+ Diag(MI->getDefinitionLoc(), diag::note_macro_here)
+ << MacroName.getIdentifierInfo();
+ }
// Remember this occurred, allowing us to elide the comma when used for
// cases like:
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index deba302e21..f64962e341 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1141,6 +1141,7 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
// Decode function-like macro info.
bool isC99VarArgs = Record[NextIndex++];
bool isGNUVarArgs = Record[NextIndex++];
+ bool hasCommaPasting = Record[NextIndex++];
MacroArgs.clear();
unsigned NumArgs = Record[NextIndex++];
for (unsigned i = 0; i != NumArgs; ++i)
@@ -1150,6 +1151,7 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
MI->setIsFunctionLike();
if (isC99VarArgs) MI->setIsC99Varargs();
if (isGNUVarArgs) MI->setIsGNUVarargs();
+ if (hasCommaPasting) MI->setHasCommaPasting();
MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
PP.getPreprocessorAllocator());
}
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index a2e8b71123..a34244d3f3 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1855,6 +1855,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Record.push_back(MI->isC99Varargs());
Record.push_back(MI->isGNUVarargs());
+ Record.push_back(MI->hasCommaPasting());
Record.push_back(MI->getNumArgs());
for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
I != E; ++I)
diff --git a/test/Preprocessor/macro_fn.c b/test/Preprocessor/macro_fn.c
index f93d52c7ed..8ac9ed9a24 100644
--- a/test/Preprocessor/macro_fn.c
+++ b/test/Preprocessor/macro_fn.c
@@ -44,3 +44,9 @@ one_dot() /* empty first argument, elided ...: expected-warning {{must specify
#define E() (i == 0)
#if E
#endif
+
+
+/* <rdar://problem/12292192> */
+#define NSAssert(condition, desc, ...) /* expected-warning {{variadic macros are a C99 feature}} */ \
+ SomeComplicatedStuff((desc), ##__VA_ARGS__) /* expected-warning {{token pasting of ',' and __VA_ARGS__ is a GNU extension}} */
+NSAssert(somecond, somedesc)