Implementation of pre-compiled headers (PCH) based on lazy
de-serialization of abstract syntax trees.

PCH support serializes the contents of the abstract syntax tree (AST)
to a bitstream. When the PCH file is read, declarations are serialized
as-needed. For example, a declaration of a variable "x" will be
deserialized only when its VarDecl can be found by a client, e.g.,
based on name lookup for "x" or traversing the entire contents of the
owner of "x".

This commit provides the framework for serialization and (lazy)
deserialization, along with support for variable and typedef
declarations (along with several kinds of types). More
declarations/types, along with important auxiliary structures (source
manager, preprocessor, etc.), will follow.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68732 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index b10323a..f8c44d6 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -29,6 +29,7 @@
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/InitHeaderSearch.h"
 #include "clang/Frontend/PathDiagnosticClients.h"
+#include "clang/Frontend/PCHReader.h"
 #include "clang/Frontend/TextDiagnosticBuffer.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Analysis/PathDiagnostic.h"
@@ -194,6 +195,7 @@
   DumpRawTokens,                // Dump out raw tokens.
   RunAnalysis,                  // Run one or more source code analyses. 
   GeneratePTH,                  // Generate pre-tokenized header.
+  GeneratePCH,                  // Generate pre-compiled header.
   InheritanceView               // View C++ inheritance for a specified class.
 };
 
@@ -229,6 +231,8 @@
                         "Print DeclContexts and their Decls"),
              clEnumValN(GeneratePTH, "emit-pth",
                         "Generate pre-tokenized header file"),
+             clEnumValN(GeneratePCH, "emit-pch",
+                        "Generate pre-compiled header file"),
              clEnumValN(TestSerialization, "test-pickling",
                         "Run prototype serialization code"),
              clEnumValN(EmitAssembly, "S",
@@ -975,6 +979,10 @@
 ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"),
                    llvm::cl::desc("Include file before parsing"));
 
+static llvm::cl::opt<std::string>
+ImplicitIncludePCH("include-pch", llvm::cl::value_desc("file"),
+                   llvm::cl::desc("Include precompiled header file"));
+
 // Append a #define line to Buf for Macro.  Macro should be of the form XXX,
 // in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit
 // "#define XXX Y z W".  To get a #define with no value, use "XXX=".
@@ -1516,6 +1524,9 @@
     // FIXME: Allow user to tailor where the file is written.
     return CreateASTSerializer(InFile, OutputFile, Diag);
     
+  case GeneratePCH:
+    return CreatePCHGenerator(Diag, LangOpts, InFile, OutputFile);    
+
   case RewriteObjC:
     return CreateCodeRewriterTest(InFile, OutputFile, Diag, LangOpts);
 
@@ -1683,6 +1694,18 @@
                                       PP.getSelectorTable(),
                                       /* FreeMemory = */ !DisableFree));
     
+    if (!ImplicitIncludePCH.empty()) {
+      // The user has asked us to include a precompiled header. Load
+      // the precompiled header into the AST context.
+      llvm::OwningPtr<PCHReader> Reader(
+                                   new clang::PCHReader(*ContextOwner.get()));
+      if (Reader->ReadPCH(ImplicitIncludePCH))
+        return;
+
+      llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
+      ContextOwner->setExternalSource(Source);
+    }
+
     ParseAST(PP, Consumer.get(), *ContextOwner.get(), Stats);
     
     if (FixItRewrite)