]> granicus.if.org Git - clang/commitdiff
fix rdar://7466570 - Be more bug compatible with GCC when it comes to
authorChris Lattner <sabre@nondot.org>
Mon, 14 Dec 2009 05:00:18 +0000 (05:00 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 14 Dec 2009 05:00:18 +0000 (05:00 +0000)
expanding directives withing macro expansions.  This is undefined behavior
according to 6.10.3p11, so we might as well be undefined in ways similar to
GCC.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91266 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Lex/PPExpressions.cpp
test/Preprocessor/macro_fn_disable_expand.c

index 6422752ae92b90e5c4f0235d1b927e4f568bad17..2a6b2a7294178ef3d7fbb21b956a80d49914f9b4 100644 (file)
@@ -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;
 }
 
index 2c24d696d52ffc14eeec4491f1c6352625f8ddfd..e2c666e6a28e29527a33ae23e5e042d536ff6160 100644 (file)
@@ -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)