Reshuffle the PCH generator action and consumer, so that we can re-use
it while generating precompiled preambles. No functionality change.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110108 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index b36a338..bd60296 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -12,7 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/PCHWriter.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/DeclVisitor.h"
@@ -25,6 +25,7 @@
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/PCHReader.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/TargetOptions.h"
@@ -328,6 +329,54 @@
   virtual bool hasCodeCompletionSupport() const { return false; }
 };
 
+class PrecompilePreambleConsumer : public PCHGenerator {
+  ASTUnit &Unit;
+
+public:
+  PrecompilePreambleConsumer(ASTUnit &Unit,
+                             const Preprocessor &PP, bool Chaining,
+                             const char *isysroot, llvm::raw_ostream *Out)
+    : PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { }
+
+  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
+      // reported as top-level declarations, even though their DeclContext
+      // is the containing ObjC @interface/@implementation.  This is a
+      // fundamental problem in the parser right now.
+      if (isa<ObjCMethodDecl>(D))
+        continue;
+      Unit.getTopLevelDecls().push_back(D);
+    }
+  }
+};
+
+class PrecompilePreambleAction : public ASTFrontendAction {
+  ASTUnit &Unit;
+
+public:
+  explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
+
+  virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+                                         llvm::StringRef InFile) {
+    std::string Sysroot;
+    llvm::raw_ostream *OS = 0;
+    bool Chaining;
+    if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot, 
+                                                       OS, Chaining))
+      return 0;
+    
+    const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
+                             Sysroot.c_str() : 0;  
+    return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Chaining,
+                                          isysroot, OS);
+  }
+
+  virtual bool hasCodeCompletionSupport() const { return false; }
+  virtual bool hasASTFileSupport() const { return false; }
+};
+
 }
 
 /// Parse the source file into a translation unit using the given compiler
@@ -819,8 +868,8 @@
   Clang.setSourceManager(new SourceManager(getDiagnostics()));
   
   // FIXME: Eventually, we'll have to track top-level declarations here, too.
-  llvm::OwningPtr<GeneratePCHAction> Act;
-  Act.reset(new GeneratePCHAction);
+  llvm::OwningPtr<PrecompilePreambleAction> Act;
+  Act.reset(new PrecompilePreambleAction(*this));
   if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
                             Clang.getFrontendOpts().Inputs[0].first)) {
     Clang.takeDiagnosticClient();
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index b0f85f1..08639b6 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -17,6 +17,7 @@
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/PCHWriter.h"
 #include "clang/Frontend/Utils.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -70,22 +71,35 @@
 
 ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
                                                   llvm::StringRef InFile) {
-  const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
-  if (CI.getFrontendOpts().RelocatablePCH &&
-      Sysroot.empty()) {
-    CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
+  std::string Sysroot;
+  llvm::raw_ostream *OS = 0;
+  bool Chaining;
+  if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OS, Chaining))
     return 0;
+
+  const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
+                             Sysroot.c_str() : 0;  
+  return new PCHGenerator(CI.getPreprocessor(), Chaining, isysroot, OS);
+}
+
+bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
+                                                    llvm::StringRef InFile,
+                                                    std::string &Sysroot,
+                                                    llvm::raw_ostream *&OS,
+                                                    bool &Chaining) {
+  Sysroot = CI.getHeaderSearchOpts().Sysroot;
+  if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
+    CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
+    return true;
   }
 
-  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
+  OS = CI.createDefaultOutputFile(true, InFile);
   if (!OS)
-    return 0;
+    return true;
 
-  bool Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
-                  !CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
-  const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
-                             Sysroot.c_str() : 0;
-  return CreatePCHGenerator(CI.getPreprocessor(), OS, Chaining, isysroot);
+  Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
+             !CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
+  return false;
 }
 
 ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp
index 561a68a..33f5ef5 100644
--- a/lib/Frontend/GeneratePCH.cpp
+++ b/lib/Frontend/GeneratePCH.cpp
@@ -25,26 +25,6 @@
 
 using namespace clang;
 
-namespace {
-  class PCHGenerator : public SemaConsumer {
-    const Preprocessor &PP;
-    const char *isysroot;
-    llvm::raw_ostream *Out;
-    Sema *SemaPtr;
-    MemorizeStatCalls *StatCalls; // owned by the FileManager
-    std::vector<unsigned char> Buffer;
-    llvm::BitstreamWriter Stream;
-    PCHWriter Writer;
-
-  public:
-    PCHGenerator(const Preprocessor &PP, bool Chaining,
-                 const char *isysroot, llvm::raw_ostream *Out);
-    virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
-    virtual void HandleTranslationUnit(ASTContext &Ctx);
-    virtual PCHDeserializationListener *GetPCHDeserializationListener();
-  };
-}
-
 PCHGenerator::PCHGenerator(const Preprocessor &PP,
                            bool Chaining,
                            const char *isysroot,
@@ -82,10 +62,3 @@
 PCHDeserializationListener *PCHGenerator::GetPCHDeserializationListener() {
   return &Writer;
 }
-
-ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP,
-                                       llvm::raw_ostream *OS,
-                                       bool Chaining,
-                                       const char *isysroot) {
-  return new PCHGenerator(PP, Chaining, isysroot, OS);
-}