Introduce a PCHContainerOperations interface (NFC).

A PCHContainerOperations abstract interface provides operations for
creating and unwrapping containers for serialized ASTs (precompiled
headers and clang modules). The default implementation is
RawPCHContainerOperations, which uses a flat file for the output.

The main application for this interface will be an
ObjectFilePCHContainerOperations implementation that uses LLVM to
wrap the module in an ELF/Mach-O/COFF container to store debug info
alongside the AST.

rdar://problem/20091852

llvm-svn: 240225
diff --git a/clang/tools/arcmt-test/arcmt-test.cpp b/clang/tools/arcmt-test/arcmt-test.cpp
index 7be4ed6..c269e01 100644
--- a/clang/tools/arcmt-test/arcmt-test.cpp
+++ b/clang/tools/arcmt-test/arcmt-test.cpp
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Frontend/PCHContainerOperations.h"
 #include "clang/ARCMigrate/ARCMT.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
@@ -130,7 +131,8 @@
   if (!CI.getLangOpts()->ObjC1)
     return false;
 
-  arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0], 
+  arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0],
+                              std::make_shared<RawPCHContainerOperations>(),
                               Diags->getClient());
   return Diags->getClient()->getNumErrors() > 0;
 }
@@ -169,7 +171,8 @@
   if (!origCI.getLangOpts()->ObjC1)
     return false;
 
-  MigrationProcess migration(origCI, DiagClient);
+  MigrationProcess migration(
+      origCI, std::make_shared<RawPCHContainerOperations>(), DiagClient);
 
   std::vector<TransformFn>
     transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC(),
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index fa1a10e..972bf5b 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Option/Arg.h"
+#include "clang/Frontend/PCHContainerOperations.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
 #include "clang/Frontend/CompilerInstance.h"
@@ -64,7 +65,8 @@
 #endif
 
 int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
-  std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+  std::unique_ptr<CompilerInstance> Clang(
+      new CompilerInstance(std::make_shared<RawPCHContainerOperations>()));
   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
 
   // Initialize targets first, so that --version shows registered targets.
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index bdefa9b..2216ec6 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2889,7 +2889,8 @@
   IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
       CompilerInstance::createDiagnostics(new DiagnosticOptions());
   std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
-      ast_filename, Diags, FileSystemOpts, CXXIdx->getOnlyLocalDecls(), None,
+      ast_filename, CXXIdx->getPCHContainerOperations(), Diags, FileSystemOpts,
+      CXXIdx->getOnlyLocalDecls(), None,
       /*CaptureDiagnostics=*/true,
       /*AllowPCHWithCompilerErrors=*/true,
       /*UserFilesAreVolatile=*/true);
@@ -3027,7 +3028,8 @@
   unsigned NumErrors = Diags->getClient()->getNumErrors();
   std::unique_ptr<ASTUnit> ErrUnit;
   std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCommandLine(
-      Args->data(), Args->data() + Args->size(), Diags,
+      Args->data(), Args->data() + Args->size(),
+      CXXIdx->getPCHContainerOperations(), Diags,
       CXXIdx->getClangResourcesPath(), CXXIdx->getOnlyLocalDecls(),
       /*CaptureDiagnostics=*/true, *RemappedFiles.get(),
       /*RemappedFilesKeepOriginalName=*/true, PrecompilePreamble, TUKind,
@@ -3268,7 +3270,8 @@
     RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));
   }
 
-  if (!CXXUnit->Reparse(*RemappedFiles.get()))
+  if (!CXXUnit->Reparse(CXXIdx->getPCHContainerOperations(),
+                        *RemappedFiles.get()))
     RTUI->result = CXError_Success;
   else if (isASTReadError(CXXUnit))
     RTUI->result = CXError_ASTReadError;
