]> granicus.if.org Git - clang/commitdiff
Fix PR6282: the include guard optimization cannot happen if the
authorChris Lattner <sabre@nondot.org>
Fri, 12 Feb 2010 08:03:27 +0000 (08:03 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 12 Feb 2010 08:03:27 +0000 (08:03 +0000)
guard macro is already defined for the first occurrence of the
header.  If it is, the body will be skipped and not be properly
analyzed for the include guard optimization.

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

lib/Lex/PPDirectives.cpp
test/Preprocessor/mi_opt2.c [new file with mode: 0644]
test/Preprocessor/mi_opt2.h [new file with mode: 0644]

index b0e784bcd96a1a311d84b3aa9818185d57ef044e..4803c5ab85d58e4ffa4ea69e8230569103401997 100644 (file)
@@ -1514,18 +1514,21 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
   // Check to see if this is the last token on the #if[n]def line.
   CheckEndOfDirective(isIfndef ? "ifndef" : "ifdef");
 
+  IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
+  MacroInfo *MI = getMacroInfo(MII);
+  
   if (CurPPLexer->getConditionalStackDepth() == 0) {
-    // If the start of a top-level #ifdef, inform MIOpt.
-    if (!ReadAnyTokensBeforeDirective) {
+    // If the start of a top-level #ifdef and if the macro is not defined,
+    // inform MIOpt that this might be the start of a proper include guard.
+    // Otherwise it is some other form of unknown conditional which we can't
+    // handle.
+    if (!ReadAnyTokensBeforeDirective && MI == 0) {
       assert(isIfndef && "#ifdef shouldn't reach here");
-      CurPPLexer->MIOpt.EnterTopLevelIFNDEF(MacroNameTok.getIdentifierInfo());
+      CurPPLexer->MIOpt.EnterTopLevelIFNDEF(MII);
     } else
       CurPPLexer->MIOpt.EnterTopLevelConditional();
   }
 
-  IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
-  MacroInfo *MI = getMacroInfo(MII);
-
   // If there is a macro, process it.
   if (MI)  // Mark it used.
     MI->setIsUsed(true);
@@ -1558,7 +1561,7 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
   // If this condition is equivalent to #ifndef X, and if this is the first
   // directive seen, handle it for the multiple-include optimization.
   if (CurPPLexer->getConditionalStackDepth() == 0) {
-    if (!ReadAnyTokensBeforeDirective && IfNDefMacro)
+    if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
       CurPPLexer->MIOpt.EnterTopLevelIFNDEF(IfNDefMacro);
     else
       CurPPLexer->MIOpt.EnterTopLevelConditional();
diff --git a/test/Preprocessor/mi_opt2.c b/test/Preprocessor/mi_opt2.c
new file mode 100644 (file)
index 0000000..198d19f
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -E %s | FileCheck %s
+// PR6282
+// This test should not trigger the include guard optimization since
+// the guard macro is defined on the first include.
+
+#define ITERATING 1
+#define X 1
+#include "mi_opt2.h"
+#undef X
+#define X 2
+#include "mi_opt2.h"
+
+// CHECK: b: 1
+// CHECK: b: 2
+
diff --git a/test/Preprocessor/mi_opt2.h b/test/Preprocessor/mi_opt2.h
new file mode 100644 (file)
index 0000000..df37eba
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef ITERATING
+a: X
+#else
+b: X
+#endif