summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-08-30 13:38:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-08-30 13:38:46 +0000
commitc30981a563a8947cb26b1e308d122fa2ef90fceb (patch)
treebe7c0367d7be45d668115cc556982c847b875867
parent3bc22262af7b09a459b400976cfce3d9318b8ea9 (diff)
downloadclang-c30981a563a8947cb26b1e308d122fa2ef90fceb.tar.gz
clang-c30981a563a8947cb26b1e308d122fa2ef90fceb.tar.bz2
clang-c30981a563a8947cb26b1e308d122fa2ef90fceb.tar.xz
Make preprocessor act in a GCC-compatible fashion when a macro is redefined
within its own argument list. The original definition is used for the immediate expansion, but the new definition is used for any subsequent occurences within the argument list or after the expansion. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162906 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Lex/Preprocessor.h3
-rw-r--r--include/clang/Lex/TokenLexer.h11
-rw-r--r--lib/Lex/PPLexerChange.cpp6
-rw-r--r--lib/Lex/PPMacroExpansion.cpp2
-rw-r--r--lib/Lex/TokenLexer.cpp5
-rw-r--r--test/Preprocessor/macro_arg_directive.c7
6 files changed, 22 insertions, 12 deletions
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index adc6b240e9..053200de5b 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -569,7 +569,8 @@ public:
///
/// ILEnd specifies the location of the ')' for a function-like macro or the
/// identifier for an object-like macro.
- void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroArgs *Args);
+ void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroInfo *Macro,
+ MacroArgs *Args);
/// EnterTokenStream - Add a "macro" context to the top of the include stack,
/// which will cause the lexer to start returning the specified tokens.
diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h
index 1330ad5f31..6f11e126e9 100644
--- a/include/clang/Lex/TokenLexer.h
+++ b/include/clang/Lex/TokenLexer.h
@@ -22,7 +22,7 @@ namespace clang {
class Token;
class MacroArgs;
-/// TokenLexer - This implements a lexer that returns token from a macro body
+/// TokenLexer - This implements a lexer that returns tokens from a macro body
/// or token stream instead of lexing from a character buffer. This is used for
/// macro expansion and _Pragma handling, for example.
///
@@ -98,17 +98,18 @@ public:
/// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
/// ILEnd specifies the location of the ')' for a function-like macro or the
/// identifier for an object-like macro.
- TokenLexer(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs,
- Preprocessor &pp)
+ TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI,
+ MacroArgs *ActualArgs, Preprocessor &pp)
: Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) {
- Init(Tok, ILEnd, ActualArgs);
+ Init(Tok, ILEnd, MI, ActualArgs);
}
/// Init - Initialize this TokenLexer to expand from the specified macro
/// with the specified argument information. Note that this ctor takes
/// ownership of the ActualArgs pointer. ILEnd specifies the location of the
/// ')' for a function-like macro or the identifier for an object-like macro.
- void Init(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs);
+ void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI,
+ MacroArgs *ActualArgs);
/// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is
/// specified, this takes ownership of the tokens and delete[]'s them when
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index e824320cf7..d827f58a48 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -157,15 +157,15 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer.
void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd,
- MacroArgs *Args) {
+ MacroInfo *Macro, MacroArgs *Args) {
PushIncludeMacroStack();
CurDirLookup = 0;
if (NumCachedTokenLexers == 0) {
- CurTokenLexer.reset(new TokenLexer(Tok, ILEnd, Args, *this));
+ CurTokenLexer.reset(new TokenLexer(Tok, ILEnd, Macro, Args, *this));
} else {
CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
- CurTokenLexer->Init(Tok, ILEnd, Args);
+ CurTokenLexer->Init(Tok, ILEnd, Macro, Args);
}
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_TokenLexer;
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 3f27236cac..5c5bc00fe2 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -341,7 +341,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
}
// Start expanding the macro.
- EnterMacro(Identifier, ExpansionEnd, Args);
+ EnterMacro(Identifier, ExpansionEnd, MI, Args);
// Now that the macro is at the top of the include stack, ask the
// preprocessor to read the next token from it.
diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp
index ade40dad77..819bb3f43e 100644
--- a/lib/Lex/TokenLexer.cpp
+++ b/lib/Lex/TokenLexer.cpp
@@ -23,12 +23,13 @@ using namespace clang;
/// Create a TokenLexer for the specified macro with the specified actual
/// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
-void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroArgs *Actuals) {
+void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI,
+ MacroArgs *Actuals) {
// If the client is reusing a TokenLexer, make sure to free any memory
// associated with it.
destroy();
- Macro = PP.getMacroInfo(Tok.getIdentifierInfo());
+ Macro = MI;
ActualArgs = Actuals;
CurToken = 0;
diff --git a/test/Preprocessor/macro_arg_directive.c b/test/Preprocessor/macro_arg_directive.c
index 5c9943d605..5bc2236f0c 100644
--- a/test/Preprocessor/macro_arg_directive.c
+++ b/test/Preprocessor/macro_arg_directive.c
@@ -1,5 +1,12 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify
+#define a(x) enum { x }
+a(n =
+#undef a
+#define a 5
+ a);
+_Static_assert(n == 5, "");
+
// header1.h
void fail(const char *);
#define MUNCH(...) \