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()); 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 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( - std::make_shared()); - 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/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 CI(new CompilerInvocation); - CompilerInvocation::CreateFromArgs(*CI, - const_cast(CCArgs.data()), - const_cast(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(CCArgs.data()), + const_cast(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 Act(new EmitLLVMOnlyAction()); if (!Clang.ExecuteAction(*Act)) 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 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/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 Args; + DiagnosticConsumer *DiagsClient = nullptr; + std::unique_ptr OwnedDiagsClient; InMemoryModuleCache *SharedModuleCache = nullptr; std::shared_ptr PCHContainerOps; + std::shared_ptr Invocation; + IntrusiveRefCntPtr Diags; + IntrusiveRefCntPtr 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 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 + 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(std::forward(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 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 Args, + IntrusiveRefCntPtr 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 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(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 PCHContainerOps) && { this->PCHContainerOps = std::move(PCHContainerOps); @@ -47,7 +142,10 @@ IntrusiveRefCntPtr getModuleCache(); std::shared_ptr getPCHContainerOps(); + std::shared_ptr getInvocation(); + IntrusiveRefCntPtr getDiags(); bool isBuildingModule(); + void initDiagsAndInvocation(); }; } // end namespace clang 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/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 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 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 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 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 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 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/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 DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient)); - - std::unique_ptr Clang( - new CompilerInstance(CI.getPCHContainerOperations())); - Clang->setInvocation(std::move(CInvok)); - Clang->setDiagnostics(Diags.get()); + std::unique_ptr Clang(new CompilerInstance( + CompilerInstanceBuilder() + .pchContainerOps(CI.getPCHContainerOperations()) + .invocation(std::move(CInvok)) + .diags(llvm::errs(), + new DiagnosticOptions))); Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); Clang->createFileManager(); 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(); } +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 DiagsBuffer; + if (!Diags && MakeInvocation) { + // Create a temporary diagnostics engine. + IntrusiveRefCntPtr 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(); + Invocation->setError(); + } + } else if (MakeInvocation) { + // Create an invocation from a command-line. + Invocation = std::make_shared(); + 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(); + } + + 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 CompilerInstanceBuilder::getInvocation() { + initDiagsAndInvocation(); + return std::move(Invocation); +} + +IntrusiveRefCntPtr 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 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 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( + 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/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 Opts = createDriverOptTable(); 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 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 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/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(CI.getInvocation())); - Instance.createDiagnostics( - new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), - /*ShouldOwnClient=*/true); + CompilerInstance Instance( + CompilerInstanceBuilder() + .pchContainerOps(CI.getPCHContainerOperations()) + .moduleCache(CI.getModuleCache()) + .invocation( + std::make_shared(CI.getInvocation())) + .diags(CI.getDiagnosticClient())); Instance.getFrontendOpts().DisableFree = false; Instance.getFrontendOpts().Inputs.clear(); Instance.getFrontendOpts().Inputs.emplace_back( 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(CI.getDiagnosticClient())); Instance.getDiagnostics().setSourceManager(&SM); Index: clang/lib/Tooling/Tooling.cpp =================================================================== --- clang/lib/Tooling/Tooling.cpp +++ clang/lib/Tooling/Tooling.cpp @@ -350,8 +350,10 @@ std::shared_ptr 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 ScopedToolAction(create()); - // Create the compiler's actual diagnostics engine. - Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); if (!Compiler.hasDiagnostics()) return false; 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 BuildCompilerInstance() { - auto Ins = llvm::make_unique(); - auto DC = llvm::make_unique(); - const bool ShouldOwnClient = true; - Ins->createDiagnostics(DC.release(), ShouldOwnClient); + auto Ins = llvm::make_unique( + CompilerInstanceBuilder().diags()); - auto Inv = llvm::make_unique(); + auto *Inv = &Ins->getInvocation(); std::vector 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/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 Argv, const char *Argv0, void *MainAddr) { ensureSufficientStack(); - std::unique_ptr Clang(new CompilerInstance()); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - - // Register the support for object-file-wrapped Clang modules. - auto PCHOps = Clang->getPCHContainerOperations(); - PCHOps->registerWriter(llvm::make_unique()); - PCHOps->registerReader(llvm::make_unique()); - // 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 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 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()); + PCHOps->registerReader(llvm::make_unique()); + // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. llvm::install_fatal_error_handler(LLVMErrorHandler, static_cast(&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/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(); - 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/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/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/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/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/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 Act(new NullCodeGenAction); 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 Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); - - std::shared_ptr 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/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/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 IRBuffer; std::unique_ptr 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/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 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: 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: 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 instance( - new clang::CompilerInstance); + std::unique_ptr instance = + llvm::make_unique( + 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 action(new clang::SyntaxOnlyAction);