aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Lex/PPExpressions.cpp23
-rw-r--r--test/Preprocessor/macro_fn_disable_expand.c20
2 files changed, 41 insertions, 2 deletions
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index 6422752ae9..2a6b2a7294 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -72,8 +72,8 @@ struct DefinedTracker {
};
/// EvaluateDefined - Process a 'defined(sym)' expression.
-static bool EvaluateDefined(PPValue &Result, Token &PeekTok,
- DefinedTracker &DT, bool ValueLive, Preprocessor &PP) {
+static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
+ bool ValueLive, Preprocessor &PP) {
IdentifierInfo *II;
Result.setBegin(PeekTok.getLocation());
@@ -676,6 +676,15 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
/// to "!defined(X)" return X in IfNDefMacro.
bool Preprocessor::
EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
+ // Save the current state of 'DisableMacroExpansion' and reset it to false. If
+ // 'DisableMacroExpansion' is true, then we must be in a macro argument list
+ // in which case a directive is undefined behavior. We want macros to be able
+ // to recursively expand in order to get more gcc-list behavior, so we force
+ // DisableMacroExpansion to false and restore it when we're done parsing the
+ // expression.
+ bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
+ DisableMacroExpansion = false;
+
// Peek ahead one token.
Token Tok;
Lex(Tok);
@@ -689,6 +698,9 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// Parse error, skip the rest of the macro line.
if (Tok.isNot(tok::eom))
DiscardUntilEndOfDirective();
+
+ // Restore 'DisableMacroExpansion'.
+ DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return false;
}
@@ -701,6 +713,8 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
if (DT.State == DefinedTracker::NotDefinedMacro)
IfNDefMacro = DT.TheMacro;
+ // Restore 'DisableMacroExpansion'.
+ DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return ResVal.Val != 0;
}
@@ -711,6 +725,9 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// Parse error, skip the rest of the macro line.
if (Tok.isNot(tok::eom))
DiscardUntilEndOfDirective();
+
+ // Restore 'DisableMacroExpansion'.
+ DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return false;
}
@@ -721,6 +738,8 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
DiscardUntilEndOfDirective();
}
+ // Restore 'DisableMacroExpansion'.
+ DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
return ResVal.Val != 0;
}
diff --git a/test/Preprocessor/macro_fn_disable_expand.c b/test/Preprocessor/macro_fn_disable_expand.c
index 2c24d696d5..e2c666e6a2 100644
--- a/test/Preprocessor/macro_fn_disable_expand.c
+++ b/test/Preprocessor/macro_fn_disable_expand.c
@@ -8,3 +8,23 @@ foo(foo) (2)
#define w ABCD
m(m)
// CHECK: m(ABCD)
+
+
+
+// rdar://7466570
+
+// We should get '42' in the argument list for gcc compatibility.
+#define A 1
+#define B 2
+#define C(x) (x + 1)
+
+X: C(
+#ifdef A
+#if A == 1
+#if B
+ 42
+#endif
+#endif
+#endif
+ )
+// CHECK: X: (42 + 1)