When we try (but fail) to build a precompiled preamble, wait for a
short "cooling off" period (defaulting to 5 reparses) before trying to
build a precompiled preamble again. Previously, if we failed to build
the precompiled preamble at any time, we just gave up the whole
charade any never tried again.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110187 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 58f2b38..1fd5a0f 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -122,6 +122,17 @@
   static const unsigned int CheckLocked = 28573289;
   static const unsigned int CheckUnlocked = 9803453;
 
+  /// \brief Counter that determines when we want to try building a
+  /// precompiled preamble.
+  ///
+  /// If zero, we will never build a precompiled preamble. Otherwise,
+  /// it's treated as a counter that decrements each time we reparse
+  /// without the benefit of a precompiled preamble. When it hits 1,
+  /// we'll attempt to rebuild the precompiled header. This way, if
+  /// building the precompiled preamble fails, we won't try again for
+  /// some number of calls.
+  unsigned PreambleRebuildCounter;
+  
   /// \brief The file in which the precompiled preamble is stored.
   std::string PreambleFile;
   
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index c37610a..b553d7c 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -40,9 +40,16 @@
 #include <sys/stat.h>
 using namespace clang;
 
+/// \brief After failing to build a precompiled preamble (due to
+/// errors in the source that occurs in the preamble), the number of
+/// reparses during which we'll skip even trying to precompile the
+/// preamble.
+const unsigned DefaultPreambleRebuildInterval = 5;
+
 ASTUnit::ASTUnit(bool _MainFileIsAST)
   : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST), 
-    ConcurrencyCheckValue(CheckUnlocked), SavedMainFileBuffer(0) { 
+    ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0),
+    SavedMainFileBuffer(0) { 
 }
 
 ASTUnit::~ASTUnit() {
@@ -685,7 +692,9 @@
     }
     if (CreatedPreambleBuffer)
       delete NewPreamble.first;
-    
+
+    // The next time we actually see a preamble, precompile it.
+    PreambleRebuildCounter = 1;
     return 0;
   }
   
@@ -784,8 +793,17 @@
     // We can't reuse the previously-computed preamble. Build a new one.
     Preamble.clear();
     llvm::sys::Path(PreambleFile).eraseFromDisk();
+    PreambleRebuildCounter = 1;
   } 
-    
+
+  // If the preamble rebuild counter > 1, it's because we previously
+  // failed to build a preamble and we're not yet ready to try
+  // again. Decrement the counter and return a failure.
+  if (PreambleRebuildCounter > 1) {
+    --PreambleRebuildCounter;
+    return 0;
+  }
+
   // We did not previously compute a preamble, or it can't be reused anyway.
   llvm::Timer *PreambleTimer = 0;
   if (TimerGroup.get()) {
@@ -850,7 +868,7 @@
       delete NewPreamble.first;
     if (PreambleTimer)
       PreambleTimer->stopTimer();
-
+    PreambleRebuildCounter = DefaultPreambleRebuildInterval;
     return 0;
   }
   
@@ -895,6 +913,7 @@
       delete NewPreamble.first;
     if (PreambleTimer)
       PreambleTimer->stopTimer();
+    PreambleRebuildCounter = DefaultPreambleRebuildInterval;
 
     return 0;
   }
@@ -915,6 +934,7 @@
     if (PreambleTimer)
       PreambleTimer->stopTimer();
     TopLevelDeclsInPreamble.clear();
+    PreambleRebuildCounter = DefaultPreambleRebuildInterval;
     return 0;
   }
   
@@ -944,6 +964,7 @@
   if (PreambleTimer)
     PreambleTimer->stopTimer();
   
+  PreambleRebuildCounter = 1;
   return CreatePaddedMainFileBuffer(NewPreamble.first, 
                                     CreatedPreambleBuffer,
                                     PreambleReservedSize,
@@ -1003,8 +1024,10 @@
   
   llvm::MemoryBuffer *OverrideMainBuffer = 0;
   // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
-  if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus)
+  if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) {
+    AST->PreambleRebuildCounter = 1;
     OverrideMainBuffer = AST->BuildPrecompiledPreamble();
+  }
   
   llvm::Timer *ParsingTimer = 0;
   if (AST->TimerGroup.get()) {
@@ -1110,10 +1133,10 @@
     Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
                                                       RemappedFiles[I].second);
   
-  // If we have a preamble file lying around, build or reuse the precompiled
-  // preamble.
+  // If we have a preamble file lying around, or if we might try to
+  // build a precompiled preamble, do so now.
   llvm::MemoryBuffer *OverrideMainBuffer = 0;
-  if (!PreambleFile.empty())
+  if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
     OverrideMainBuffer = BuildPrecompiledPreamble();
     
   // Clear out the diagnostics state.