dexonsmith created this revision.
dexonsmith added a reviewer: rsmith.
Herald added subscribers: kadircet, arphaman, jkorous.
dexonsmith added a parent revision: D62457: Frontend: Create basic 
CompilerInstanceBuilder.

Add CompilerInvocation and DiagnosticsEngine to the new builder,
replacing a number of no-longer-needed `CompilerInstance` mutators.
These are in the same commit because the construction of a
`CompilerInvocation` and a `DiagnosticsEngine` is interestingly
entangled, since they each can depend on the other.  When the dependency
is truly cyclic, a temporary `DiagnosticsEngine` is used to construct
the `CompilerInvocation`, then the latter to construct the "real"
`DiagnosticsEngine` and the former's diagnostics are replayed.


https://reviews.llvm.org/D62458

Files:
  clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
  clang-tools-extra/clangd/Compiler.cpp
  clang/examples/clang-interpreter/main.cpp
  clang/include/clang/Frontend/CompilerInstance.h
  clang/include/clang/Frontend/CompilerInstanceBuilder.h
  clang/include/clang/Frontend/CompilerInvocation.h
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Frontend/ChainedIncludesSource.cpp
  clang/lib/Frontend/CompilerInstance.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/PrecompiledPreamble.cpp
  clang/lib/Frontend/Rewrite/FrontendActions.cpp
  clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
  clang/lib/Tooling/Tooling.cpp
  clang/tools/clang-import-test/clang-import-test.cpp
  clang/tools/driver/cc1_main.cpp
  clang/unittests/AST/ExternalASTSourceTest.cpp
  clang/unittests/CodeGen/BufferSourceTest.cpp
  clang/unittests/CodeGen/CodeGenExternalTest.cpp
  clang/unittests/CodeGen/IncrementalProcessingTest.cpp
  clang/unittests/CodeGen/TBAAMetadataTest.cpp
  clang/unittests/Frontend/CodeGenActionTest.cpp
  clang/unittests/Frontend/CompilerInstanceTest.cpp
  clang/unittests/Frontend/FrontendActionTest.cpp
  clang/unittests/Frontend/OutputStreamTest.cpp
  clang/unittests/Tooling/Syntax/TokensTest.cpp
  lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
  lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp

Index: lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -663,8 +663,11 @@
   invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName,
                                                     source_buffer.release());
 
-  std::unique_ptr<clang::CompilerInstance> instance(
-      new clang::CompilerInstance);
+  std::unique_ptr<clang::CompilerInstance> instance =
+      llvm::make_unique<clang::CompilerInstance>(
+          clang::CompilerInstanceBuilder()
+              .invocation(invocation)
+              .diags(*diagnostics_engine));
 
   // When capturing a reproducer, hook up the file collector with clang to
   // collector modules and headers.
@@ -680,8 +683,6 @@
 
   // Make sure clang uses the same VFS as LLDB.
   instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem());
-  instance->setDiagnostics(diagnostics_engine.get());
-  instance->setInvocation(invocation);
 
   std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
 
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -403,7 +403,6 @@
     }
 
   // 4. Create and install the target on the compiler.
-  m_compiler->createDiagnostics();
   auto target_info = TargetInfo::CreateTargetInfo(
       m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts);
   if (log) {
Index: clang/unittests/Tooling/Syntax/TokensTest.cpp
===================================================================
--- clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -113,14 +113,12 @@
       Diags->setClient(new IgnoringDiagConsumer);
     std::vector<const char *> Args = {"tok-test", "-std=c++03", "-fsyntax-only",
                                       FileName};
-    auto CI = createInvocationFromCommandLine(Args, Diags, FS);
-    assert(CI);
-    CI->getFrontendOpts().DisableFree = false;
-    CI->getPreprocessorOpts().addRemappedFile(
+    CompilerInstance Compiler(
+        CompilerInstanceBuilder().diags(*Diags).invocationFromDriver(Args, FS));
+    CompilerInvocation &CI = Compiler.getInvocation();
+    CI.getFrontendOpts().DisableFree = false;
+    CI.getPreprocessorOpts().addRemappedFile(
         FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release());
-    CompilerInstance Compiler;
-    Compiler.setInvocation(std::move(CI));
-    Compiler.setDiagnostics(Diags.get());
     Compiler.setFileManager(FileMgr.get());
     Compiler.setSourceManager(SourceMgr.get());
 
Index: clang/unittests/Frontend/OutputStreamTest.cpp
===================================================================
--- clang/unittests/Frontend/OutputStreamTest.cpp
+++ clang/unittests/Frontend/OutputStreamTest.cpp
@@ -27,15 +27,14 @@
       FrontendInputFile("test.cc", InputKind::CXX));
   Invocation->getFrontendOpts().ProgramAction = EmitBC;
   Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
-  CompilerInstance Compiler;
+  CompilerInstance Compiler(
+      CompilerInstanceBuilder().invocation(std::move(Invocation)));
 
   SmallVector<char, 256> IRBuffer;
   std::unique_ptr<raw_pwrite_stream> IRStream(
       new raw_svector_ostream(IRBuffer));
 
   Compiler.setOutputStream(std::move(IRStream));
-  Compiler.setInvocation(std::move(Invocation));
-  Compiler.createDiagnostics();
 
   bool Success = ExecuteCompilerInvocation(&Compiler);
   EXPECT_TRUE(Success);
Index: clang/unittests/Frontend/FrontendActionTest.cpp
===================================================================
--- clang/unittests/Frontend/FrontendActionTest.cpp
+++ clang/unittests/Frontend/FrontendActionTest.cpp
@@ -87,9 +87,8 @@
       FrontendInputFile("test.cc", InputKind::CXX));
   invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
   invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
