When using a precompiled preamble, keep track of the top-level
declarations that we saw when creating the precompiled preamble, and
provide those declarations in addition to the declarations parsed in
the main source file when traversing top-level declarations. This
makes the use of precompiled preambles a pure optimization, rather
than changing the semantics of the parsed translation unit.

llvm-svn: 110131
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index bd60296..c37610a 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -309,7 +309,7 @@
       // fundamental problem in the parser right now.
       if (isa<ObjCMethodDecl>(D))
         continue;
-      Unit.getTopLevelDecls().push_back(D);
+      Unit.addTopLevelDecl(D);
     }
   }
 };
@@ -331,6 +331,7 @@
 
 class PrecompilePreambleConsumer : public PCHGenerator {
   ASTUnit &Unit;
+  std::vector<Decl *> TopLevelDecls;
 
 public:
   PrecompilePreambleConsumer(ASTUnit &Unit,
@@ -338,7 +339,7 @@
                              const char *isysroot, llvm::raw_ostream *Out)
     : PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { }
 
-  void HandleTopLevelDecl(DeclGroupRef D) {
+  virtual void HandleTopLevelDecl(DeclGroupRef D) {
     for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
       Decl *D = *it;
       // FIXME: Currently ObjC method declarations are incorrectly being
@@ -347,7 +348,20 @@
       // fundamental problem in the parser right now.
       if (isa<ObjCMethodDecl>(D))
         continue;
-      Unit.getTopLevelDecls().push_back(D);
+      TopLevelDecls.push_back(D);
+    }
+  }
+
+  virtual void HandleTranslationUnit(ASTContext &Ctx) {
+    PCHGenerator::HandleTranslationUnit(Ctx);
+    if (!Unit.getDiagnostics().hasErrorOccurred()) {
+      // 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
+      // declarations when requested.
+      for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
+        Unit.addTopLevelDeclFromPreamble(
+                                      getWriter().getDeclID(TopLevelDecls[I]));
     }
   }
 };
@@ -855,7 +869,9 @@
   
   // Clear out old caches and data.
   StoredDiagnostics.clear();
-  
+  TopLevelDecls.clear();
+  TopLevelDeclsInPreamble.clear();
+
   // Capture any diagnostics that would otherwise be dropped.
   CaptureDroppedDiagnostics Capture(CaptureDiagnostics, 
                                     getDiagnostics(),
@@ -867,7 +883,6 @@
   // Create the source manager.
   Clang.setSourceManager(new SourceManager(getDiagnostics()));
   
-  // FIXME: Eventually, we'll have to track top-level declarations here, too.
   llvm::OwningPtr<PrecompilePreambleAction> Act;
   Act.reset(new PrecompilePreambleAction(*this));
   if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
@@ -889,7 +904,7 @@
   Clang.takeDiagnosticClient();
   Clang.takeInvocation();
   
-  if (Diagnostics->getNumErrors() > 0) {
+  if (Diagnostics->hasErrorOccurred()) {
     // 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?
@@ -899,7 +914,7 @@
       delete NewPreamble.first;
     if (PreambleTimer)
       PreambleTimer->stopTimer();
-
+    TopLevelDeclsInPreamble.clear();
     return 0;
   }
   
@@ -935,6 +950,31 @@
                                     FrontendOpts.Inputs[0].second);
 }
 
+void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
+  std::vector<Decl *> Resolved;
+  Resolved.reserve(TopLevelDeclsInPreamble.size());
+  ExternalASTSource &Source = *getASTContext().getExternalSource();
+  for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
+    // Resolve the declaration ID to an actual declaration, possibly
+    // deserializing the declaration in the process.
+    Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
+    if (D)
+      Resolved.push_back(D);
+  }
+  TopLevelDeclsInPreamble.clear();
+  TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
+}
+
+unsigned ASTUnit::getMaxPCHLevel() const {
+  if (!getOnlyLocalDecls())
+    return Decl::MaxPCHLevel;
+
+  unsigned Result = 0;
+  if (isMainFileAST() || SavedMainFileBuffer)
+    ++Result;
+  return Result;
+}
+
 ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
                                    llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
                                              bool OnlyLocalDecls,