erikjv created this revision.
erikjv added a reviewer: bkramer.
erikjv added a subscriber: cfe-commits.

Previously, a preamble only included #if blocks (and friends like
#ifdef) if there was a corresponding #endif before any declaration or
definition. The problem is that any header file that uses include guards
will not have a preamble generated, which makes code-completion very
slow.

This fixes PR26045.


http://reviews.llvm.org/D15994

Files:
  lib/Lex/Lexer.cpp
  test/Lexer/preamble.c
  test/Lexer/preamble2.c

Index: test/Lexer/preamble2.c
===================================================================
--- /dev/null
+++ test/Lexer/preamble2.c
@@ -0,0 +1,19 @@
+// Preamble detection test: header with an include guard.
+#ifndef HEADER_H
+#define HEADER_H
+#include "foo"
+int bar;
+#endif
+
+// This test checks for detection of the preamble of a file, which
+// includes all of the starting comments and #includes.
+
+// RUN: %clang_cc1 -print-preamble %s > %t
+// RUN: echo END. >> %t
+// RUN: FileCheck < %t %s
+
+// CHECK: // Preamble detection test: header with an include guard.
+// CHECK-NEXT: #ifndef HEADER_H
+// CHECK-NEXT: #define HEADER_H
+// CHECK-NEXT: #include "foo"
+// CHECK-NEXT: END.
Index: test/Lexer/preamble.c
===================================================================
--- test/Lexer/preamble.c
+++ test/Lexer/preamble.c
@@ -9,15 +9,12 @@
 #pragma unknown
 #endif
 #ifdef WIBBLE
-#include "honk"
-#else
-int foo();
+#include "foo"
+int bar;
 #endif
 
 // This test checks for detection of the preamble of a file, which
-// includes all of the starting comments and #includes. Note that any
-// changes to the preamble part of this file must be mirrored in
-// Inputs/preamble.txt, since we diff against it.
+// includes all of the starting comments and #includes.
 
 // RUN: %clang_cc1 -print-preamble %s > %t
 // RUN: echo END. >> %t
@@ -33,4 +30,6 @@
 // CHECK-NEXT: #endif
 // CHECK-NEXT: #pragma unknown
 // CHECK-NEXT: #endif
+// CHECK-NEXT: #ifdef WIBBLE
+// CHECK-NEXT: #include "foo"
 // CHECK-NEXT: END.
Index: lib/Lex/Lexer.cpp
===================================================================
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -552,7 +552,7 @@
   bool InPreprocessorDirective = false;
   Token TheTok;
   Token IfStartTok;
-  unsigned IfCount = 0;
+  int IfCount = 0;
   SourceLocation ActiveCommentLoc;
 
   unsigned MaxLineOffset = 0;
@@ -656,8 +656,10 @@
             
         case PDK_EndIf:
           // Mismatched #endif. The preamble ends here.
-          if (IfCount == 0)
+          if (IfCount == 0) {
+            --IfCount;
             break;
+          }
 
           --IfCount;
           continue;
@@ -682,7 +684,8 @@
   } while (true);
   
   SourceLocation End;
-  if (IfCount)
+  if (IfCount < 0) // This allows for open #ifs, so a header with an include
+                   // guard will have a preamble generated for it.
     End = IfStartTok.getLocation();
   else if (ActiveCommentLoc.isValid())
     End = ActiveCommentLoc; // don't truncate a decl comment.


Index: test/Lexer/preamble2.c
===================================================================
--- /dev/null
+++ test/Lexer/preamble2.c
@@ -0,0 +1,19 @@
+// Preamble detection test: header with an include guard.
+#ifndef HEADER_H
+#define HEADER_H
+#include "foo"
+int bar;
+#endif
+
+// This test checks for detection of the preamble of a file, which
+// includes all of the starting comments and #includes.
+
+// RUN: %clang_cc1 -print-preamble %s > %t
+// RUN: echo END. >> %t
+// RUN: FileCheck < %t %s
+
+// CHECK: // Preamble detection test: header with an include guard.
+// CHECK-NEXT: #ifndef HEADER_H
+// CHECK-NEXT: #define HEADER_H
+// CHECK-NEXT: #include "foo"
+// CHECK-NEXT: END.
Index: test/Lexer/preamble.c
===================================================================
--- test/Lexer/preamble.c
+++ test/Lexer/preamble.c
@@ -9,15 +9,12 @@
 #pragma unknown
 #endif
 #ifdef WIBBLE
-#include "honk"
-#else
-int foo();
+#include "foo"
+int bar;
 #endif
 
 // This test checks for detection of the preamble of a file, which
-// includes all of the starting comments and #includes. Note that any
-// changes to the preamble part of this file must be mirrored in
-// Inputs/preamble.txt, since we diff against it.
+// includes all of the starting comments and #includes.
 
 // RUN: %clang_cc1 -print-preamble %s > %t
 // RUN: echo END. >> %t
@@ -33,4 +30,6 @@
 // CHECK-NEXT: #endif
 // CHECK-NEXT: #pragma unknown
 // CHECK-NEXT: #endif
+// CHECK-NEXT: #ifdef WIBBLE
+// CHECK-NEXT: #include "foo"
 // CHECK-NEXT: END.
Index: lib/Lex/Lexer.cpp
===================================================================
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -552,7 +552,7 @@
   bool InPreprocessorDirective = false;
   Token TheTok;
   Token IfStartTok;
-  unsigned IfCount = 0;
+  int IfCount = 0;
   SourceLocation ActiveCommentLoc;
 
   unsigned MaxLineOffset = 0;
@@ -656,8 +656,10 @@
             
         case PDK_EndIf:
           // Mismatched #endif. The preamble ends here.
-          if (IfCount == 0)
+          if (IfCount == 0) {
+            --IfCount;
             break;
+          }
 
           --IfCount;
           continue;
@@ -682,7 +684,8 @@
   } while (true);
   
   SourceLocation End;
-  if (IfCount)
+  if (IfCount < 0) // This allows for open #ifs, so a header with an include
+                   // guard will have a preamble generated for it.
     End = IfStartTok.getLocation();
   else if (ActiveCommentLoc.isValid())
     End = ActiveCommentLoc; // don't truncate a decl comment.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to