-  CompilerInstance compiler;
-  compiler.setInvocation(std::move(invocation));
-  compiler.createDiagnostics();
+  CompilerInstance compiler(
+      CompilerInstanceBuilder().invocation(std::move(invocation)));
 
   TestASTFrontendAction test_action;
   ASSERT_TRUE(compiler.ExecuteAction(test_action));
@@ -107,9 +106,8 @@
       FrontendInputFile("test.cc", InputKind::CXX));
   invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
   invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
-  CompilerInstance compiler;
-  compiler.setInvocation(std::move(invocation));
-  compiler.createDiagnostics();
+  CompilerInstance compiler(
+      CompilerInstanceBuilder().invocation(std::move(invocation)));
 
   TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true);
   ASSERT_TRUE(compiler.ExecuteAction(test_action));
@@ -134,9 +132,8 @@
       FrontendInputFile("test.cc", InputKind::CXX));
   invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
   invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
-  CompilerInstance compiler;
-  compiler.setInvocation(std::move(invocation));
-  compiler.createDiagnostics();
+  CompilerInstance compiler(
+      CompilerInstanceBuilder().invocation(std::move(invocation)));
 
   TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true,
                                     /*actOnEndOfTranslationUnit=*/true);
@@ -180,9 +177,8 @@
       FrontendInputFile("test.cc", InputKind::CXX));
   Invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
   Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
-  CompilerInstance Compiler;
-  Compiler.setInvocation(std::move(Invocation));
-  Compiler.createDiagnostics();
+  CompilerInstance Compiler(
+      CompilerInstanceBuilder().invocation(std::move(Invocation)));
 
   TestPPCallbacks *Callbacks = new TestPPCallbacks;
   TestPPCallbacksFrontendAction TestAction(Callbacks);
@@ -241,18 +237,17 @@
       FrontendInputFile("test.cc", InputKind::CXX));
   Invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
   Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
-  CompilerInstance Compiler;
-  Compiler.setInvocation(std::move(Invocation));
-  auto *TDC = new TypoDiagnosticConsumer;
-  Compiler.createDiagnostics(TDC, /*ShouldOwnClient=*/true);
+  TypoDiagnosticConsumer TDC;
+  CompilerInstance Compiler(
+      CompilerInstanceBuilder().invocation(std::move(Invocation)).diags(TDC));
   Compiler.setExternalSemaSource(new TypoExternalSemaSource(Compiler));
 
   SyntaxOnlyAction TestAction;
   ASSERT_TRUE(Compiler.ExecuteAction(TestAction));
   // There should be one error correcting to 'moo' and a note attached to it.
   EXPECT_EQ("use of undeclared identifier 'foo'; did you mean 'moo'?",
-            TDC->Error.str().str());
-  EXPECT_EQ("This is a note", TDC->Note.str().str());
+            TDC.Error.str().str());
+  EXPECT_EQ("This is a note", TDC.Note.str().str());
 }
 
 TEST(GeneratePCHFrontendAction, CacheGeneratedPCH) {
@@ -274,9 +269,8 @@
     Invocation->getFrontendOpts().OutputFile = StringRef(PCHFilename);
     Invocation->getFrontendOpts().ProgramAction = frontend::GeneratePCH;
     Invocation->getTargetOpts().Triple = "x86_64-apple-darwin19.0.0";
-    CompilerInstance Compiler;
-    Compiler.setInvocation(std::move(Invocation));
-    Compiler.createDiagnostics();
+    CompilerInstance Compiler(
+        CompilerInstanceBuilder().invocation(std::move(Invocation)));
 
     GeneratePCHAction TestAction;
     ASSERT_TRUE(Compiler.ExecuteAction(TestAction));
Index: clang/unittests/Frontend/CompilerInstanceTest.cpp
===================================================================
--- clang/unittests/Frontend/CompilerInstanceTest.cpp
+++ clang/unittests/Frontend/CompilerInstanceTest.cpp
@@ -50,19 +50,13 @@
   const std::string VFSArg = "-ivfsoverlay" + FileNameStr;
   const char *Args[] = {"clang", VFSArg.c_str(), "-xc++", "-"};
 
-  IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
-      CompilerInstance::createDiagnostics(new DiagnosticOptions());
-
-  std::shared_ptr<CompilerInvocation> CInvok =
-      createInvocationFromCommandLine(Args, Diags);
-
-  if (!CInvok)
-    FAIL() << "could not create compiler invocation";
   // Create a minimal CompilerInstance which should use the VFS we specified
   // in the CompilerInvocation (as we don't explicitly set our own).
-  CompilerInstance Instance;
-  Instance.setDiagnostics(Diags.get());
-  Instance.setInvocation(CInvok);
+  CompilerInstance Instance(
+      CompilerInstanceBuilder().invocationFromDriver(Args));
+
+  if (Instance.getInvocation().hasError())
+    FAIL() << "could not create compiler invocation";
   Instance.createFileManager();
 
   // Check if the virtual file exists which means that our VFS is used by the
Index: clang/unittests/Frontend/CodeGenActionTest.cpp
===================================================================
--- clang/unittests/Frontend/CodeGenActionTest.cpp
+++ clang/unittests/Frontend/CodeGenActionTest.cpp
@@ -48,9 +48,8 @@
       FrontendInputFile("test.cc", InputKind::CXX));
   Invocation->getFrontendOpts().ProgramAction = EmitLLVM;
   Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
-  CompilerInstance Compiler;
-  Compiler.setInvocation(std::move(Invocation));
-  Compiler.createDiagnostics();
+  CompilerInstance Compiler(
+      CompilerInstanceBuilder().invocation(std::move(Invocation)));
   EXPECT_TRUE(Compiler.hasDiagnostics());
 
   std::unique_ptr<FrontendAction> Act(new NullCodeGenAction);