diff --git a/clang/tools/libclang/CIndexCodeCompletion.cpp b/clang/tools/libclang/CIndexCodeCompletion.cpp
index ca167e8..a7b8e29 100644
--- a/clang/tools/libclang/CIndexCodeCompletion.cpp
+++ b/clang/tools/libclang/CIndexCodeCompletion.cpp
@@ -715,14 +715,12 @@
 
   // Perform completion.
   AST->CodeComplete(complete_filename, complete_line, complete_column,
-                    RemappedFiles,
-                    (options & CXCodeComplete_IncludeMacros),
+                    RemappedFiles, (options & CXCodeComplete_IncludeMacros),
                     (options & CXCodeComplete_IncludeCodePatterns),
-                    IncludeBriefComments,
-                    Capture,
-                    *Results->Diag, Results->LangOpts, *Results->SourceMgr,
-                    *Results->FileMgr, Results->Diagnostics,
-                    Results->TemporaryBuffers);
+                    IncludeBriefComments, Capture,
+                    CXXIdx->getPCHContainerOperations(), *Results->Diag,
+                    Results->LangOpts, *Results->SourceMgr, *Results->FileMgr,
+                    Results->Diagnostics, Results->TemporaryBuffers);
 
   Results->DiagnosticsWrappers.resize(Results->Diagnostics.size());
 
diff --git a/clang/tools/libclang/CIndexer.h b/clang/tools/libclang/CIndexer.h
index cb7c62e..8a306cd 100644
--- a/clang/tools/libclang/CIndexer.h
+++ b/clang/tools/libclang/CIndexer.h
@@ -16,6 +16,8 @@
 #define LLVM_CLANG_TOOLS_LIBCLANG_CINDEXER_H
 
 #include "clang-c/Index.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Lex/ModuleLoader.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Path.h"
 #include <vector>
@@ -38,11 +40,14 @@
   unsigned Options; // CXGlobalOptFlags.
 
   std::string ResourcesPath;
+  std::shared_ptr<PCHContainerOperations> PCHContainerOps;
 
 public:
- CIndexer() : OnlyLocalDecls(false), DisplayDiagnostics(false),
-              Options(CXGlobalOpt_None) { }
-  
+  CIndexer(std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+               std::make_shared<RawPCHContainerOperations>())
+      : OnlyLocalDecls(false), DisplayDiagnostics(false),
+        Options(CXGlobalOpt_None), PCHContainerOps(PCHContainerOps) {}
+
   /// \brief Whether we only want to see "local" declarations (that did not
   /// come from a previous precompiled header). If false, we want to see all
   /// declarations.
@@ -54,6 +59,10 @@
     DisplayDiagnostics = Display;
   }
 
+  std::shared_ptr<PCHContainerOperations> getPCHContainerOperations() const {
+    return PCHContainerOps;
+  }
+
   unsigned getCXGlobalOptFlags() const { return Options; }
   void setCXGlobalOptFlags(unsigned options) { Options = options; }
 
diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp
index 0ede684..e356400 100644
--- a/clang/tools/libclang/Indexing.cpp
+++ b/clang/tools/libclang/Indexing.cpp
@@ -590,8 +590,7 @@
   if (index_options & CXIndexOpt_SuppressWarnings)
     CInvok->getDiagnosticOpts().IgnoreWarnings = true;
 
-  ASTUnit *Unit = ASTUnit::create(CInvok.get(), Diags,
-                                  CaptureDiagnostics,
+  ASTUnit *Unit = ASTUnit::create(CInvok.get(), Diags, CaptureDiagnostics,
                                   /*UserFilesAreVolatile=*/true);
   if (!Unit) {
     ITUI->result = CXError_InvalidArguments;
@@ -644,17 +643,13 @@
     PPOpts.DetailedRecord = false;
 
   DiagnosticErrorTrap DiagTrap(*Diags);
-  bool Success = ASTUnit::LoadFromCompilerInvocationAction(CInvok.get(), Diags,
-                                                       IndexAction.get(),
-                                                       Unit,
-                                                       Persistent,
-                                                CXXIdx->getClangResourcesPath(),
-                                                       OnlyLocalDecls,
-                                                       CaptureDiagnostics,
-                                                       PrecompilePreamble,
-                                                    CacheCodeCompletionResults,
-                                 /*IncludeBriefCommentsInCodeCompletion=*/false,
-                                                 /*UserFilesAreVolatile=*/true);
+  bool Success = ASTUnit::LoadFromCompilerInvocationAction(
+      CInvok.get(), CXXIdx->getPCHContainerOperations(), Diags,
+      IndexAction.get(), Unit, Persistent, CXXIdx->getClangResourcesPath(),
+      OnlyLocalDecls, CaptureDiagnostics, PrecompilePreamble,
+      CacheCodeCompletionResults,
+      /*IncludeBriefCommentsInCodeCompletion=*/false,
+      /*UserFilesAreVolatile=*/true);
   if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
     printDiagsToStderr(Unit);