[libclang] Allow building a precompiled preamble with compiler errors

A while ago we allowed libclang to build a PCH that had compiler errors; this was to retain the performance
afforded by a PCH even if the user's code is in an intermediate state.

Extend this for the precompiled preamble as well.

rdar://14109828

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183717 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 2d91653..b03e71c 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -974,8 +974,8 @@
 public:
   PrecompilePreambleConsumer(ASTUnit &Unit, const Preprocessor &PP, 
                              StringRef isysroot, raw_ostream *Out)
-    : PCHGenerator(PP, "", 0, isysroot, Out), Unit(Unit),
-      Hash(Unit.getCurrentTopLevelHashValue()) {
+    : PCHGenerator(PP, "", 0, isysroot, Out, /*AllowASTWithErrors=*/true),
+      Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()) {
     Hash = 0;
   }
 
@@ -996,7 +996,7 @@
 
   virtual void HandleTranslationUnit(ASTContext &Ctx) {
     PCHGenerator::HandleTranslationUnit(Ctx);
-    if (!Unit.getDiagnostics().hasErrorOccurred()) {
+    if (hasEmittedPCH()) {
       // Translate the top-level declarations we captured during
       // parsing into declaration IDs in the precompiled
       // preamble. This will allow us to deserialize those top-level
@@ -1010,9 +1010,11 @@
 
 class PrecompilePreambleAction : public ASTFrontendAction {
   ASTUnit &Unit;
+  PrecompilePreambleConsumer *PreambleConsumer;
 
 public:
-  explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
+  explicit PrecompilePreambleAction(ASTUnit &Unit)
+    : Unit(Unit), PreambleConsumer(0) {}
 
   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
                                          StringRef InFile) {
@@ -1029,10 +1031,16 @@
 
     CI.getPreprocessor().addPPCallbacks(
      new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
-    return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Sysroot, 
-                                          OS);
+    PreambleConsumer = new PrecompilePreambleConsumer(Unit,CI.getPreprocessor(),
+                                                      Sysroot, OS);
+    return PreambleConsumer;
   }
 
+  bool hasEmittedPreamblePCH() const {
+    return PreambleConsumer && PreambleConsumer->hasEmittedPCH();
+  }
+  virtual bool shouldEraseOutputFiles() { return !hasEmittedPreamblePCH(); }
+
   virtual bool hasCodeCompletionSupport() const { return false; }
   virtual bool hasASTFileSupport() const { return false; }
   virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; }
@@ -1622,7 +1630,7 @@
   Act->Execute();
   Act->EndSourceFile();
 
-  if (Diagnostics->hasErrorOccurred()) {
+  if (!Act->hasEmittedPreamblePCH()) {
     // There were errors parsing the preamble, so no precompiled header was
     // generated. Forget that we even tried.
     // FIXME: Should we leave a note for ourselves to try again?
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index ece51a3..60e6156 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -429,9 +429,9 @@
     llvm::errs() << "\n";
   }
 
-  // Cleanup the output streams, and erase the output files if we encountered
-  // an error.
-  CI.clearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().hasErrorOccurred());
+  // Cleanup the output streams, and erase the output files if instructed by the
+  // FrontendAction.
+  CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles());
 
   if (isCurrentFileAST()) {
     CI.takeSema();
@@ -445,6 +445,10 @@
   setCurrentInput(FrontendInputFile());
 }
 
+bool FrontendAction::shouldEraseOutputFiles() {
+  return getCompilerInstance().getDiagnostics().hasErrorOccurred();
+}
+
 //===----------------------------------------------------------------------===//
 // Utility Actions
 //===----------------------------------------------------------------------===//