Index: clang/unittests/CodeGen/TBAAMetadataTest.cpp
===================================================================
--- clang/unittests/CodeGen/TBAAMetadataTest.cpp
+++ clang/unittests/CodeGen/TBAAMetadataTest.cpp
@@ -32,7 +32,6 @@
   unsigned PtrSize = 0;
 
   void init(const char *TestProgram) {
-    compiler.createDiagnostics();
     compiler.getCodeGenOpts().StructPathTBAA = 1;
     compiler.getCodeGenOpts().OptimizationLevel = 1;
 
Index: clang/unittests/CodeGen/IncrementalProcessingTest.cpp
===================================================================
--- clang/unittests/CodeGen/IncrementalProcessingTest.cpp
+++ clang/unittests/CodeGen/IncrementalProcessingTest.cpp
@@ -111,7 +111,6 @@
     LLVMContext Context;
     CompilerInstance compiler;
 
-    compiler.createDiagnostics();
     compiler.getLangOpts().CPlusPlus = 1;
     compiler.getLangOpts().CPlusPlus11 = 1;
 
Index: clang/unittests/CodeGen/CodeGenExternalTest.cpp
===================================================================
--- clang/unittests/CodeGen/CodeGenExternalTest.cpp
+++ clang/unittests/CodeGen/CodeGenExternalTest.cpp
@@ -260,7 +260,6 @@
     LLVMContext Context;
     CompilerInstance compiler;
 
-    compiler.createDiagnostics();
     compiler.getLangOpts().CPlusPlus = 1;
     compiler.getLangOpts().CPlusPlus11 = 1;
 
Index: clang/unittests/CodeGen/BufferSourceTest.cpp
===================================================================
--- clang/unittests/CodeGen/BufferSourceTest.cpp
+++ clang/unittests/CodeGen/BufferSourceTest.cpp
@@ -41,7 +41,6 @@
     LLVMContext Context;
     CompilerInstance compiler;
 
-    compiler.createDiagnostics();
     compiler.getLangOpts().CPlusPlus = 1;
     compiler.getLangOpts().CPlusPlus11 = 1;
 
Index: clang/unittests/AST/ExternalASTSourceTest.cpp
===================================================================
--- clang/unittests/AST/ExternalASTSourceTest.cpp
+++ clang/unittests/AST/ExternalASTSourceTest.cpp
@@ -45,17 +45,10 @@
 
 bool testExternalASTSource(ExternalASTSource *Source,
                            StringRef FileContents) {
-  CompilerInstance Compiler;
-  Compiler.createDiagnostics();
-
-  auto Invocation = std::make_shared<CompilerInvocation>();
-  Invocation->getPreprocessorOpts().addRemappedFile(
-      "test.cc", MemoryBuffer::getMemBuffer(FileContents).release());
   const char *Args[] = { "test.cc" };
-  CompilerInvocation::CreateFromArgs(*Invocation, Args,
-                                     Args + array_lengthof(Args),
-                                     Compiler.getDiagnostics());
-  Compiler.setInvocation(std::move(Invocation));
+  CompilerInstance Compiler(CompilerInstanceBuilder().invocation(Args));
+  Compiler.getInvocation().getPreprocessorOpts().addRemappedFile(
+      "test.cc", MemoryBuffer::getMemBuffer(FileContents).release());
 
   TestFrontendAction Action(Source);
   return Compiler.ExecuteAction(Action);
Index: clang/tools/driver/cc1_main.cpp
===================================================================
--- clang/tools/driver/cc1_main.cpp
+++ clang/tools/driver/cc1_main.cpp
@@ -20,8 +20,6 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/TextDiagnosticBuffer.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/FrontendTool/Utils.h"
 #include "llvm/ADT/Statistic.h"
@@ -169,14 +167,6 @@
 int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
   ensureSufficientStack();
 
-  std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
-  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
-
-  // Register the support for object-file-wrapped Clang modules.
-  auto PCHOps = Clang->getPCHContainerOperations();
-  PCHOps->registerWriter(llvm::make_unique<ObjectFilePCHContainerWriter>());
-  PCHOps->registerReader(llvm::make_unique<ObjectFilePCHContainerReader>());
-
   // Initialize targets first, so that --version shows registered targets.
   llvm::InitializeAllTargets();
   llvm::InitializeAllTargetMCs();
@@ -188,38 +178,28 @@
   polly::initializePollyPasses(Registry);
 #endif
 
-  // Buffer diagnostics from argument parsing so that we can output them using a
-  // well formed diagnostic object.
-  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
-  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
-  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
-  bool Success = CompilerInvocation::CreateFromArgs(
-      Clang->getInvocation(), Argv.begin(), Argv.end(), Diags);
-
+  std::unique_ptr<CompilerInstance> Clang(new CompilerInstance(
+      CompilerInstanceBuilder().invocation(Argv).inferResourceDir(Argv0,
+                                                                  MainAddr)));
   if (Clang->getFrontendOpts().TimeTrace)
     llvm::timeTraceProfilerInitialize();
 
-  // Infer the builtin include path if unspecified.
-  if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
-      Clang->getHeaderSearchOpts().ResourceDir.empty())
-    Clang->getHeaderSearchOpts().ResourceDir =
-      CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
-
-  // Create the actual diagnostics engine.
-  Clang->createDiagnostics();
-  if (!Clang->hasDiagnostics())
+  // Check for an error creating the compiler invocation.
+  if (Clang->getInvocation().hasError())
     return 1;
 
+  // Register the support for object-file-wrapped Clang modules.
+  auto PCHOps = Clang->getPCHContainerOperations();
+  PCHOps->registerWriter(llvm::make_unique<ObjectFilePCHContainerWriter>());
+  PCHOps->registerReader(llvm::make_unique<ObjectFilePCHContainerReader>());
+
   // Set an error handler, so that any LLVM backend diagnostics go through our
   // error handler.
   llvm::install_fatal_error_handler(LLVMErrorHandler,
                                   static_cast<void*>(&Clang->getDiagnostics()));
 
-  DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
-  if (!Success)
-    return 1;
-
   // Execute the frontend actions.
+  bool Success;
   {
     llvm::TimeTraceScope TimeScope("ExecuteCompiler", StringRef(""));
     Success = ExecuteCompilerInvocation(Clang.get());
Index: clang/tools/clang-import-test/clang-import-test.cpp
===================================================================
--- clang/tools/clang-import-test/clang-import-test.cpp
+++ clang/tools/clang-import-test/clang-import-test.cpp
@@ -158,12 +158,10 @@
 };
 
 std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
-  auto Ins = llvm::make_unique<CompilerInstance>();
-  auto DC = llvm::make_unique<TestDiagnosticConsumer>();
-  const bool ShouldOwnClient = true;
-  Ins->createDiagnostics(DC.release(), ShouldOwnClient);
+  auto Ins = llvm::make_unique<CompilerInstance>(
+      CompilerInstanceBuilder().diags<TestDiagnosticConsumer>());
 
-  auto Inv = llvm::make_unique<CompilerInvocation>();
+  auto *Inv = &Ins->getInvocation();
 
   std::vector<const char *> ClangArgv(ClangArgs.size());
   std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
@@ -200,8 +198,6 @@
   Inv->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
   Inv->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
 
-  Ins->setInvocation(std::move(Inv));
-
   TargetInfo *TI = TargetInfo::CreateTargetInfo(
       Ins->getDiagnostics(), Ins->getInvocation().TargetOpts);
   Ins->setTarget(TI);
Index: clang/lib/Tooling/Tooling.cpp
===================================================================
--- clang/lib/Tooling/Tooling.cpp
+++ clang/lib/Tooling/Tooling.cpp
@@ -350,8 +350,10 @@
     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
     DiagnosticConsumer *DiagConsumer) {
   // Create a compiler instance to handle the actual work.
-  CompilerInstance Compiler(std::move(PCHContainerOps));
-  Compiler.setInvocation(std::move(Invocation));
+  CompilerInstance Compiler(CompilerInstanceBuilder()
+                                .pchContainerOps(std::move(PCHContainerOps))
+                                .invocation(std::move(Invocation))
+                                .diags(*DiagConsumer));
   Compiler.setFileManager(Files);
 
   // The FrontendAction can have lifetime requirements for Compiler or its
@@ -359,8 +361,6 @@
   // pass it to an std::unique_ptr declared after the Compiler variable.
   std::unique_ptr<FrontendAction> ScopedToolAction(create());
 
-  // Create the compiler's actual diagnostics engine.
-  Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
   if (!Compiler.hasDiagnostics())
     return false;
 
Index: clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -74,11 +74,11 @@
 
   // Modules are parsed by a separate CompilerInstance, so this code mimics that
   // behavior for models
-  CompilerInstance Instance(CI.getPCHContainerOperations());
-  Instance.setInvocation(std::move(Invocation));
-  Instance.createDiagnostics(
-      new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
-      /*ShouldOwnClient=*/true);
+  CompilerInstance Instance(
+      CompilerInstanceBuilder()
+          .pchContainerOps(CI.getPCHContainerOperations())
+          .invocation(std::move(Invocation))
+          .diags<ForwardingDiagnosticConsumer>(CI.getDiagnosticClient()));
 
   Instance.getDiagnostics().setSourceManager(&SM);
 
Index: clang/lib/Frontend/Rewrite/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -236,13 +236,13 @@
     (*OS) << '\n';
 
     // Rewrite the contents of the module in a separate compiler instance.
-    CompilerInstance Instance(CI.getPCHContainerOperations(),
-                              &CI.getModuleCache());
-    Instance.setInvocation(
-        std::make_shared<CompilerInvocation>(CI.getInvocation()));
-    Instance.createDiagnostics(
-        new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
-        /*ShouldOwnClient=*/true);
+    CompilerInstance Instance(
+        CompilerInstanceBuilder()
+            .pchContainerOps(CI.getPCHContainerOperations())
+            .moduleCache(CI.getModuleCache())
+            .invocation(
+                std::make_shared<CompilerInvocation>(CI.getInvocation()))
+            .diags<ForwardingDiagnosticConsumer>(CI.getDiagnosticClient()));
     Instance.getFrontendOpts().DisableFree = false;
     Instance.getFrontendOpts().Inputs.clear();
     Instance.getFrontendOpts().Inputs.emplace_back(
Index: clang/lib/Frontend/PrecompiledPreamble.cpp
===================================================================
--- clang/lib/Frontend/PrecompiledPreamble.cpp
+++ clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -278,15 +278,15 @@
 
   // Create the compiler instance to use for building the precompiled preamble.
   std::unique_ptr<CompilerInstance> Clang(
-      new CompilerInstance(std::move(PCHContainerOps)));
+      new CompilerInstance(CompilerInstanceBuilder()
+                               .pchContainerOps(std::move(PCHContainerOps))
+                               .invocation(std::move(PreambleInvocation))
+                               .diags(Diagnostics)));
 
   // Recover resources if we crash before exiting this method.
   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(
       Clang.get());
 
-  Clang->setInvocation(std::move(PreambleInvocation));
-  Clang->setDiagnostics(&Diagnostics);
-
   // Create the target instance.
   Clang->setTarget(TargetInfo::CreateTargetInfo(
       Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -49,6 +49,7 @@
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -3276,6 +3277,8 @@
                                         const char *const *ArgEnd,
                                         DiagnosticsEngine &Diags) {
   bool Success = true;
+  auto SaveErrorOnExit =
+      llvm::make_scope_exit([&]() { Res.HasError = !Success; });
 
   // Parse the arguments.
   std::unique_ptr<OptTable> Opts = createDriverOptTable();
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -24,6 +24,7 @@
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/LogDiagnosticPrinter.h"
 #include "clang/Frontend/SerializedDiagnosticPrinter.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/Frontend/VerifyDiagnosticConsumer.h"
@@ -67,11 +68,76 @@
                          : std::make_shared<PCHContainerOperations>();
 }
 
+void CompilerInstanceBuilder::initDiagsAndInvocation() {
+  if (DidInitDiagsAndInvocation)
+    return;
+
+  DidInitDiagsAndInvocation = true;
+
+  // Creating an invocation without a diagnostics engine requires storing the
+  // diagnostics in a temporary buffer and replaying them later.
+  std::unique_ptr<TextDiagnosticBuffer> DiagsBuffer;
+  if (!Diags && MakeInvocation) {
+    // Create a temporary diagnostics engine.
+    IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+    DiagsBuffer.reset(new TextDiagnosticBuffer);
+    Diags = new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions,
+                                  DiagsBuffer.get(),
+                                  /*ShouldOwnClient=*/false);
+  }
+
+  if (MakeInvocationFromDriver) {
+    // Create an invocation from a command-line.
+    Invocation = createInvocationFromCommandLine(Args, Diags, VFS);
+    if (!Invocation) {
+      Invocation = std::make_shared<CompilerInvocation>();
+      Invocation->setError();
+    }
+  } else if (MakeInvocation) {
+    // Create an invocation from a command-line.
+    Invocation = std::make_shared<CompilerInvocation>();
+    CompilerInvocation::CreateFromArgs(*Invocation, Args.begin(), Args.end(),
+                                       *Diags);
+
+    // Infer the builtin include path if unspecified.
+    if (ShouldInferResourceDir &&
+        Invocation->getHeaderSearchOpts().UseBuiltinIncludes &&
+        Invocation->getHeaderSearchOpts().ResourceDir.empty())
+      Invocation->getHeaderSearchOpts().ResourceDir =
+          CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
+  } else if (!Invocation) {
+    Invocation = std::make_shared<CompilerInvocation>();
+  }
+
+  if (!Diags || DiagsBuffer) {
+    // Create a diagnostics engine using the compiler invocation.  If we
+    // created a temporary engine above, this will destroy it.
+    bool IsClientOwned = OwnedDiagsClient.get();
+    Diags = CompilerInstance::createDiagnostics(
+        &Invocation->getDiagnosticOpts(),
+        IsClientOwned ? OwnedDiagsClient.release() : DiagsClient, IsClientOwned,
+        &Invocation->getCodeGenOpts());
+  }
+
+  if (DiagsBuffer)
+    DiagsBuffer->FlushDiagnostics(*Diags);
+}
+
+std::shared_ptr<CompilerInvocation> CompilerInstanceBuilder::getInvocation() {
+  initDiagsAndInvocation();
+  return std::move(Invocation);
+}
+
+IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstanceBuilder::getDiags() {
+  initDiagsAndInvocation();
+  return std::move(Diags);
+}
+
 bool CompilerInstanceBuilder::isBuildingModule() { return SharedModuleCache; }
 
 CompilerInstance::CompilerInstance(CompilerInstanceBuilder Builder)
     : ModuleLoader(Builder.isBuildingModule()),
-      Invocation(new CompilerInvocation()),
+      Invocation(Builder.getInvocation()), Diagnostics(Builder.getDiags()),
       ModuleCache(Builder.getModuleCache()),
       ThePCHContainerOperations(Builder.getPCHContainerOps()) {}
 
@@ -86,11 +152,6 @@
   assert(OutputFiles.empty() && "Still output files in flight?");
 }
 
