summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/Lex/Preprocessor.cpp21
-rw-r--r--clang/include/clang/Lex/LexerToken.h7
2 files changed, 24 insertions, 4 deletions
diff --git a/clang/Lex/Preprocessor.cpp b/clang/Lex/Preprocessor.cpp
index 1a95b887f39..b614785dd83 100644
--- a/clang/Lex/Preprocessor.cpp
+++ b/clang/Lex/Preprocessor.cpp
@@ -147,6 +147,8 @@ void Preprocessor::DumpToken(const LexerToken &Tok, bool DumpFlags) const {
std::cerr << " [StartOfLine]";
if (Tok.hasLeadingSpace())
std::cerr << " [LeadingSpace]";
+ if (Tok.isExpandDisabled())
+ std::cerr << " [ExpandDisabled]";
if (Tok.needsCleaning()) {
const char *Start = SourceMgr.getCharacterData(Tok.getLocation());
std::cerr << " [UnClean='" << std::string(Start, Start+Tok.getLength())
@@ -675,6 +677,11 @@ bool Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
SourceMgr.getInstantiationLoc(Identifier.getLocation(), InstantiateLoc);
Identifier.SetLocation(Loc);
+ // If this is #define X X, we must mark the result as unexpandible.
+ if (IdentifierInfo *NewII = Identifier.getIdentifierInfo())
+ if (NewII->getMacroInfo() == MI)
+ Identifier.SetFlag(LexerToken::DisableExpand);
+
// Since this is not an identifier token, it can't be macro expanded, so
// we're done.
++NumFastMacroExpanded;
@@ -998,9 +1005,17 @@ void Preprocessor::HandleIdentifier(LexerToken &Identifier) {
// If this is a macro to be expanded, do it.
if (MacroInfo *MI = II.getMacroInfo())
- if (MI->isEnabled() && !DisableMacroExpansion)
- if (!HandleMacroExpandedIdentifier(Identifier, MI))
- return;
+ if (!DisableMacroExpansion && !Identifier.isExpandDisabled()) {
+ if (MI->isEnabled()) {
+ if (!HandleMacroExpandedIdentifier(Identifier, MI))
+ return;
+ } else {
+ // C99 6.10.3.4p2 says that a disabled macro may never again be
+ // expanded, even if it's in a context where it could be expanded in the
+ // future.
+ Identifier.SetFlag(LexerToken::DisableExpand);
+ }
+ }
// Change the kind of this identifier to the appropriate token kind, e.g.
// turning "for" into a keyword.
diff --git a/clang/include/clang/Lex/LexerToken.h b/clang/include/clang/Lex/LexerToken.h
index 94793706a0c..1816b9d18a4 100644
--- a/clang/include/clang/Lex/LexerToken.h
+++ b/clang/include/clang/Lex/LexerToken.h
@@ -47,7 +47,8 @@ public:
enum TokenFlags {
StartOfLine = 0x01, // At start of line or only after whitespace.
LeadingSpace = 0x02, // Whitespace exists before this token.
- NeedsCleaning = 0x04 // Contained an escaped newline or trigraph.
+ DisableExpand = 0x04, // This identifier may never be macro expanded.
+ NeedsCleaning = 0x08 // Contained an escaped newline or trigraph.
};
tok::TokenKind getKind() const { return Kind; }
@@ -100,6 +101,10 @@ public:
///
bool hasLeadingSpace() const { return Flags & LeadingSpace; }
+ /// isExpandDisabled - Return true if this identifier token should never
+ /// be expanded in the future, due to C99 6.10.3.4p2.
+ bool isExpandDisabled() const { return Flags & DisableExpand; }
+
/// needsCleaning - Return true if this token has trigraphs or escaped
/// newlines in it.
///
OpenPOWER on IntegriCloud