-void CompilerInstance::setInvocation(
-    std::shared_ptr<CompilerInvocation> Value) {
-  Invocation = std::move(Value);
-}
-
 bool CompilerInstance::shouldBuildGlobalModuleIndex() const {
   return (BuildGlobalModuleIndex ||
           (ModuleManager && ModuleManager->isGlobalIndexUnavailable() &&
@@ -98,10 +159,6 @@
          !ModuleBuildFailed;
 }
 
-void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
-  Diagnostics = Value;
-}
-
 void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
 void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }
 
@@ -269,12 +326,6 @@
   }
 }
 
-void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
-                                         bool ShouldOwnClient) {
-  Diagnostics = createDiagnostics(&getDiagnosticOpts(), Client,
-                                  ShouldOwnClient, &getCodeGenOpts());
-}
-
 IntrusiveRefCntPtr<DiagnosticsEngine>
 CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
                                     DiagnosticConsumer *Client,
@@ -1103,14 +1154,14 @@
   // module.  Since we're sharing an in-memory module cache,
   // CompilerInstance::CompilerInstance is responsible for finalizing the
   // buffers to prevent use-after-frees.
-  CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(),
-                            &ImportingInstance.getModuleCache());
   auto &Inv = *Invocation;
-  Instance.setInvocation(std::move(Invocation));
-
-  Instance.createDiagnostics(new ForwardingDiagnosticConsumer(
-                                   ImportingInstance.getDiagnosticClient()),
-                             /*ShouldOwnClient=*/true);
+  CompilerInstance Instance(
+      CompilerInstanceBuilder()
+          .pchContainerOps(ImportingInstance.getPCHContainerOperations())
+          .moduleCache(ImportingInstance.getModuleCache())
+          .invocation(std::move(Invocation))
+          .diags<ForwardingDiagnosticConsumer>(
+              ImportingInstance.getDiagnosticClient()));
 
   // Note that this module is part of the module build stack, so that we
   // can detect cycles in the module graph.
Index: clang/lib/Frontend/ChainedIncludesSource.cpp
===================================================================
--- clang/lib/Frontend/ChainedIncludesSource.cpp
+++ clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -137,16 +137,12 @@
     FrontendInputFile InputFile(includes[i], IK);
     CInvok->getFrontendOpts().Inputs.push_back(InputFile);
 
-    TextDiagnosticPrinter *DiagClient =
-      new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
-    IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
-    IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
-        new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
-
-    std::unique_ptr<CompilerInstance> Clang(
-        new CompilerInstance(CI.getPCHContainerOperations()));
-    Clang->setInvocation(std::move(CInvok));
-    Clang->setDiagnostics(Diags.get());
+    std::unique_ptr<CompilerInstance> Clang(new CompilerInstance(
+        CompilerInstanceBuilder()
+            .pchContainerOps(CI.getPCHContainerOperations())
+            .invocation(std::move(CInvok))
+            .diags<TextDiagnosticPrinter>(llvm::errs(),
+                                          new DiagnosticOptions)));
     Clang->setTarget(TargetInfo::CreateTargetInfo(
         Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
     Clang->createFileManager();
Index: clang/lib/Frontend/ASTUnit.cpp
===================================================================
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -1092,7 +1092,10 @@
 
   // Create the compiler instance to use for building the AST.
   std::unique_ptr<CompilerInstance> Clang(
-      new CompilerInstance(std::move(PCHContainerOps)));
+      new CompilerInstance(CompilerInstanceBuilder()
+                               .pchContainerOps(std::move(PCHContainerOps))
+                               .invocation(CCInvocation)
+                               .diags(getDiagnostics())));
 
   // Ensure that Clang has a FileManager with the right VFS, which may have
   // changed above in AddImplicitPreamble.  If VFS is nullptr, rely on
@@ -1106,13 +1109,8 @@
   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
     CICleanup(Clang.get());
 
-  Clang->setInvocation(CCInvocation);
   OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
 
-  // Set up diagnostics, capturing any diagnostics that would
-  // otherwise be dropped.
-  Clang->setDiagnostics(&getDiagnostics());
-
   // Create the target instance.
   Clang->setTarget(TargetInfo::CreateTargetInfo(
       Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
@@ -1530,19 +1528,17 @@
 
   // Create the compiler instance to use for building the AST.
   std::unique_ptr<CompilerInstance> Clang(
-      new CompilerInstance(std::move(PCHContainerOps)));
+      new CompilerInstance(CompilerInstanceBuilder()
+                               .pchContainerOps(std::move(PCHContainerOps))
+                               .invocation(std::move(CI))
+                               .diags(AST->getDiagnostics())));
 
   // Recover resources if we crash before exiting this method.
   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
     CICleanup(Clang.get());
 
-  Clang->setInvocation(std::move(CI));
   AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
 
-  // Set up diagnostics, capturing any diagnostics that would
-  // otherwise be dropped.
-  Clang->setDiagnostics(&AST->getDiagnostics());
-
   // Create the target instance.
   Clang->setTarget(TargetInfo::CreateTargetInfo(
       Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
@@ -2146,19 +2142,20 @@
   LangOpts.SpellChecking = false;
   CCInvocation->getDiagnosticOpts().IgnoreWarnings = true;
 
+  auto &Inv = *CCInvocation;
   std::unique_ptr<CompilerInstance> Clang(
-      new CompilerInstance(PCHContainerOps));
+      new CompilerInstance(CompilerInstanceBuilder()
+                               .pchContainerOps(PCHContainerOps)
+                               .invocation(std::move(CCInvocation))
+                               .diags(Diag)));
 
   // Recover resources if we crash before exiting this method.
   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
     CICleanup(Clang.get());
 
-  auto &Inv = *CCInvocation;
-  Clang->setInvocation(std::move(CCInvocation));
   OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
 
   // Set up diagnostics, capturing any diagnostics produced.
-  Clang->setDiagnostics(&Diag);
   CaptureDroppedDiagnostics Capture(true,
                                     Clang->getDiagnostics(),
                                     &StoredDiagnostics, nullptr);
@@ -2168,7 +2165,7 @@
   Clang->setTarget(TargetInfo::CreateTargetInfo(
       Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
   if (!Clang->hasTarget()) {
-    Clang->setInvocation(nullptr);
+    Clang->resetInvocation();
     return;
   }
 
Index: clang/include/clang/Frontend/CompilerInvocation.h
===================================================================
--- clang/include/clang/Frontend/CompilerInvocation.h
+++ clang/include/clang/Frontend/CompilerInvocation.h
@@ -138,6 +138,9 @@
   /// Options controlling preprocessed output.
   PreprocessorOutputOptions PreprocessorOutputOpts;
 
+  /// Track whether there was an error during creation.
+  bool HasError = false;
+
 public:
   CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {}
 
@@ -145,7 +148,8 @@
   /// @{
 
   /// Create a compiler invocation from a list of input options.
-  /// \returns true on success.
+  /// \returns true on success; otherwise Res.hasError() returns
+  /// false.
   ///
   /// \param [out] Res - The resulting invocation.
   /// \param ArgBegin - The first element in the argument vector.
@@ -156,6 +160,9 @@
                              const char* const *ArgEnd,
                              DiagnosticsEngine &Diags);
 
+  bool hasError() const { return HasError; }
+  void setError() { HasError = true; }
+
   /// Get the directory where the compiler headers
   /// reside, relative to the compiler binary (found by the passed in
   /// arguments).
Index: clang/include/clang/Frontend/CompilerInstanceBuilder.h
===================================================================
--- clang/include/clang/Frontend/CompilerInstanceBuilder.h
+++ clang/include/clang/Frontend/CompilerInstanceBuilder.h
@@ -11,18 +11,113 @@
 
 namespace clang {
 
+class CompilerInvocation;
 class InMemoryModuleCache;
 class PCHContainerOperations;
 
 class CompilerInstanceBuilder {
+  bool MakeDiags = false;
+  bool MakeInvocation = false;
+  bool MakeInvocationFromDriver = false;
+  bool DidInitDiagsAndInvocation = false;
+  bool ShouldInferResourceDir = false;
+  const char *Argv0 = nullptr;
+  void *MainAddr = nullptr;
+  ArrayRef<const char *> Args;
+  DiagnosticConsumer *DiagsClient = nullptr;
+  std::unique_ptr<DiagnosticConsumer> OwnedDiagsClient;
   InMemoryModuleCache *SharedModuleCache = nullptr;
   std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+  std::shared_ptr<CompilerInvocation> Invocation;
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
+  IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS; // For the driver.
 
 public:
   CompilerInstanceBuilder() = default;
   CompilerInstanceBuilder(CompilerInstanceBuilder &&) = default;
   CompilerInstanceBuilder(const CompilerInstanceBuilder &) = delete;
 
+  CompilerInstanceBuilder &&diags(DiagnosticsEngine &Diags) && {
+    // Own the consumer.
+    assert(!MakeDiags && "Already built diagnostics engine?");
+    assert(!this->Diags && "Already has diagnostics engine?");
+    this->Diags = &Diags;
+    return std::move(*this);
+  }
+
+  CompilerInstanceBuilder &&
+  diags(std::unique_ptr<DiagnosticConsumer> DiagsClient) && {
+    // Own the consumer.
+    assert(!MakeDiags && "Already built diagnostics engine?");
+    assert(!Diags && "Already has diagnostics engine?");
+    MakeDiags = true;
+    this->OwnedDiagsClient = std::move(DiagsClient);
+    return std::move(*this);
+  }
+
+  template <class DiagClientT, class... ArgsT>
+  CompilerInstanceBuilder &&diags(ArgsT &&... args) && {
+    // Own the consumer.
+    assert(!MakeDiags && "Already built diagnostics engine?");
+    assert(!Diags && "Already has diagnostics engine?");
+    MakeDiags = true;
+    this->OwnedDiagsClient =
+        llvm::make_unique<DiagClientT>(std::forward<ArgsT>(args)...);
+    return std::move(*this);
+  }
+
+  CompilerInstanceBuilder &&diags(DiagnosticConsumer &DiagsClient) && {
+    // Don't own the consumer.
+    assert(!MakeDiags && "Already built diagnostics engine?");
+    assert(!Diags && "Already has diagnostics engine?");
+    MakeDiags = true;
+    this->DiagsClient = &DiagsClient;
+    return std::move(*this);
+  }
+
+  CompilerInstanceBuilder &&
+  invocation(std::shared_ptr<CompilerInvocation> Invocation) && {
+    assert(!this->Invocation && "Already has an invocation?");
+    assert(!this->MakeInvocation && "Already built an invocation?");
+    this->Invocation = std::move(Invocation);
+    return std::move(*this);
+  }
+
+  CompilerInstanceBuilder &&invocationFromDriver(
+      ArrayRef<const char *> Args,
+      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr) && {
+    assert(!this->Invocation && "Already has an invocation?");
+    assert(!this->MakeInvocation && "Already built an invocation?");
+    this->Args = Args;
+    this->MakeInvocation = true;
+    this->MakeInvocationFromDriver = true;
+    return std::move(*this);
+  }
+
+  CompilerInstanceBuilder &&invocation(ArrayRef<const char *> Args) && {
+    assert(!this->Invocation && "Already has an invocation?");
+    assert(!this->MakeInvocation && "Already built an invocation?");
+    this->Args = Args;
+    this->MakeInvocation = true;
+    return std::move(*this);
+  }
+
+  CompilerInstanceBuilder &&invocation(const char *const *ArgBegin,
+                                       const char *const *ArgEnd) && {
+    return std::move(*this).invocation(
+        ArrayRef<const char *>(ArgBegin, ArgEnd));
+  }
+
+  CompilerInstanceBuilder &&inferResourceDir(const char *Argv0,
+                                             void *MainAddr) && {
+    assert(MakeInvocation && "Expected to be making an invocation?");
+    assert(!MakeInvocationFromDriver && "Expected a -cc1?");
+    ShouldInferResourceDir = true;
+    this->Argv0 = Argv0;
+    this->MainAddr = MainAddr;
+    return std::move(*this);
+  }
+
   CompilerInstanceBuilder &&
   pchContainerOps(std::shared_ptr<PCHContainerOperations> PCHContainerOps) && {
     this->PCHContainerOps = std::move(PCHContainerOps);
@@ -47,7 +142,10 @@
 
   IntrusiveRefCntPtr<InMemoryModuleCache> getModuleCache();
   std::shared_ptr<PCHContainerOperations> getPCHContainerOps();
+  std::shared_ptr<CompilerInvocation> getInvocation();
+  IntrusiveRefCntPtr<DiagnosticsEngine> getDiags();
   bool isBuildingModule();
+  void initDiagsAndInvocation();
 };
 
 } // end namespace clang
Index: clang/include/clang/Frontend/CompilerInstance.h
===================================================================
--- clang/include/clang/Frontend/CompilerInstance.h
+++ clang/include/clang/Frontend/CompilerInstance.h
@@ -240,8 +240,8 @@
     return *Invocation;
   }
 
-  /// setInvocation - Replace the current invocation.
-  void setInvocation(std::shared_ptr<CompilerInvocation> Value);
+  /// Drop the invocation.
+  void resetInvocation() { Invocation.reset(); }
 
   /// Indicates whether we should (re)build the global module index.
   bool shouldBuildGlobalModuleIndex() const;
@@ -345,9 +345,6 @@
     return *Diagnostics;
   }
 
-  /// setDiagnostics - Replace the current diagnostics engine.
-  void setDiagnostics(DiagnosticsEngine *Value);
-
   DiagnosticConsumer &getDiagnosticClient() const {
     assert(Diagnostics && Diagnostics->getClient() &&
            "Compiler instance has no diagnostic client!");
@@ -589,22 +586,6 @@
   /// }
   /// @name Construction Utility Methods
   /// {
-
-  /// Create the diagnostics engine using the invocation's diagnostic options
-  /// and replace any existing one with it.
-  ///
-  /// Note that this routine also replaces the diagnostic client,
-  /// allocating one if one is not provided.
-  ///
-  /// \param Client If non-NULL, a diagnostic client that will be
-  /// attached to (and, then, owned by) the DiagnosticsEngine inside this AST
-  /// unit.
-  ///
-  /// \param ShouldOwnClient If Client is non-NULL, specifies whether
-  /// the diagnostic object should take ownership of the client.
-  void createDiagnostics(DiagnosticConsumer *Client = nullptr,
-                         bool ShouldOwnClient = true);
-
   /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
   ///
   /// If no diagnostic client is provided, this creates a
Index: clang/examples/clang-interpreter/main.cpp
===================================================================
--- clang/examples/clang-interpreter/main.cpp
+++ clang/examples/clang-interpreter/main.cpp
@@ -164,37 +164,26 @@
 
   // Initialize a compiler invocation object from the clang (-cc1) arguments.
   const llvm::opt::ArgStringList &CCArgs = Cmd.getArguments();
-  std::unique_ptr<CompilerInvocation> CI(new CompilerInvocation);
-  CompilerInvocation::CreateFromArgs(*CI,
-                                     const_cast<const char **>(CCArgs.data()),
-                                     const_cast<const char **>(CCArgs.data()) +
-                                       CCArgs.size(),
-                                     Diags);
+
+  // FIXME: This is copied from cc1_main.cpp; simplify and eliminate.
+
+  // Create a compiler instance to handle the actual work.
+  CompilerInstance Clang(
+      CompilerInstanceBuilder()
+          .invocation(const_cast<const char **>(CCArgs.data()),
+                      const_cast<const char **>(CCArgs.data()) + CCArgs.size())
+          .inferResourceDir(argv[0], MainAddr));
 
   // Show the invocation, with -v.
-  if (CI->getHeaderSearchOpts().Verbose) {
+  if (Clang.getHeaderSearchOpts().Verbose) {
     llvm::errs() << "clang invocation:\n";
     Jobs.Print(llvm::errs(), "\n", true);
     llvm::errs() << "\n";
   }
 
-  // FIXME: This is copied from cc1_main.cpp; simplify and eliminate.
-
-  // Create a compiler instance to handle the actual work.
-  CompilerInstance Clang;
-  Clang.setInvocation(std::move(CI));
-
-  // Create the compilers actual diagnostics engine.
-  Clang.createDiagnostics();
-  if (!Clang.hasDiagnostics())
+  if (Clang.getInvocation().hasError())
     return 1;
 
-  // Infer the builtin include path if unspecified.
-  if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
-      Clang.getHeaderSearchOpts().ResourceDir.empty())
-    Clang.getHeaderSearchOpts().ResourceDir =
-      CompilerInvocation::GetResourcesPath(argv[0], MainAddr);
-
   // Create and execute the frontend to generate an LLVM bitcode module.
   std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction());
   if (!Clang.ExecuteAction(*Act))
Index: clang-tools-extra/clangd/Compiler.cpp
===================================================================
--- clang-tools-extra/clangd/Compiler.cpp
+++ clang-tools-extra/clangd/Compiler.cpp
@@ -89,9 +89,7 @@
   }
 
   auto Clang = llvm::make_unique<CompilerInstance>(
-      std::make_shared<PCHContainerOperations>());
-  Clang->setInvocation(std::move(CI));
-  Clang->createDiagnostics(&DiagsClient, false);
+      CompilerInstanceBuilder().invocation(std::move(CI)).diags(DiagsClient));
 
   if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
           Clang->getInvocation(), Clang->getDiagnostics(), VFS))
Index: clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
===================================================================
--- clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
+++ clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
@@ -88,14 +88,12 @@
   assert(Invocation->getFrontendOpts().Inputs.size() == 1);
 
   // Set up Clang.
-  clang::CompilerInstance Compiler(PCHContainerOps);
-  Compiler.setInvocation(std::move(Invocation));
+  clang::CompilerInstance Compiler(CompilerInstanceBuilder()
+                                       .pchContainerOps(PCHContainerOps)
+                                       .invocation(std::move(Invocation))
+                                       .diags<IgnoringDiagConsumer>());
   Compiler.setFileManager(Files);
 
-  // Create the compiler's actual diagnostics engine. We want to drop all
-  // diagnostics here.
-  Compiler.createDiagnostics(new clang::IgnoringDiagConsumer,
-                             /*ShouldOwnClient=*/true);
   Compiler.createSourceManager(*Files);
 
   // We abort on fatal errors so don't let a large number of errors become
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to