From 9e64628ed88c1afab1ef0a80e541c6c4adf1df0d Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Tue, 22 Jul 2025 10:10:39 -0700 Subject: [PATCH 01/15] [clang][deps] Remove dependency on `tooling::ToolAction` (#149904) The dependency scanner was initially using a fair amount of infrastructure provided by the `clangTooling` library. Over time, the needs for bespoke handling of command lines grew and the overlap with the tooling library kept shrinking. I don't think the library provides any value anymore. I decided to remove the dependency and only reimplement the small bits required by the scanner. This allowed for a nice simplification, where we no longer need to create temporary dummy `FileManager` instances (mis-named as `DriverFileMgr` in some parts) and `SourceManager` instances to attach to the `DiagnosticsEngine`. That code was copied from the tooling library to support `DiagnosticConsumers` that expect these to exist. The scanner uses a closed set of consumers and none need these objects to exist. The motivation for this (hopefully NFC) patch are some new restrictions to how VFS's can be propagated in Clang that I'm working on. (cherry picked from commit aa1b416065ec615e93c496bbb43c7c006a04553e) --- .../DependencyScanningWorker.cpp | 101 ++++++++---------- 1 file changed, 43 insertions(+), 58 deletions(-) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 0420a83191922..541e6ced39061 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -28,7 +28,6 @@ #include "clang/Tooling/DependencyScanning/InProcessModuleCache.h" #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" #include "clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h" -#include "clang/Tooling/Tooling.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/CAS/CASProvidingFileSystem.h" #include "llvm/CAS/CachingOnDiskFileSystem.h" @@ -506,7 +505,7 @@ class CASDependencyDirectivesGetter : public DependencyDirectivesGetter { /// A clang tool that runs the preprocessor in a mode that's optimized for /// dependency scanning for the given compiler invocation. -class DependencyScanningAction : public tooling::ToolAction { +class DependencyScanningAction { public: DependencyScanningAction( DependencyScanningService &Service, StringRef WorkingDirectory, @@ -514,26 +513,23 @@ class DependencyScanningAction : public tooling::ToolAction { llvm::IntrusiveRefCntPtr DepFS, llvm::IntrusiveRefCntPtr DepCASFS, llvm::IntrusiveRefCntPtr CacheFS, - bool DisableFree, bool EmitDependencyFile, - bool DiagGenerationAsCompilation, const CASOptions &CASOpts, + bool EmitDependencyFile, bool DiagGenerationAsCompilation, + const CASOptions &CASOpts, std::optional ModuleName = std::nullopt, raw_ostream *VerboseOS = nullptr) - : Service(Service), WorkingDirectory(WorkingDirectory), Consumer(Consumer), - Controller(Controller), DepFS(std::move(DepFS)), + : Service(Service), WorkingDirectory(WorkingDirectory), + Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)), DepCASFS(std::move(DepCASFS)), CacheFS(std::move(CacheFS)), - DisableFree(DisableFree), CASOpts(CASOpts), EmitDependencyFile(EmitDependencyFile), DiagGenerationAsCompilation(DiagGenerationAsCompilation), ModuleName(ModuleName), VerboseOS(VerboseOS) {} bool runInvocation(std::shared_ptr Invocation, - FileManager *DriverFileMgr, + IntrusiveRefCntPtr FS, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagConsumer) override { + DiagnosticConsumer *DiagConsumer) { // Make a deep copy of the original Clang invocation. CompilerInvocation OriginalInvocation(*Invocation); - // Restore the value of DisableFree, which may be modified by Tooling. - OriginalInvocation.getFrontendOpts().DisableFree = DisableFree; if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros)) canonicalizeDefines(OriginalInvocation.getPreprocessorOpts()); @@ -574,8 +570,8 @@ class DependencyScanningAction : public tooling::ToolAction { if (!DiagGenerationAsCompilation) sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); - ScanInstance.createDiagnostics(DriverFileMgr->getVirtualFileSystem(), - DiagConsumer, /*ShouldOwnClient=*/false); + ScanInstance.createDiagnostics(*FS, DiagConsumer, + /*ShouldOwnClient=*/false); if (!ScanInstance.hasDiagnostics()) return false; if (VerboseOS) @@ -588,6 +584,7 @@ class DependencyScanningAction : public tooling::ToolAction { ScanInstance.getHeaderSearchOpts().BuildSessionTimestamp = Service.getBuildSessionTimestamp(); + ScanInstance.getFrontendOpts().DisableFree = false; ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false; ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false; // This will prevent us compiling individual modules asynchronously since @@ -600,9 +597,9 @@ class DependencyScanningAction : public tooling::ToolAction { any(Service.getOptimizeArgs() & ScanningOptimizations::VFS); // Support for virtual file system overlays. - auto FS = createVFSFromCompilerInvocation( - ScanInstance.getInvocation(), ScanInstance.getDiagnostics(), - DriverFileMgr->getVirtualFileSystemPtr()); + FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(), + ScanInstance.getDiagnostics(), + std::move(FS)); // Create a new FileManager to match the invocation's FileSystemOptions. auto *FileMgr = ScanInstance.createFileManager(FS); @@ -776,9 +773,6 @@ class DependencyScanningAction : public tooling::ToolAction { LastCC1Arguments = OriginalInvocation.getCC1CommandLine(); LastCC1CacheKey = Controller.getCacheKey(OriginalInvocation); - // Propagate the statistics to the parent FileManager. - DriverFileMgr->AddStats(ScanInstance.getFileManager()); - return true; } @@ -819,7 +813,6 @@ class DependencyScanningAction : public tooling::ToolAction { llvm::IntrusiveRefCntPtr DepFS; llvm::IntrusiveRefCntPtr DepCASFS; llvm::IntrusiveRefCntPtr CacheFS; - bool DisableFree; const CASOptions &CASOpts; bool EmitDependencyFile = false; bool DiagGenerationAsCompilation; @@ -922,15 +915,14 @@ llvm::Error DependencyScanningWorker::computeDependencies( } static bool forEachDriverJob( - ArrayRef ArgStrs, DiagnosticsEngine &Diags, FileManager &FM, + ArrayRef ArgStrs, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr FS, llvm::function_ref Callback) { SmallVector Argv; Argv.reserve(ArgStrs.size()); for (const std::string &Arg : ArgStrs) Argv.push_back(Arg.c_str()); - llvm::vfs::FileSystem *FS = &FM.getVirtualFileSystem(); - std::unique_ptr Driver = std::make_unique( Argv[0], llvm::sys::getDefaultTargetTriple(), Diags, "clang LLVM compiler", FS); @@ -940,7 +932,8 @@ static bool forEachDriverJob( bool CLMode = driver::IsClangCL( driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1))); - if (llvm::Error E = driver::expandResponseFiles(Argv, CLMode, Alloc, FS)) { + if (llvm::Error E = + driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) { Diags.Report(diag::err_drv_expand_response_file) << llvm::toString(std::move(E)); return false; @@ -963,17 +956,25 @@ static bool forEachDriverJob( static bool createAndRunToolInvocation( std::vector CommandLine, DependencyScanningAction &Action, - FileManager &FM, + IntrusiveRefCntPtr FS, std::shared_ptr &PCHContainerOps, DiagnosticsEngine &Diags, DependencyConsumer &Consumer) { // Save executable path before providing CommandLine to ToolInvocation std::string Executable = CommandLine[0]; - ToolInvocation Invocation(std::move(CommandLine), &Action, &FM, - PCHContainerOps); - Invocation.setDiagnosticConsumer(Diags.getClient()); - Invocation.setDiagnosticOptions(&Diags.getDiagnosticOptions()); - if (!Invocation.run()) + + llvm::opt::ArgStringList Argv; + for (const std::string &Str : ArrayRef(CommandLine).drop_front()) + Argv.push_back(Str.c_str()); + + auto Invocation = std::make_shared(); + if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) { + // FIXME: Should we just go on like cc1_main does? + return false; + } + + if (!Action.runInvocation(std::move(Invocation), std::move(FS), + PCHContainerOps, Diags.getClient())) return false; std::vector Args = Action.takeLastCC1Arguments(); @@ -988,40 +989,25 @@ bool DependencyScanningWorker::scanDependencies( DependencyConsumer &Consumer, DependencyActionController &Controller, DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr FS, std::optional ModuleName) { - auto FileMgr = - llvm::makeIntrusiveRefCnt(FileSystemOptions{}, FS); - std::vector CCommandLine(CommandLine.size(), nullptr); llvm::transform(CommandLine, CCommandLine.begin(), [](const std::string &Str) { return Str.c_str(); }); auto DiagOpts = CreateAndPopulateDiagOpts(CCommandLine); sanitizeDiagOpts(*DiagOpts); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(FileMgr->getVirtualFileSystem(), - *DiagOpts, &DC, - /*ShouldOwnClient=*/false); - - // Although `Diagnostics` are used only for command-line parsing, the - // custom `DiagConsumer` might expect a `SourceManager` to be present. - SourceManager SrcMgr(*Diags, *FileMgr); - Diags->setSourceManager(&SrcMgr); - // DisableFree is modified by Tooling for running - // in-process; preserve the original value, which is - // always true for a driver invocation. - bool DisableFree = true; - DependencyScanningAction Action(Service, WorkingDirectory, Consumer, Controller, DepFS, - DepCASFS, CacheFS, - DisableFree, - /*EmitDependencyFile=*/false, - /*DiagGenerationAsCompilation=*/false, getCASOpts(), - ModuleName); + auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC, + /*ShouldOwnClient=*/false); + + DependencyScanningAction Action( + Service, WorkingDirectory, Consumer, Controller, DepFS, DepCASFS, CacheFS, + /*EmitDependencyFile=*/false, + /*DiagGenerationAsCompilation=*/false, getCASOpts(), ModuleName); bool Success = false; if (CommandLine[1] == "-cc1") { - Success = createAndRunToolInvocation(CommandLine, Action, *FileMgr, + Success = createAndRunToolInvocation(CommandLine, Action, FS, PCHContainerOps, *Diags, Consumer); } else { Success = forEachDriverJob( - CommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) { + CommandLine, *Diags, FS, [&](const driver::Command &Cmd) { if (StringRef(Cmd.getCreator().getName()) != "clang") { // Non-clang command. Just pass through to the dependency // consumer. @@ -1041,7 +1027,7 @@ bool DependencyScanningWorker::scanDependencies( // system to ensure that any file system requests that // are made by the driver do not go through the // dependency scanning filesystem. - return createAndRunToolInvocation(std::move(Argv), Action, *FileMgr, + return createAndRunToolInvocation(std::move(Argv), Action, FS, PCHContainerOps, *Diags, Consumer); }); } @@ -1171,7 +1157,6 @@ void DependencyScanningWorker::computeDependenciesFromCompilerInvocation( // compilation. DependencyScanningAction Action(Service, WorkingDirectory, DepsConsumer, Controller, DepFS, DepCASFS, CacheFS, - /*DisableFree=*/false, /*EmitDependencyFile=*/!DepFile.empty(), DiagGenerationAsCompilation, getCASOpts(), /*ModuleName=*/std::nullopt, VerboseOS); @@ -1181,6 +1166,6 @@ void DependencyScanningWorker::computeDependenciesFromCompilerInvocation( // FIXME: will clients other than -cc1scand care? IntrusiveRefCntPtr ActiveFiles = new FileManager(Invocation->getFileSystemOpts(), BaseFS); - (void)Action.runInvocation(std::move(Invocation), ActiveFiles.get(), - PCHContainerOps, &DiagsConsumer); + (void)Action.runInvocation(std::move(Invocation), BaseFS, PCHContainerOps, + &DiagsConsumer); } From a7299db4e2c225fd2eb321d8d4402315131a0c42 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Wed, 10 Sep 2025 15:29:26 -0700 Subject: [PATCH 02/15] Reland "[clang] Delay normalization of `-fmodules-cache-path` (#150123)" This reverts commit 613caa909c78f707e88960723c6a98364656a926, essentially reapplying 4a4bddec3571d78c8073fa45b57bbabc8796d13d after moving `normalizeModuleCachePath` from clangFrontend to clangLex. This PR is part of an effort to remove file system usage from the command line parsing code. The reason for that is that it's impossible to do file system access correctly without a configured VFS, and the VFS can only be configured after the command line is parsed. I don't want to intertwine command line parsing and VFS configuration, so I decided to perform the file system access after the command line is parsed and the VFS is configured - ideally right before the file system entity is used for the first time. This patch delays normalization of the module cache path until `CompilerInstance` is asked for the cache path in the current compilation context. (cherry picked from commit 55bef46146f05e1911fcb98715716d914efd518c) --- clang/include/clang/Driver/Options.td | 3 ++- clang/include/clang/Lex/HeaderSearch.h | 3 +++ clang/lib/Frontend/CompilerInstance.cpp | 11 ++++++++-- clang/lib/Frontend/CompilerInvocation.cpp | 20 ++----------------- clang/lib/Lex/HeaderSearch.cpp | 7 +++++++ clang/lib/Serialization/ASTWriter.cpp | 7 ++++++- .../DependencyScanningWorker.cpp | 7 ++++--- ...dules-cache-path-canonicalization-output.c | 18 +++++++++++++++++ 8 files changed, 51 insertions(+), 25 deletions(-) create mode 100644 clang/test/Modules/modules-cache-path-canonicalization-output.c diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index ab36095da58d4..27caddf378044 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3399,7 +3399,8 @@ defm declspec : BoolOption<"f", "declspec", def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group, Flags<[]>, Visibility<[ClangOption, CC1Option]>, MetaVarName<"">, - HelpText<"Specify the module cache path">; + HelpText<"Specify the module cache path">, + MarshallingInfoString>; def fmodules_user_build_path : Separate<["-"], "fmodules-user-build-path">, Group, Flags<[]>, Visibility<[ClangOption, CC1Option]>, MetaVarName<"">, diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index 2e0c8bec8bd8c..850aea41c4c3b 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -986,6 +986,9 @@ void ApplyHeaderSearchOptions(HeaderSearch &HS, const LangOptions &Lang, const llvm::Triple &triple); +void normalizeModuleCachePath(FileManager &FileMgr, StringRef Path, + SmallVectorImpl &NormalizedPath); + } // namespace clang #endif // LLVM_CLANG_LEX_HEADERSEARCH_H diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index b9016b4a0fd6a..dde2fba867f66 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -559,9 +559,16 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { } std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) { + assert(FileMgr && "Specific module cache path requires a FileManager"); + + if (getHeaderSearchOpts().ModuleCachePath.empty()) + return ""; + // Set up the module path, including the hash for the module-creation options. - SmallString<256> SpecificModuleCache(getHeaderSearchOpts().ModuleCachePath); - if (!SpecificModuleCache.empty() && !getHeaderSearchOpts().DisableModuleHash) + SmallString<256> SpecificModuleCache; + normalizeModuleCachePath(*FileMgr, getHeaderSearchOpts().ModuleCachePath, + SpecificModuleCache); + if (!getHeaderSearchOpts().DisableModuleHash) llvm::sys::path::append(SpecificModuleCache, ModuleHash); return std::string(SpecificModuleCache); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 8602b16c2f526..dedc9fd7ebf97 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3586,9 +3586,6 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts, if (Opts.UseLibcxx) GenerateArg(Consumer, OPT_stdlib_EQ, "libc++"); - if (!Opts.ModuleCachePath.empty()) - GenerateArg(Consumer, OPT_fmodules_cache_path, Opts.ModuleCachePath); - for (const auto &File : Opts.PrebuiltModuleFiles) GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second); @@ -3691,8 +3688,7 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts, } static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, - DiagnosticsEngine &Diags, - const std::string &WorkingDir) { + DiagnosticsEngine &Diags) { unsigned NumErrorsBefore = Diags.getNumErrors(); HeaderSearchOptions *HeaderSearchOpts = &Opts; @@ -3705,17 +3701,6 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ)) Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0); - // Canonicalize -fmodules-cache-path before storing it. - SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path)); - if (!(P.empty() || llvm::sys::path::is_absolute(P))) { - if (WorkingDir.empty()) - llvm::sys::fs::make_absolute(P); - else - llvm::sys::fs::make_absolute(WorkingDir, P); - } - llvm::sys::path::remove_dots(P); - Opts.ModuleCachePath = std::string(P); - // Only the -fmodule-file== form. for (const auto *A : Args.filtered(OPT_fmodule_file)) { StringRef Val = A->getValue(); @@ -5582,8 +5567,7 @@ bool CompilerInvocation::CreateFromArgsImpl( InputKind DashX = Res.getFrontendOpts().DashX; ParseTargetArgs(Res.getTargetOpts(), Args, Diags); llvm::Triple T(Res.getTargetOpts().Triple); - ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags, - Res.getFileSystemOpts().WorkingDir); + ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags); if (Res.getFrontendOpts().GenReducedBMI || Res.getFrontendOpts().ProgramAction == frontend::GenerateReducedModuleInterface || diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index ea2391f6812cf..f28a74f5d0ae5 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -2183,3 +2183,10 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics( } return path::convert_to_slash(Filename); } + +void clang::normalizeModuleCachePath(FileManager &FileMgr, StringRef Path, + SmallVectorImpl &NormalizedPath) { + NormalizedPath.assign(Path.begin(), Path.end()); + FileMgr.makeAbsolutePath(NormalizedPath); + llvm::sys::path::remove_dots(NormalizedPath); +} diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 4a784d4a62c2b..5357bfd123d2d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -57,6 +57,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" +#include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/MacroInfo.h" @@ -1725,9 +1726,13 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) { const HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); + SmallString<256> HSOpts_ModuleCachePath; + normalizeModuleCachePath(PP.getFileManager(), HSOpts.ModuleCachePath, + HSOpts_ModuleCachePath); + AddString(HSOpts.Sysroot, Record); AddString(HSOpts.ResourceDir, Record); - AddString(HSOpts.ModuleCachePath, Record); + AddString(HSOpts_ModuleCachePath, Record); AddString(HSOpts.ModuleUserBuildPath, Record); Record.push_back(HSOpts.DisableModuleHash); Record.push_back(HSOpts.ImplicitModuleMaps); diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 541e6ced39061..73482a7c52fcf 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -606,9 +606,10 @@ class DependencyScanningAction { // Use the dependency scanning optimized file system if requested to do so. if (DepFS) { - StringRef ModulesCachePath = - ScanInstance.getHeaderSearchOpts().ModuleCachePath; - + SmallString<256> ModulesCachePath; + normalizeModuleCachePath( + *FileMgr, ScanInstance.getHeaderSearchOpts().ModuleCachePath, + ModulesCachePath); DepFS->resetBypassedPathPrefix(); if (!ModulesCachePath.empty()) DepFS->setBypassedPathPrefix(ModulesCachePath); diff --git a/clang/test/Modules/modules-cache-path-canonicalization-output.c b/clang/test/Modules/modules-cache-path-canonicalization-output.c new file mode 100644 index 0000000000000..ad71b69e5299e --- /dev/null +++ b/clang/test/Modules/modules-cache-path-canonicalization-output.c @@ -0,0 +1,18 @@ +// This checks that implicitly-built modules produce identical PCM +// files regardless of the spelling of the same module cache path. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fsyntax-only %t/tu.c \ +// RUN: -fmodules-cache-path=%t/cache -fdisable-module-hash +// RUN: mv %t/cache/M.pcm %t/M.pcm +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fsyntax-only %t/tu.c \ +// RUN: -fmodules-cache-path=%t/./cache -fdisable-module-hash +// RUN: diff %t/./cache/M.pcm %t/M.pcm + +//--- tu.c +#include "M.h" +//--- M.h +//--- module.modulemap +module M { header "M.h" } From f9d542f6b4ffa08a8572725d6ce2ccff3ffb9522 Mon Sep 17 00:00:00 2001 From: James Y Knight Date: Thu, 31 Jul 2025 15:07:35 -0400 Subject: [PATCH 03/15] NFC: Clean up of IntrusiveRefCntPtr construction from raw pointers. (#151545) Handles clang::DiagnosticsEngine and clang::DiagnosticIDs. For DiagnosticIDs, this mostly migrates from `new DiagnosticIDs` to convenience method `DiagnosticIDs::create()`. Part of cleanup https://github.com/llvm/llvm-project/issues/151026 (cherry picked from commit c7f343750744fd0c928b1da67e9dd894a2fe52cf) Conflicts: clang/tools/driver/cc1_main.cpp clang/unittests/Driver/DXCModeTest.cpp clang/unittests/Driver/SimpleDiagnosticConsumer.h clang/unittests/Frontend/SearchPathTest.cpp clang/unittests/Lex/HeaderSearchTest.cpp clang/unittests/Tooling/RewriterTestContext.h --- .../tool/ClangApplyReplacementsMain.cpp | 3 +- .../tool/ClangChangeNamespace.cpp | 5 ++-- .../tool/ClangIncludeFixer.cpp | 2 +- .../clang-move/tool/ClangMove.cpp | 5 ++-- .../tool/ClangReorderFields.cpp | 5 ++-- clang-tools-extra/clang-tidy/ClangTidy.cpp | 5 ++-- .../ExpandModularHeadersPPCallbacks.cpp | 2 +- .../clang-tidy/plugin/ClangTidyPlugin.cpp | 2 +- clang-tools-extra/clangd/Preamble.cpp | 2 +- .../clangd/SystemIncludeExtractor.cpp | 2 +- .../clangd/unittests/ConfigCompileTests.cpp | 2 +- .../clangd/unittests/tweaks/TweakTests.cpp | 2 +- .../modularize/ModularizeUtilities.cpp | 2 +- .../ApplyReplacementsTest.cpp | 3 +- .../clang-tidy/ClangTidyOptionsTest.cpp | 9 ++++-- .../unittests/clang-tidy/ClangTidyTest.h | 3 +- .../include/common/VirtualFileHelper.h | 3 +- clang/include/clang/Basic/DiagnosticIDs.h | 5 ++++ clang/include/clang/Frontend/ASTUnit.h | 8 +++-- .../include/clang/Frontend/CompilerInstance.h | 2 +- .../clang/Frontend/PrecompiledPreamble.h | 2 +- clang/lib/Basic/SourceManager.cpp | 4 +-- clang/lib/CrossTU/CrossTranslationUnit.cpp | 9 +++--- clang/lib/Frontend/ASTMerge.cpp | 4 +-- clang/lib/Frontend/ASTUnit.cpp | 15 +++++----- clang/lib/Frontend/ChainedIncludesSource.cpp | 7 ++--- clang/lib/Frontend/CompilerInstance.cpp | 10 +++---- clang/lib/Frontend/CompilerInvocation.cpp | 4 +-- clang/lib/Frontend/FrontendAction.cpp | 8 ++--- clang/lib/Frontend/PrecompiledPreamble.cpp | 14 ++++----- .../Frontend/SerializedDiagnosticPrinter.cpp | 5 ++-- clang/lib/Interpreter/CodeCompletion.cpp | 2 +- clang/lib/Interpreter/Interpreter.cpp | 6 ++-- clang/lib/Serialization/ASTReader.cpp | 3 +- clang/lib/Tooling/CompilationDatabase.cpp | 5 ++-- clang/lib/Tooling/Core/Replacement.cpp | 3 +- clang/lib/Tooling/Refactoring.cpp | 5 ++-- .../ClangExtDefMapGen.cpp | 5 ++-- clang/tools/clang-format/ClangFormat.cpp | 8 ++--- .../clang-fuzzer/handle-cxx/handle_cxx.cpp | 6 ++-- .../clang-installapi/ClangInstallAPI.cpp | 4 +-- clang/tools/diagtool/ShowEnabledWarnings.cpp | 4 +-- clang/tools/diagtool/TreeView.cpp | 2 +- clang/tools/driver/cc1_main.cpp | 2 +- clang/tools/driver/cc1as_main.cpp | 3 +- clang/tools/driver/cc1gen_reproducer_main.cpp | 4 +-- clang/tools/driver/driver.cpp | 4 +-- clang/tools/libclang/CIndexCodeCompletion.cpp | 6 ++-- clang/unittests/AST/ASTVectorTest.cpp | 5 ++-- clang/unittests/AST/CommentLexer.cpp | 6 ++-- clang/unittests/AST/CommentParser.cpp | 5 ++-- clang/unittests/AST/CommentTextTest.cpp | 2 +- .../Analysis/MacroExpansionContextTest.cpp | 4 +-- .../Analysis/UnsafeBufferUsageTest.cpp | 7 ++--- clang/unittests/Basic/DiagnosticTest.cpp | 14 ++++----- clang/unittests/Basic/SarifTest.cpp | 4 +-- clang/unittests/Basic/SourceManagerTest.cpp | 5 ++-- clang/unittests/Driver/DXCModeTest.cpp | 8 ++--- clang/unittests/Driver/SanitizerArgsTest.cpp | 2 +- .../Driver/SimpleDiagnosticConsumer.h | 5 ++-- clang/unittests/Driver/ToolChainTest.cpp | 30 +++++++++---------- .../Frontend/CompilerInstanceTest.cpp | 4 +-- clang/unittests/Frontend/SearchPathTest.cpp | 2 +- .../unittests/Frontend/TextDiagnosticTest.cpp | 3 +- clang/unittests/Lex/HeaderSearchTest.cpp | 4 +-- clang/unittests/Lex/LexerTest.cpp | 5 ++-- clang/unittests/Lex/ModuleDeclStateTest.cpp | 5 ++-- clang/unittests/Lex/PPCallbacksTest.cpp | 2 +- .../Lex/PPConditionalDirectiveRecordTest.cpp | 5 ++-- .../Lex/PPDependencyDirectivesTest.cpp | 5 ++-- .../unittests/Lex/PPMemoryAllocationsTest.cpp | 5 ++-- .../Parse/ParseHLSLRootSignatureTest.cpp | 5 ++-- clang/unittests/Sema/SemaNoloadLookupTest.cpp | 2 +- .../Serialization/ForceCheckFileInputTest.cpp | 4 +-- .../Serialization/LoadSpecLazilyTest.cpp | 2 +- .../Serialization/ModuleCacheTest.cpp | 8 ++--- .../Serialization/NoCommentsTest.cpp | 2 +- .../PreambleInNamedModulesTest.cpp | 4 +-- .../Serialization/VarDeclConstantInitTest.cpp | 2 +- clang/unittests/Tooling/RewriterTestContext.h | 3 +- clang/unittests/Tooling/Syntax/TokensTest.cpp | 5 ++-- .../unittests/Tooling/Syntax/TreeTestBase.cpp | 2 +- clang/unittests/Tooling/Syntax/TreeTestBase.h | 3 +- flang/lib/Frontend/CompilerInstance.cpp | 6 ++-- flang/tools/flang-driver/driver.cpp | 5 ++-- flang/tools/flang-driver/fc1_main.cpp | 5 ++-- .../Clang/ClangExpressionSourceCode.cpp | 3 +- .../Clang/ClangModulesDeclVendor.cpp | 2 +- .../Language/ClangCommon/ClangHighlighter.cpp | 3 +- .../TypeSystem/Clang/TypeSystemClang.cpp | 5 ++-- 90 files changed, 197 insertions(+), 237 deletions(-) diff --git a/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp b/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp index 062e236d3e51f..76de8bd877d03 100644 --- a/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp +++ b/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp @@ -97,8 +97,7 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv); DiagnosticOptions DiagOpts; - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), DiagOpts); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts); // Determine a formatting style from options. auto FormatStyleOrError = format::getStyle(FormatStyleOpt, FormatStyleConfig, diff --git a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp index 2a8fe2d06d185..2efdd9223dfba 100644 --- a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp +++ b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp @@ -128,9 +128,8 @@ int main(int argc, const char **argv) { LangOptions DefaultLangOptions; DiagnosticOptions DiagOpts; clang::TextDiagnosticPrinter DiagnosticPrinter(errs(), DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), DiagOpts, - &DiagnosticPrinter, false); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts, + &DiagnosticPrinter, false); auto &FileMgr = Tool.getFiles(); SourceManager Sources(Diagnostics, FileMgr); Rewriter Rewrite(Sources, DefaultLangOptions); diff --git a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp index 9f73f47998056..568cb2b83d79a 100644 --- a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp +++ b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp @@ -454,7 +454,7 @@ int includeFixerMain(int argc, const char **argv) { // Set up a new source manager for applying the resulting replacements. DiagnosticOptions DiagOpts; - DiagnosticsEngine Diagnostics(new DiagnosticIDs, DiagOpts); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts); TextDiagnosticPrinter DiagnosticPrinter(outs(), DiagOpts); SourceManager SM(Diagnostics, tool.getFiles()); Diagnostics.setClient(&DiagnosticPrinter, false); diff --git a/clang-tools-extra/clang-move/tool/ClangMove.cpp b/clang-tools-extra/clang-move/tool/ClangMove.cpp index 750eb952714f7..1be3cb1e3b9ca 100644 --- a/clang-tools-extra/clang-move/tool/ClangMove.cpp +++ b/clang-tools-extra/clang-move/tool/ClangMove.cpp @@ -178,9 +178,8 @@ int main(int argc, const char **argv) { DiagnosticOptions DiagOpts; clang::TextDiagnosticPrinter DiagnosticPrinter(errs(), DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), DiagOpts, - &DiagnosticPrinter, false); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts, + &DiagnosticPrinter, false); auto &FileMgr = Tool.getFiles(); SourceManager SM(Diagnostics, FileMgr); Rewriter Rewrite(SM, LangOptions()); diff --git a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp index 03502525417b2..fbfce07bb7512 100644 --- a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp +++ b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp @@ -74,9 +74,8 @@ int main(int argc, const char **argv) { LangOptions DefaultLangOptions; DiagnosticOptions DiagOpts; TextDiagnosticPrinter DiagnosticPrinter(errs(), DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), DiagOpts, - &DiagnosticPrinter, false); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts, + &DiagnosticPrinter, false); auto &FileMgr = Tool.getFiles(); SourceManager Sources(Diagnostics, FileMgr); diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index e84be0461f280..4ae2864d310d0 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -96,8 +96,7 @@ class ErrorReporter { llvm::IntrusiveRefCntPtr BaseFS) : Files(FileSystemOptions(), std::move(BaseFS)), DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), DiagOpts)), - Diags(IntrusiveRefCntPtr(new DiagnosticIDs), DiagOpts, - DiagPrinter), + Diags(DiagnosticIDs::create(), DiagOpts, DiagPrinter), SourceMgr(Diags, Files), Context(Context), ApplyFixes(ApplyFixes) { DiagOpts.ShowColors = Context.getOptions().UseColor.value_or( llvm::sys::Process::StandardOutHasColors()); @@ -570,7 +569,7 @@ runClangTidy(clang::tidy::ClangTidyContext &Context, ClangTidyDiagnosticConsumer DiagConsumer(Context, nullptr, true, ApplyAnyFix); auto DiagOpts = std::make_unique(); - DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, /*ShouldOwnClient=*/false); Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); Tool.setDiagnosticConsumer(&DiagConsumer); diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp index dd3b80510169b..1e4849cdfd2ae 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp @@ -71,7 +71,7 @@ ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks( InMemoryFs(new llvm::vfs::InMemoryFileSystem), Sources(Compiler.getSourceManager()), // Forward the new diagnostics to the original DiagnosticConsumer. - Diags(new DiagnosticIDs, DiagOpts, + Diags(DiagnosticIDs::create(), DiagOpts, new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())), LangOpts(Compiler.getLangOpts()), HSOpts(Compiler.getHeaderSearchOpts()) { // Add a FileSystem containing the extra files needed in place of modular diff --git a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp index 651a63b3aa972..195418d2e2ca2 100644 --- a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp +++ b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp @@ -41,7 +41,7 @@ class ClangTidyPluginAction : public PluginASTAction { new ClangTidyDiagnosticConsumer(*Context, &Compiler.getDiagnostics()); auto DiagOpts = std::make_unique(); auto DiagEngine = std::make_unique( - new DiagnosticIDs, *DiagOpts, DiagConsumer); + DiagnosticIDs::create(), *DiagOpts, DiagConsumer); Context->setDiagnosticsEngine(std::move(DiagOpts), DiagEngine.get()); // Create the AST consumer. diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp index 7b4d63ff197e7..8af9e4649218d 100644 --- a/clang-tools-extra/clangd/Preamble.cpp +++ b/clang-tools-extra/clangd/Preamble.cpp @@ -659,7 +659,7 @@ buildPreamble(PathRef FileName, CompilerInvocation CI, WallTimer PreambleTimer; PreambleTimer.startTimer(); auto BuiltPreamble = PrecompiledPreamble::Build( - CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine, + CI, ContentsBuffer.get(), Bounds, PreambleDiagsEngine, Stats ? TimedFS : StatCacheFS, std::make_shared(), StoreInMemory, /*StoragePath=*/"", CapturedInfo); diff --git a/clang-tools-extra/clangd/SystemIncludeExtractor.cpp b/clang-tools-extra/clangd/SystemIncludeExtractor.cpp index 0b067e8b0b2b2..106de1b84c5c6 100644 --- a/clang-tools-extra/clangd/SystemIncludeExtractor.cpp +++ b/clang-tools-extra/clangd/SystemIncludeExtractor.cpp @@ -254,7 +254,7 @@ bool isValidTarget(llvm::StringRef Triple) { std::shared_ptr TargetOpts(new TargetOptions); TargetOpts->Triple = Triple.str(); DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs, DiagOpts, + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer); llvm::IntrusiveRefCntPtr Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp index 75d0ff244038d..0e411b2034178 100644 --- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp @@ -299,7 +299,7 @@ TEST_F(ConfigCompileTests, DiagnosticSuppression) { "typecheck_bool_condition", "unexpected_friend", "warn_alloca")); clang::DiagnosticOptions DiagOpts; - clang::DiagnosticsEngine DiagEngine(new DiagnosticIDs, DiagOpts, + clang::DiagnosticsEngine DiagEngine(DiagnosticIDs::create(), DiagOpts, new clang::IgnoringDiagConsumer); using Diag = clang::Diagnostic; diff --git a/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp index e39b70224d97c..b6607e940a62f 100644 --- a/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp @@ -45,7 +45,7 @@ TEST(FileEdits, AbsolutePath) { MemFS->addFile(Path, 0, llvm::MemoryBuffer::getMemBuffer("", Path)); FileManager FM(FileSystemOptions(), MemFS); DiagnosticOptions DiagOpts; - DiagnosticsEngine DE(new DiagnosticIDs, DiagOpts); + DiagnosticsEngine DE(DiagnosticIDs::create(), DiagOpts); SourceManager SM(DE, FM); for (const auto *Path : RelPaths) { diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp index 8a24f21d658df..4dd84feac5df4 100644 --- a/clang-tools-extra/modularize/ModularizeUtilities.cpp +++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp @@ -47,7 +47,7 @@ ModularizeUtilities::ModularizeUtilities(std::vector &InputPaths, ProblemFilesPath(ProblemFilesListPath), HasModuleMap(false), MissingHeaderCount(0), // Init clang stuff needed for loading the module map and preprocessing. - LangOpts(new LangOptions()), DiagIDs(new DiagnosticIDs()), + LangOpts(new LangOptions()), DiagIDs(DiagnosticIDs::create()), DC(llvm::errs(), DiagnosticOpts), Diagnostics(new DiagnosticsEngine(DiagIDs, DiagnosticOpts, &DC, false)), TargetOpts(new ModuleMapTargetOptions()), diff --git a/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp b/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp index 87b0d69f4654a..0b9211893a013 100644 --- a/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp +++ b/clang-tools-extra/unittests/clang-apply-replacements/ApplyReplacementsTest.cpp @@ -33,8 +33,7 @@ makeTUDiagnostics(const std::string &MainSourceFile, StringRef DiagnosticName, // before applying. TEST(ApplyReplacementsTest, mergeDiagnosticsWithNoFixes) { DiagnosticOptions DiagOpts; - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), DiagOpts); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts); FileManager Files((FileSystemOptions())); SourceManager SM(Diagnostics, Files); TUReplacements TURs; diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp index d3ca26a19dd63..410cebf90913d 100644 --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp @@ -318,7 +318,8 @@ TEST(CheckOptionsValidation, MissingOptions) { ClangTidyGlobalOptions(), Options)); ClangTidyDiagnosticConsumer DiagConsumer(Context); auto DiagOpts = std::make_unique(); - DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, false); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); TestCheck TestCheck(&Context); EXPECT_FALSE(TestCheck.getLocal("Opt")); @@ -348,7 +349,8 @@ TEST(CheckOptionsValidation, ValidIntOptions) { ClangTidyGlobalOptions(), Options)); ClangTidyDiagnosticConsumer DiagConsumer(Context); auto DiagOpts = std::make_unique(); - DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, false); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); TestCheck TestCheck(&Context); @@ -410,7 +412,8 @@ TEST(ValidConfiguration, ValidEnumOptions) { ClangTidyGlobalOptions(), Options)); ClangTidyDiagnosticConsumer DiagConsumer(Context); auto DiagOpts = std::make_unique(); - DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, false); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); TestCheck TestCheck(&Context); diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h b/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h index 789cc2afb4f0c..89f0f9f2a1f19 100644 --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h @@ -97,7 +97,8 @@ runCheckOnCode(StringRef Code, std::vector *Errors = nullptr, ClangTidyGlobalOptions(), Options)); ClangTidyDiagnosticConsumer DiagConsumer(Context); auto DiagOpts = std::make_unique(); - DiagnosticsEngine DE(new DiagnosticIDs(), *DiagOpts, &DiagConsumer, false); + DiagnosticsEngine DE(DiagnosticIDs::create(), *DiagOpts, &DiagConsumer, + false); Context.setDiagnosticsEngine(std::move(DiagOpts), &DE); std::vector Args(1, "clang-tidy"); diff --git a/clang-tools-extra/unittests/include/common/VirtualFileHelper.h b/clang-tools-extra/unittests/include/common/VirtualFileHelper.h index 86991bb343d8d..cb075f8b77355 100644 --- a/clang-tools-extra/unittests/include/common/VirtualFileHelper.h +++ b/clang-tools-extra/unittests/include/common/VirtualFileHelper.h @@ -32,8 +32,7 @@ class VirtualFileHelper { public: VirtualFileHelper() - : Diagnostics(IntrusiveRefCntPtr(new DiagnosticIDs), - DiagOpts), + : Diagnostics(DiagnosticIDs::create(), DiagOpts), DiagnosticPrinter(llvm::outs(), DiagOpts), Files((FileSystemOptions())) {} diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h index 6ebb7aeb828b7..2f256ae6b22bf 100644 --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -281,6 +281,11 @@ class DiagnosticIDs : public RefCountedBase { DiagnosticIDs(); ~DiagnosticIDs(); + // Convenience method to construct a new refcounted DiagnosticIDs. + static llvm::IntrusiveRefCntPtr create() { + return llvm::makeIntrusiveRefCnt(); + } + /// Return an ID for a diagnostic with the specified format string and /// level. /// diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 1485192e8f1e3..de878ab67eda9 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -443,6 +443,9 @@ class ASTUnit { const DiagnosticsEngine &getDiagnostics() const { return *Diagnostics; } DiagnosticsEngine &getDiagnostics() { return *Diagnostics; } + llvm::IntrusiveRefCntPtr getDiagnosticsPtr() { + return Diagnostics; + } const SourceManager &getSourceManager() const { return *SourceMgr; } SourceManager &getSourceManager() { return *SourceMgr; } @@ -916,8 +919,9 @@ class ASTUnit { bool IncludeCodePatterns, bool IncludeBriefComments, CodeCompleteConsumer &Consumer, std::shared_ptr PCHContainerOps, - DiagnosticsEngine &Diag, LangOptions &LangOpts, - SourceManager &SourceMgr, FileManager &FileMgr, + llvm::IntrusiveRefCntPtr Diag, + LangOptions &LangOpts, SourceManager &SourceMgr, + FileManager &FileMgr, SmallVectorImpl &StoredDiagnostics, SmallVectorImpl &OwnedBuffers, std::unique_ptr Act); diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 72861e573ea34..cd4957f5909dd 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -395,7 +395,7 @@ class CompilerInstance : public ModuleLoader { } /// setDiagnostics - Replace the current diagnostics engine. - void setDiagnostics(DiagnosticsEngine *Value); + void setDiagnostics(llvm::IntrusiveRefCntPtr Value); DiagnosticConsumer &getDiagnosticClient() const { assert(Diagnostics && Diagnostics->getClient() && diff --git a/clang/include/clang/Frontend/PrecompiledPreamble.h b/clang/include/clang/Frontend/PrecompiledPreamble.h index 624df004bf89e..565395b4f3986 100644 --- a/clang/include/clang/Frontend/PrecompiledPreamble.h +++ b/clang/include/clang/Frontend/PrecompiledPreamble.h @@ -84,7 +84,7 @@ class PrecompiledPreamble { static llvm::ErrorOr Build(const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, - DiagnosticsEngine &Diagnostics, + IntrusiveRefCntPtr Diagnostics, IntrusiveRefCntPtr VFS, std::shared_ptr PCHContainerOps, bool StoreInMemory, StringRef StoragePath, diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index b2b1488f9dc8e..45f90cc31339e 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -2381,8 +2381,8 @@ SourceManagerForFile::SourceManagerForFile(StringRef FileName, DiagOpts = std::make_unique(); // This is passed to `SM` as reference, so the pointer has to be referenced // by `Environment` due to the same reason above. - Diagnostics = std::make_unique( - IntrusiveRefCntPtr(new DiagnosticIDs), *DiagOpts); + Diagnostics = + std::make_unique(DiagnosticIDs::create(), *DiagOpts); SourceMgr = std::make_unique(*Diagnostics, *FileMgr); FileEntryRef FE = llvm::cantFail(FileMgr->getFileRef(FileName)); FileID ID = diff --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp index 6d0f042d5accd..fb2a79ab657db 100644 --- a/clang/lib/CrossTU/CrossTranslationUnit.cpp +++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp @@ -563,9 +563,8 @@ CrossTranslationUnitContext::ASTLoader::loadFromDump(StringRef ASTDumpPath) { auto DiagOpts = std::make_shared(); TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), *DiagOpts); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, *DiagOpts, DiagClient)); + auto Diags = llvm::makeIntrusiveRefCnt( + DiagnosticIDs::create(), *DiagOpts, DiagClient); return ASTUnit::LoadFromASTFile( ASTDumpPath, CI.getPCHContainerOperations()->getRawReader(), ASTUnit::LoadEverything, DiagOpts, Diags, CI.getFileSystemOpts(), @@ -607,8 +606,8 @@ CrossTranslationUnitContext::ASTLoader::loadFromSource( auto *DiagClient = new ForwardingDiagnosticConsumer{CI.getDiagnosticClient()}; IntrusiveRefCntPtr DiagID{ CI.getDiagnostics().getDiagnosticIDs()}; - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine{DiagID, *DiagOpts, DiagClient}); + auto Diags = llvm::makeIntrusiveRefCnt(DiagID, *DiagOpts, + DiagClient); return ASTUnit::LoadFromCommandLine( CommandLineArgs.begin(), (CommandLineArgs.end()), diff --git a/clang/lib/Frontend/ASTMerge.cpp b/clang/lib/Frontend/ASTMerge.cpp index a4ce88351e28e..10c10458466bc 100644 --- a/clang/lib/Frontend/ASTMerge.cpp +++ b/clang/lib/Frontend/ASTMerge.cpp @@ -41,10 +41,10 @@ void ASTMergeAction::ExecuteAction() { auto SharedState = std::make_shared( *CI.getASTContext().getTranslationUnitDecl()); for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { - IntrusiveRefCntPtr Diags(new DiagnosticsEngine( + auto Diags = llvm::makeIntrusiveRefCnt( DiagIDs, CI.getDiagnosticOpts(), new ForwardingDiagnosticConsumer(*CI.getDiagnostics().getClient()), - /*ShouldOwnClient=*/true)); + /*ShouldOwnClient=*/true); std::unique_ptr Unit = ASTUnit::LoadFromASTFile( ASTFiles[I], CI.getPCHContainerReader(), ASTUnit::LoadEverything, nullptr, Diags, CI.getFileSystemOpts(), CI.getHeaderSearchOpts()); diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index a99e176291582..66c3392d1d528 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1193,7 +1193,7 @@ bool ASTUnit::Parse(std::shared_ptr PCHContainerOps, // Set up diagnostics, capturing any diagnostics that would // otherwise be dropped. - Clang->setDiagnostics(&getDiagnostics()); + Clang->setDiagnostics(getDiagnosticsPtr()); // Create the target instance. if (!Clang->createTarget()) @@ -1413,7 +1413,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true; llvm::ErrorOr NewPreamble = PrecompiledPreamble::Build( - PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS, + PreambleInvocationIn, MainFileBuffer.get(), Bounds, Diagnostics, VFS, PCHContainerOps, StorePreamblesInMemory, PreambleStoragePath, Callbacks); @@ -1613,7 +1613,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( // Set up diagnostics, capturing any diagnostics that would // otherwise be dropped. - Clang->setDiagnostics(&AST->getDiagnostics()); + Clang->setDiagnostics(AST->getDiagnosticsPtr()); // Create the target instance. if (!Clang->createTarget()) @@ -2200,8 +2200,9 @@ void ASTUnit::CodeComplete( bool IncludeCodePatterns, bool IncludeBriefComments, CodeCompleteConsumer &Consumer, std::shared_ptr PCHContainerOps, - DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, - FileManager &FileMgr, SmallVectorImpl &StoredDiagnostics, + llvm::IntrusiveRefCntPtr Diag, LangOptions &LangOpts, + SourceManager &SourceMgr, FileManager &FileMgr, + SmallVectorImpl &StoredDiagnostics, SmallVectorImpl &OwnedBuffers, std::unique_ptr Act) { if (!Invocation) @@ -2250,11 +2251,11 @@ void ASTUnit::CodeComplete( std::string(Clang->getFrontendOpts().Inputs[0].getFile()); // Set up diagnostics, capturing any diagnostics produced. - Clang->setDiagnostics(&Diag); + Clang->setDiagnostics(Diag); CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All, Clang->getDiagnostics(), &StoredDiagnostics, nullptr); - ProcessWarningOptions(Diag, Inv.getDiagnosticOpts(), + ProcessWarningOptions(*Diag, Inv.getDiagnosticOpts(), FileMgr.getVirtualFileSystem()); // Create the target instance. diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index f9a398dbfb90f..4a19a3384339b 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -118,13 +118,12 @@ IntrusiveRefCntPtr clang::createChainedIncludesSource( TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), CI.getDiagnosticOpts()); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, CI.getDiagnosticOpts(), DiagClient)); + auto Diags = llvm::makeIntrusiveRefCnt( + DiagnosticIDs::create(), CI.getDiagnosticOpts(), DiagClient); auto Clang = std::make_unique( std::move(CInvok), CI.getPCHContainerOperations()); - Clang->setDiagnostics(Diags.get()); + Clang->setDiagnostics(Diags); Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts())); Clang->createFileManager(); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index dde2fba867f66..0df627ec8dc89 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -98,8 +98,9 @@ bool CompilerInstance::shouldBuildGlobalModuleIndex() const { !DisableGeneratingGlobalModuleIndex; } -void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) { - Diagnostics = Value; +void CompilerInstance::setDiagnostics( + llvm::IntrusiveRefCntPtr Value) { + Diagnostics = std::move(Value); } bool CompilerInstance::isSourceNonReproducible() const { @@ -356,9 +357,8 @@ IntrusiveRefCntPtr CompilerInstance::createDiagnostics( llvm::vfs::FileSystem &VFS, DiagnosticOptions &Opts, DiagnosticConsumer *Client, bool ShouldOwnClient, const CodeGenOptions *CodeGenOpts) { - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagID, Opts)); + auto Diags = llvm::makeIntrusiveRefCnt( + DiagnosticIDs::create(), Opts); // Create the diagnostic client for reporting errors or for // implementing -verify. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index dedc9fd7ebf97..adeea731649d8 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -884,7 +884,7 @@ static bool RoundTrip(ParseFn Parse, GenerateFn Generate, // Setup a dummy DiagnosticsEngine. DiagnosticOptions DummyDiagOpts; - DiagnosticsEngine DummyDiags(new DiagnosticIDs(), DummyDiagOpts); + DiagnosticsEngine DummyDiags(DiagnosticIDs::create(), DummyDiagOpts); DummyDiags.setClient(new TextDiagnosticBuffer()); // Run the first parse on the original arguments with the dummy invocation and @@ -2931,7 +2931,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, std::optional IgnoringDiags; if (!Diags) { IgnoringDiagOpts.emplace(); - IgnoringDiags.emplace(new DiagnosticIDs(), *IgnoringDiagOpts, + IgnoringDiags.emplace(DiagnosticIDs::create(), *IgnoringDiagOpts, new IgnoringDiagConsumer()); Diags = &*IgnoringDiags; } diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 2a8d00c31ec41..0fa92aca510d2 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -892,11 +892,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // If we're replaying the build of an AST file, import it and set up // the initial state from its build. if (ReplayASTFile) { - IntrusiveRefCntPtr Diags(&CI.getDiagnostics()); + IntrusiveRefCntPtr Diags = CI.getDiagnosticsPtr(); // The AST unit populates its own diagnostics engine rather than ours. - IntrusiveRefCntPtr ASTDiags(new DiagnosticsEngine( - Diags->getDiagnosticIDs(), Diags->getDiagnosticOptions())); + auto ASTDiags = llvm::makeIntrusiveRefCnt( + Diags->getDiagnosticIDs(), Diags->getDiagnosticOptions()); ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false); // FIXME: What if the input is a memory buffer? @@ -964,7 +964,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, assert(hasASTFileSupport() && "This action does not have AST file support!"); - IntrusiveRefCntPtr Diags(&CI.getDiagnostics()); + IntrusiveRefCntPtr Diags = CI.getDiagnosticsPtr(); // FIXME: What if the input is a memory buffer? StringRef InputFile = Input.getFile(); diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp index 3f3fe3c9937e4..431bd17f7b5c0 100644 --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -412,7 +412,7 @@ PrecompiledPreamble::operator=(PrecompiledPreamble &&) = default; llvm::ErrorOr PrecompiledPreamble::Build( const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, - DiagnosticsEngine &Diagnostics, + IntrusiveRefCntPtr Diagnostics, IntrusiveRefCntPtr VFS, std::shared_ptr PCHContainerOps, bool StoreInMemory, StringRef StoragePath, PreambleCallbacks &Callbacks) { @@ -461,7 +461,7 @@ llvm::ErrorOr PrecompiledPreamble::Build( llvm::CrashRecoveryContextCleanupRegistrar CICleanup( Clang.get()); - Clang->setDiagnostics(&Diagnostics); + Clang->setDiagnostics(Diagnostics); // Create the target instance. if (!Clang->createTarget()) @@ -476,18 +476,18 @@ llvm::ErrorOr PrecompiledPreamble::Build( } // Clear out old caches and data. - Diagnostics.Reset(); - ProcessWarningOptions(Diagnostics, Clang->getDiagnosticOpts(), *VFS); + Diagnostics->Reset(); + ProcessWarningOptions(*Diagnostics, Clang->getDiagnosticOpts(), *VFS); - VFS = - createVFSFromCompilerInvocation(Clang->getInvocation(), Diagnostics, VFS); + VFS = createVFSFromCompilerInvocation(Clang->getInvocation(), *Diagnostics, + VFS); // Create a file manager object to provide access to and cache the filesystem. Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS)); // Create the source manager. Clang->setSourceManager( - new SourceManager(Diagnostics, Clang->getFileManager())); + new SourceManager(*Diagnostics, Clang->getFileManager())); auto PreambleDepCollector = std::make_shared(); Clang->addDependencyCollector(PreambleDepCollector); diff --git a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp index 2abe68b29538e..e7528ea128b4b 100644 --- a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp +++ b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -781,10 +781,9 @@ DiagnosticsEngine *SDiagsWriter::getMetaDiags() { // to be distinct from the engine the writer was being added to and would // normally not be used. if (!State->MetaDiagnostics) { - IntrusiveRefCntPtr IDs(new DiagnosticIDs()); auto Client = new TextDiagnosticPrinter(llvm::errs(), State->DiagOpts); - State->MetaDiagnostics = - std::make_unique(IDs, State->DiagOpts, Client); + State->MetaDiagnostics = std::make_unique( + DiagnosticIDs::create(), State->DiagOpts, Client); } return State->MetaDiagnostics.get(); } diff --git a/clang/lib/Interpreter/CodeCompletion.cpp b/clang/lib/Interpreter/CodeCompletion.cpp index 3ab35ccd880eb..5a0a6431acb30 100644 --- a/clang/lib/Interpreter/CodeCompletion.cpp +++ b/clang/lib/Interpreter/CodeCompletion.cpp @@ -379,7 +379,7 @@ void ReplCodeCompleter::codeComplete(CompilerInstance *InterpCI, AU->setOwnsRemappedFileBuffers(false); AU->CodeComplete(CodeCompletionFileName, 1, Col, RemappedFiles, false, false, false, consumer, - std::make_shared(), *diag, + std::make_shared(), diag, InterpCI->getLangOpts(), AU->getSourceManager(), AU->getFileManager(), sd, tb, std::move(Act)); } diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index ed3bae59a144c..9509c88003b56 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -86,7 +86,6 @@ GetCC1Arguments(DiagnosticsEngine *Diagnostics, static llvm::Expected> CreateCI(const llvm::opt::ArgStringList &Argv) { std::unique_ptr Clang(new CompilerInstance()); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); // Register the support for object-file-wrapped Clang modules. // FIXME: Clang should register these container operations automatically. @@ -98,7 +97,7 @@ CreateCI(const llvm::opt::ArgStringList &Argv) { // a well formed diagnostic object. DiagnosticOptions DiagOpts; TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; - DiagnosticsEngine Diags(DiagID, DiagOpts, DiagsBuffer); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagsBuffer); bool Success = CompilerInvocation::CreateFromArgs( Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags); @@ -174,11 +173,10 @@ IncrementalCompilerBuilder::create(std::string TT, // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); std::unique_ptr DiagOpts = CreateAndPopulateDiagOpts(ClangArgv); TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; - DiagnosticsEngine Diags(DiagID, *DiagOpts, DiagsBuffer); + DiagnosticsEngine Diags(DiagnosticIDs::create(), *DiagOpts, DiagsBuffer); driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags); Driver.setCheckInputsExist(false); // the input comes from mem buffers diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e1ffe6c4a8eef..7ee2aa8101de2 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -612,8 +612,7 @@ bool PCHValidator::ReadDiagnosticOptions(DiagnosticOptions &DiagOpts, bool Complain) { DiagnosticsEngine &ExistingDiags = PP.getDiagnostics(); IntrusiveRefCntPtr DiagIDs(ExistingDiags.getDiagnosticIDs()); - IntrusiveRefCntPtr Diags( - new DiagnosticsEngine(DiagIDs, DiagOpts)); + auto Diags = llvm::makeIntrusiveRefCnt(DiagIDs, DiagOpts); // This should never fail, because we would have processed these options // before writing them to an ASTFile. ProcessWarningOptions(*Diags, DiagOpts, diff --git a/clang/lib/Tooling/CompilationDatabase.cpp b/clang/lib/Tooling/CompilationDatabase.cpp index d5fc21601ae40..860457acced85 100644 --- a/clang/lib/Tooling/CompilationDatabase.cpp +++ b/clang/lib/Tooling/CompilationDatabase.cpp @@ -241,9 +241,8 @@ static bool stripPositionalArgs(std::vector Args, llvm::raw_string_ostream Output(ErrorMsg); TextDiagnosticPrinter DiagnosticPrinter(Output, DiagOpts); UnusedInputDiagConsumer DiagClient(DiagnosticPrinter); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), DiagOpts, - &DiagClient, false); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts, &DiagClient, + false); // The clang executable path isn't required since the jobs the driver builds // will not be executed. diff --git a/clang/lib/Tooling/Core/Replacement.cpp b/clang/lib/Tooling/Core/Replacement.cpp index 1506218d88553..6452a828d11ab 100644 --- a/clang/lib/Tooling/Core/Replacement.cpp +++ b/clang/lib/Tooling/Core/Replacement.cpp @@ -585,8 +585,7 @@ llvm::Expected applyAllReplacements(StringRef Code, new llvm::vfs::InMemoryFileSystem); FileManager Files(FileSystemOptions(), InMemoryFileSystem); DiagnosticOptions DiagOpts; - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs), DiagOpts); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts); SourceManager SourceMgr(Diagnostics, Files); Rewriter Rewrite(SourceMgr, LangOptions()); InMemoryFileSystem->addFile( diff --git a/clang/lib/Tooling/Refactoring.cpp b/clang/lib/Tooling/Refactoring.cpp index d2b0b37fd808e..9b1af2377108a 100644 --- a/clang/lib/Tooling/Refactoring.cpp +++ b/clang/lib/Tooling/Refactoring.cpp @@ -39,9 +39,8 @@ int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) { LangOptions DefaultLangOptions; DiagnosticOptions DiagOpts; TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), DiagOpts, - &DiagnosticPrinter, false); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts, + &DiagnosticPrinter, false); SourceManager Sources(Diagnostics, getFiles()); Rewriter Rewrite(Sources, DefaultLangOptions); diff --git a/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp b/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp index 0b621b849e92f..ddb2944e3820b 100644 --- a/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp +++ b/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp @@ -134,10 +134,9 @@ GetDiagnosticsEngine(DiagnosticOptions &DiagOpts) { TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagOpts); DiagClient->setPrefix("clang-extdef-mappping"); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr DiagEngine( - new DiagnosticsEngine(DiagID, DiagOpts, DiagClient)); + auto DiagEngine = llvm::makeIntrusiveRefCnt( + DiagnosticIDs::create(), DiagOpts, DiagClient); Diags.swap(DiagEngine); // Retain this one time so it's not destroyed by ASTUnit::LoadFromASTFile diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 24ad3cb42254d..5f6106051b1fd 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -241,8 +241,7 @@ static bool fillRanges(MemoryBuffer *Code, new llvm::vfs::InMemoryFileSystem); FileManager Files(FileSystemOptions(), InMemoryFileSystem); DiagnosticOptions DiagOpts; - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs), DiagOpts); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts); SourceManager Sources(Diagnostics, Files); const auto ID = createInMemoryFile("", *Code, Sources, Files, InMemoryFileSystem.get()); @@ -517,9 +516,8 @@ static bool format(StringRef FileName, bool ErrorOnIncompleteFormat = false) { DiagnosticOptions DiagOpts; ClangFormatDiagConsumer IgnoreDiagnostics; - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs), DiagOpts, - &IgnoreDiagnostics, false); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts, + &IgnoreDiagnostics, false); SourceManager Sources(Diagnostics, Files); FileID ID = createInMemoryFile(AssumedFileName, *Code, Sources, Files, InMemoryFileSystem.get()); diff --git a/clang/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp b/clang/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp index 98925c00260f1..8259361bf6f83 100644 --- a/clang/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp +++ b/clang/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp @@ -33,9 +33,8 @@ void clang_fuzzer::HandleCXX(const std::string &S, new FileManager(FileSystemOptions())); IgnoringDiagConsumer Diags; DiagnosticOptions DiagOpts; - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), DiagOpts, - &Diags, false); + DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts, &Diags, + false); std::unique_ptr Invocation( tooling::newInvocation(&Diagnostics, CC1Args, /*BinaryName=*/nullptr)); std::unique_ptr Input = @@ -49,4 +48,3 @@ void clang_fuzzer::HandleCXX(const std::string &S, action->runInvocation(std::move(Invocation), Files.get(), PCHContainerOps, &Diags); } - diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index 6bc642f971a48..8a9c497338700 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -78,8 +78,8 @@ static bool run(ArrayRef Args, const char *ProgName) { ArrayRef(Args).slice(1), MissingArgIndex, MissingArgCount); ParseDiagnosticArgs(DiagOpts, ParsedArgs); - IntrusiveRefCntPtr Diag = new clang::DiagnosticsEngine( - new clang::DiagnosticIDs(), DiagOpts, + auto Diag = llvm::makeIntrusiveRefCnt( + clang::DiagnosticIDs::create(), DiagOpts, new clang::TextDiagnosticPrinter(llvm::errs(), DiagOpts)); // Create file manager for all file operations and holding in-memory generated diff --git a/clang/tools/diagtool/ShowEnabledWarnings.cpp b/clang/tools/diagtool/ShowEnabledWarnings.cpp index 0d1455d270436..bea0288c09358 100644 --- a/clang/tools/diagtool/ShowEnabledWarnings.cpp +++ b/clang/tools/diagtool/ShowEnabledWarnings.cpp @@ -55,7 +55,6 @@ static char getCharForLevel(DiagnosticsEngine::Level Level) { static IntrusiveRefCntPtr createDiagnostics(unsigned int argc, char **argv) { - IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs()); DiagnosticOptions DiagOpts; // Buffer diagnostics from argument parsing so that we can output them using a @@ -67,7 +66,8 @@ createDiagnostics(unsigned int argc, char **argv) { Args.push_back("diagtool"); Args.append(argv, argv + argc); CreateInvocationOptions CIOpts; - CIOpts.Diags = new DiagnosticsEngine(DiagIDs, DiagOpts, DiagsBuffer); + CIOpts.Diags = llvm::makeIntrusiveRefCnt( + DiagnosticIDs::create(), DiagOpts, DiagsBuffer); std::unique_ptr Invocation = createInvocation(Args, CIOpts); if (!Invocation) diff --git a/clang/tools/diagtool/TreeView.cpp b/clang/tools/diagtool/TreeView.cpp index 7e47c748af959..13b80150e6041 100644 --- a/clang/tools/diagtool/TreeView.cpp +++ b/clang/tools/diagtool/TreeView.cpp @@ -32,7 +32,7 @@ class TreePrinter { static bool isIgnored(unsigned DiagID) { // FIXME: This feels like a hack. static DiagnosticOptions DiagOpts; - static clang::DiagnosticsEngine Diags(new DiagnosticIDs, DiagOpts); + static clang::DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts); return Diags.isIgnored(DiagID, SourceLocation()); } diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index d5fc4db7a0e68..5588c7f17276b 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -221,7 +221,7 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { ensureSufficientStack(); CompileJobCache JobCache; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); // Register the support for object-file-wrapped Clang modules. auto PCHOps = std::make_shared(); diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 3b4a4b54392df..ba6bafa51db17 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -682,8 +682,7 @@ int cc1as_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(errs(), DiagOpts); DiagClient->setPrefix("clang -cc1as"); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - DiagnosticsEngine Diags(DiagID, DiagOpts, DiagClient); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagClient); // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. diff --git a/clang/tools/driver/cc1gen_reproducer_main.cpp b/clang/tools/driver/cc1gen_reproducer_main.cpp index 47e1a1ed28f81..50e348d8f9a50 100644 --- a/clang/tools/driver/cc1gen_reproducer_main.cpp +++ b/clang/tools/driver/cc1gen_reproducer_main.cpp @@ -121,8 +121,8 @@ generateReproducerForInvocationArguments(ArrayRef Argv, DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - DiagnosticsEngine Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, + new IgnoringDiagConsumer()); auto VFS = llvm::vfs::getRealFileSystem(); ProcessWarningOptions(Diags, DiagOpts, *VFS, /*ReportDiags=*/false); Driver TheDriver(ToolContext.Path, llvm::sys::getDefaultTargetTriple(), Diags, diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index aca3577b410b0..048507c457b26 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -370,9 +370,7 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) { new TextDiagnosticPrinter(llvm::errs(), *DiagOpts); FixupDiagPrefixExeName(DiagClient, ProgName); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - - DiagnosticsEngine Diags(DiagID, *DiagOpts, DiagClient); + DiagnosticsEngine Diags(DiagnosticIDs::create(), *DiagOpts, DiagClient); if (!DiagOpts->DiagnosticSerializationFile.empty()) { auto SerializedConsumer = diff --git a/clang/tools/libclang/CIndexCodeCompletion.cpp b/clang/tools/libclang/CIndexCodeCompletion.cpp index f20385f047ec7..16dfafd82399f 100644 --- a/clang/tools/libclang/CIndexCodeCompletion.cpp +++ b/clang/tools/libclang/CIndexCodeCompletion.cpp @@ -357,8 +357,8 @@ static std::atomic CodeCompletionResultObjects; AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults( IntrusiveRefCntPtr FileMgr) : CXCodeCompleteResults(), - Diag(new DiagnosticsEngine( - IntrusiveRefCntPtr(new DiagnosticIDs), DiagOpts)), + Diag(llvm::makeIntrusiveRefCnt(DiagnosticIDs::create(), + DiagOpts)), FileMgr(std::move(FileMgr)), SourceMgr(new SourceManager(*Diag, *this->FileMgr)), CodeCompletionAllocator( @@ -764,7 +764,7 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, RemappedFiles, (options & CXCodeComplete_IncludeMacros), (options & CXCodeComplete_IncludeCodePatterns), IncludeBriefComments, Capture, - CXXIdx->getPCHContainerOperations(), *Results->Diag, + CXXIdx->getPCHContainerOperations(), Results->Diag, Results->LangOpts, *Results->SourceMgr, *Results->FileMgr, Results->Diagnostics, Results->TemporaryBuffers, /*SyntaxOnlyAction=*/nullptr); diff --git a/clang/unittests/AST/ASTVectorTest.cpp b/clang/unittests/AST/ASTVectorTest.cpp index 66003b49eccb2..03da54967f1ed 100644 --- a/clang/unittests/AST/ASTVectorTest.cpp +++ b/clang/unittests/AST/ASTVectorTest.cpp @@ -26,14 +26,13 @@ namespace { class ASTVectorTest : public ::testing::Test { protected: ASTVectorTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), Idents(LangOpts, nullptr), Ctxt(LangOpts, SourceMgr, Idents, Sels, Builtins, TU_Complete) {} FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/AST/CommentLexer.cpp b/clang/unittests/AST/CommentLexer.cpp index dc10dae7a2f8f..99f469173964e 100644 --- a/clang/unittests/AST/CommentLexer.cpp +++ b/clang/unittests/AST/CommentLexer.cpp @@ -27,13 +27,12 @@ namespace { class CommentLexerTest : public ::testing::Test { protected: CommentLexerTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), Traits(Allocator, CommentOptions()) {} FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; @@ -2006,4 +2005,3 @@ TEST_F(CommentLexerTest, MultipleComments) { } // end namespace comments } // end namespace clang - diff --git a/clang/unittests/AST/CommentParser.cpp b/clang/unittests/AST/CommentParser.cpp index 67fabe5181798..3bd2bdb692131 100644 --- a/clang/unittests/AST/CommentParser.cpp +++ b/clang/unittests/AST/CommentParser.cpp @@ -33,13 +33,12 @@ const bool MY_DEBUG = true; class CommentParserTest : public ::testing::Test { protected: CommentParserTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), Traits(Allocator, CommentOptions()) {} FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/AST/CommentTextTest.cpp b/clang/unittests/AST/CommentTextTest.cpp index 84ec51a308360..675173c162586 100644 --- a/clang/unittests/AST/CommentTextTest.cpp +++ b/clang/unittests/AST/CommentTextTest.cpp @@ -44,7 +44,7 @@ class CommentTextTest : public ::testing::Test { // shouldn't matter. RawComment Comment(SourceMgr, CommentRange, EmptyOpts, /*Merged=*/true); DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs, DiagOpts); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts); return Comment.getFormattedText(SourceMgr, Diags); } }; diff --git a/clang/unittests/Analysis/MacroExpansionContextTest.cpp b/clang/unittests/Analysis/MacroExpansionContextTest.cpp index 9874ea687f3ed..6687edc4ad986 100644 --- a/clang/unittests/Analysis/MacroExpansionContextTest.cpp +++ b/clang/unittests/Analysis/MacroExpansionContextTest.cpp @@ -35,8 +35,7 @@ class MacroExpansionContextTest : public ::testing::Test { MacroExpansionContextTest() : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), FileMgr(FileSystemOptions(), InMemoryFileSystem), - DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions()) { TargetOpts->Triple = "x86_64-pc-linux-unknown"; Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); @@ -45,7 +44,6 @@ class MacroExpansionContextTest : public ::testing::Test { IntrusiveRefCntPtr InMemoryFileSystem; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Analysis/UnsafeBufferUsageTest.cpp b/clang/unittests/Analysis/UnsafeBufferUsageTest.cpp index 9da2c58970b84..f795918c743ee 100644 --- a/clang/unittests/Analysis/UnsafeBufferUsageTest.cpp +++ b/clang/unittests/Analysis/UnsafeBufferUsageTest.cpp @@ -12,13 +12,12 @@ namespace { class UnsafeBufferUsageTest : public ::testing::Test { protected: UnsafeBufferUsageTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr) {} FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; @@ -58,4 +57,4 @@ TEST_F(UnsafeBufferUsageTest, FixItHintsConflict) { Fixes = {H1, H2, H3, MkDummyHint(2, 23) /* overlaps H1, H2, and H3 */}; EXPECT_TRUE(internal::anyConflict(Fixes, SourceMgr)); -} \ No newline at end of file +} diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp index b0a034e9af1cd..4b3af00c3b0ce 100644 --- a/clang/unittests/Basic/DiagnosticTest.cpp +++ b/clang/unittests/Basic/DiagnosticTest.cpp @@ -47,7 +47,7 @@ using testing::IsEmpty; // Check that DiagnosticErrorTrap works with SuppressAllDiagnostics. TEST(DiagnosticTest, suppressAndTrap) { DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs(), DiagOpts, + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()); Diags.setSuppressAllDiagnostics(true); @@ -78,7 +78,7 @@ TEST(DiagnosticTest, suppressAndTrap) { TEST(DiagnosticTest, fatalsAsError) { for (unsigned FatalsAsError = 0; FatalsAsError != 2; ++FatalsAsError) { DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs(), DiagOpts, + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()); Diags.setFatalsAsError(FatalsAsError); @@ -102,7 +102,7 @@ TEST(DiagnosticTest, fatalsAsError) { TEST(DiagnosticTest, tooManyErrorsIsAlwaysFatal) { DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs(), DiagOpts, + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()); Diags.setFatalsAsError(true); @@ -119,7 +119,7 @@ TEST(DiagnosticTest, tooManyErrorsIsAlwaysFatal) { // Check that soft RESET works as intended TEST(DiagnosticTest, softReset) { DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs(), DiagOpts, + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()); unsigned numWarnings = 0U, numErrors = 0U; @@ -143,7 +143,7 @@ TEST(DiagnosticTest, softReset) { TEST(DiagnosticTest, diagnosticError) { DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs(), DiagOpts, + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()); PartialDiagnostic::DiagStorageAllocator Alloc; llvm::Expected> Value = DiagnosticError::create( @@ -166,7 +166,7 @@ TEST(DiagnosticTest, diagnosticError) { TEST(DiagnosticTest, storedDiagEmptyWarning) { DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs(), DiagOpts); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts); class CaptureDiagnosticConsumer : public DiagnosticConsumer { public: @@ -197,7 +197,7 @@ class SuppressionMappingTest : public testing::Test { llvm::IntrusiveRefCntPtr FS = llvm::makeIntrusiveRefCnt(); DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags{new DiagnosticIDs(), DiagOpts}; + DiagnosticsEngine Diags{DiagnosticIDs::create(), DiagOpts}; llvm::ArrayRef diags() { return CaptureConsumer.StoredDiags; diff --git a/clang/unittests/Basic/SarifTest.cpp b/clang/unittests/Basic/SarifTest.cpp index ad9f8ecc208a4..da2c775ee0304 100644 --- a/clang/unittests/Basic/SarifTest.cpp +++ b/clang/unittests/Basic/SarifTest.cpp @@ -43,13 +43,11 @@ class SarifDocumentWriterTest : public ::testing::Test { SarifDocumentWriterTest() : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), FileMgr(FileSystemOptions(), InMemoryFileSystem), - DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr) {} IntrusiveRefCntPtr InMemoryFileSystem; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Basic/SourceManagerTest.cpp b/clang/unittests/Basic/SourceManagerTest.cpp index cbe047b5e599a..04b23dd13ba3e 100644 --- a/clang/unittests/Basic/SourceManagerTest.cpp +++ b/clang/unittests/Basic/SourceManagerTest.cpp @@ -40,8 +40,8 @@ namespace { class SourceManagerTest : public ::testing::Test { protected: SourceManagerTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); @@ -49,7 +49,6 @@ class SourceManagerTest : public ::testing::Test { FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Driver/DXCModeTest.cpp b/clang/unittests/Driver/DXCModeTest.cpp index f6845939d04b4..8eb1929bd7526 100644 --- a/clang/unittests/Driver/DXCModeTest.cpp +++ b/clang/unittests/Driver/DXCModeTest.cpp @@ -55,8 +55,6 @@ static void validateTargetProfile( } TEST(DxcModeTest, TargetProfileValidation) { - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); @@ -65,7 +63,7 @@ TEST(DxcModeTest, TargetProfileValidation) { auto *DiagConsumer = new SimpleDiagnosticConsumer; DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagConsumer); validateTargetProfile("-Tvs_6_0", "dxilv1.0--shadermodel6.0-vertex", InMemoryFileSystem, Diags); @@ -105,8 +103,6 @@ TEST(DxcModeTest, TargetProfileValidation) { } TEST(DxcModeTest, ValidatorVersionValidation) { - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); @@ -115,7 +111,7 @@ TEST(DxcModeTest, ValidatorVersionValidation) { auto *DiagConsumer = new SimpleDiagnosticConsumer; DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagConsumer); Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem); std::unique_ptr C(TheDriver.BuildCompilation( {"clang", "--driver-mode=dxc", "-Tlib_6_7", "foo.hlsl"})); diff --git a/clang/unittests/Driver/SanitizerArgsTest.cpp b/clang/unittests/Driver/SanitizerArgsTest.cpp index b8bfc6806da6d..b3da389248a72 100644 --- a/clang/unittests/Driver/SanitizerArgsTest.cpp +++ b/clang/unittests/Driver/SanitizerArgsTest.cpp @@ -53,7 +53,7 @@ class SanitizerArgsTest : public ::testing::Test { assert(!DriverInstance && "Running twice is not allowed"); DiagnosticOptions DiagOpts; - DiagnosticsEngine Diags(new DiagnosticIDs, DiagOpts, + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, new TextDiagnosticPrinter(llvm::errs(), DiagOpts)); DriverInstance.emplace(ClangBinary, "x86_64-unknown-linux-gnu", Diags, "clang LLVM compiler", prepareFS(ExtraFiles)); diff --git a/clang/unittests/Driver/SimpleDiagnosticConsumer.h b/clang/unittests/Driver/SimpleDiagnosticConsumer.h index c3772baade566..ba31a839a827e 100644 --- a/clang/unittests/Driver/SimpleDiagnosticConsumer.h +++ b/clang/unittests/Driver/SimpleDiagnosticConsumer.h @@ -42,13 +42,12 @@ struct SimpleDiagnosticConsumer : public clang::DiagnosticConsumer { // for testing situations where it will only ever be used for emitting // diagnostics, such as being passed to `MultilibSet::select`. inline clang::driver::Driver diagnostic_test_driver() { - llvm::IntrusiveRefCntPtr DiagID( - new clang::DiagnosticIDs()); llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); auto *DiagConsumer = new SimpleDiagnosticConsumer; clang::DiagnosticOptions DiagOpts; - clang::DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer); + clang::DiagnosticsEngine Diags(clang::DiagnosticIDs::create(), DiagOpts, + DiagConsumer); return clang::driver::Driver("/bin/clang", "", Diags, "", InMemoryFileSystem); } diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp index 670090a01b0d3..3aff69c981531 100644 --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -40,7 +40,7 @@ namespace { TEST(ToolChainTest, VFSGCCInstallation) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); @@ -137,7 +137,7 @@ TEST(ToolChainTest, VFSGCCInstallation) { TEST(ToolChainTest, VFSGCCInstallationRelativeDir) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); IntrusiveRefCntPtr InMemoryFileSystem( @@ -176,7 +176,7 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) { TEST(ToolChainTest, VFSSolarisMultiGCCInstallation) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); @@ -340,7 +340,7 @@ MATCHER_P(jobHasArgs, Substr, "") { TEST(ToolChainTest, VFSGnuLibcxxPathNoSysroot) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); @@ -371,7 +371,7 @@ TEST(ToolChainTest, VFSGnuLibcxxPathNoSysroot) { TEST(ToolChainTest, DefaultDriverMode) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); IntrusiveRefCntPtr InMemoryFileSystem( @@ -402,7 +402,7 @@ TEST(ToolChainTest, DefaultDriverMode) { EXPECT_TRUE(CLDriver.IsCLMode()); } TEST(ToolChainTest, InvalidArgument) { - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); @@ -517,7 +517,7 @@ TEST(ToolChainTest, GetTargetAndMode) { TEST(ToolChainTest, CommandOutput) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); IntrusiveRefCntPtr InMemoryFileSystem( @@ -545,7 +545,7 @@ TEST(ToolChainTest, CommandOutput) { TEST(ToolChainTest, PostCallback) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); IntrusiveRefCntPtr InMemoryFileSystem( @@ -598,7 +598,7 @@ TEST(ToolChainTest, UEFICallingConventionTest) { TEST(ToolChainTest, UEFIDefaultDebugFormatTest) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); IntrusiveRefCntPtr InMemoryFileSystem( @@ -640,7 +640,7 @@ struct SimpleDiagnosticConsumer : public DiagnosticConsumer { TEST(ToolChainTest, ConfigFileSearch) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); IntrusiveRefCntPtr FS( @@ -717,7 +717,7 @@ struct FileSystemWithError : public llvm::vfs::FileSystem { TEST(ToolChainTest, ConfigFileError) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); std::unique_ptr DiagConsumer( new SimpleDiagnosticConsumer()); DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false); @@ -738,7 +738,7 @@ TEST(ToolChainTest, ConfigFileError) { TEST(ToolChainTest, BadConfigFile) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); std::unique_ptr DiagConsumer( new SimpleDiagnosticConsumer()); DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false); @@ -812,7 +812,7 @@ TEST(ToolChainTest, BadConfigFile) { TEST(ToolChainTest, ConfigInexistentInclude) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); std::unique_ptr DiagConsumer( new SimpleDiagnosticConsumer()); DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false); @@ -853,7 +853,7 @@ TEST(ToolChainTest, ConfigInexistentInclude) { TEST(ToolChainTest, ConfigRecursiveInclude) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); std::unique_ptr DiagConsumer( new SimpleDiagnosticConsumer()); DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false); @@ -899,7 +899,7 @@ TEST(ToolChainTest, ConfigRecursiveInclude) { TEST(ToolChainTest, NestedConfigFile) { DiagnosticOptions DiagOpts; - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); IntrusiveRefCntPtr FS( diff --git a/clang/unittests/Frontend/CompilerInstanceTest.cpp b/clang/unittests/Frontend/CompilerInstanceTest.cpp index 459a3864887e1..7c1b6539095fa 100644 --- a/clang/unittests/Frontend/CompilerInstanceTest.cpp +++ b/clang/unittests/Frontend/CompilerInstanceTest.cpp @@ -71,7 +71,7 @@ TEST(CompilerInstance, DefaultVFSOverlayFromInvocation) { // Create a minimal CompilerInstance which should use the VFS we specified // in the CompilerInvocation (as we don't explicitly set our own). CompilerInstance Instance(std::move(CInvok)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); Instance.createFileManager(); // Check if the virtual file exists which means that our VFS is used by the @@ -135,7 +135,7 @@ TEST(CompilerInstance, MultipleInputsCleansFileIDs) { ASSERT_TRUE(CInvok) << "could not create compiler invocation"; CompilerInstance Instance(std::move(CInvok)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); Instance.createFileManager(VFS); // Run once for `a.cc` and then for `a.h`. This makes sure we get the same diff --git a/clang/unittests/Frontend/SearchPathTest.cpp b/clang/unittests/Frontend/SearchPathTest.cpp index c74a5c75fada5..afea2ddf411b0 100644 --- a/clang/unittests/Frontend/SearchPathTest.cpp +++ b/clang/unittests/Frontend/SearchPathTest.cpp @@ -40,7 +40,7 @@ namespace { class SearchPathTest : public ::testing::Test { protected: SearchPathTest() - : Diags(new DiagnosticIDs(), DiagOpts, new IgnoringDiagConsumer()), + : Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), VFS(new llvm::vfs::InMemoryFileSystem), FileMgr(FileSystemOptions(), VFS), SourceMgr(Diags, FileMgr), Invocation(std::make_unique()) {} diff --git a/clang/unittests/Frontend/TextDiagnosticTest.cpp b/clang/unittests/Frontend/TextDiagnosticTest.cpp index 8fd8187134b63..622dbc5883067 100644 --- a/clang/unittests/Frontend/TextDiagnosticTest.cpp +++ b/clang/unittests/Frontend/TextDiagnosticTest.cpp @@ -36,9 +36,8 @@ TEST(TextDiagnostic, ShowLine) { // Create dummy FileManager and SourceManager. FileSystemOptions FSOpts; FileManager FileMgr(FSOpts); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs); DiagnosticOptions DiagEngineOpts; - DiagnosticsEngine DiagEngine(DiagID, DiagEngineOpts, + DiagnosticsEngine DiagEngine(DiagnosticIDs::create(), DiagEngineOpts, new IgnoringDiagConsumer()); SourceManager SrcMgr(DiagEngine, FileMgr); diff --git a/clang/unittests/Lex/HeaderSearchTest.cpp b/clang/unittests/Lex/HeaderSearchTest.cpp index 9903c1246d33d..6d7c588efa0ed 100644 --- a/clang/unittests/Lex/HeaderSearchTest.cpp +++ b/clang/unittests/Lex/HeaderSearchTest.cpp @@ -29,8 +29,7 @@ class HeaderSearchTest : public ::testing::Test { protected: HeaderSearchTest() : VFS(new llvm::vfs::InMemoryFileSystem), FileMgr(FileMgrOpts, VFS), - DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions), Search(HSOpts, SourceMgr, Diags, LangOpts, Target.get()) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; @@ -80,7 +79,6 @@ class HeaderSearchTest : public ::testing::Test { IntrusiveRefCntPtr VFS; FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp index bb6404c434485..c51cd0d2bfdaa 100644 --- a/clang/unittests/Lex/LexerTest.cpp +++ b/clang/unittests/Lex/LexerTest.cpp @@ -41,8 +41,8 @@ using testing::ElementsAre; class LexerTest : public ::testing::Test { protected: LexerTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); @@ -102,7 +102,6 @@ class LexerTest : public ::testing::Test { FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Lex/ModuleDeclStateTest.cpp b/clang/unittests/Lex/ModuleDeclStateTest.cpp index 0c03cfd6d0f89..ac2ddfaf52cd0 100644 --- a/clang/unittests/Lex/ModuleDeclStateTest.cpp +++ b/clang/unittests/Lex/ModuleDeclStateTest.cpp @@ -54,8 +54,8 @@ class CheckNamedModuleImportingCB : public PPCallbacks { class ModuleDeclStateTest : public ::testing::Test { protected: ModuleDeclStateTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-unknown-linux-gnu"; Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); @@ -94,7 +94,6 @@ class ModuleDeclStateTest : public ::testing::Test { FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Lex/PPCallbacksTest.cpp b/clang/unittests/Lex/PPCallbacksTest.cpp index af86c1888f2c7..f76ba793c7258 100644 --- a/clang/unittests/Lex/PPCallbacksTest.cpp +++ b/clang/unittests/Lex/PPCallbacksTest.cpp @@ -135,7 +135,7 @@ class PPCallbacksTest : public ::testing::Test { PPCallbacksTest() : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), FileMgr(FileSystemOptions(), InMemoryFileSystem), - DiagID(new DiagnosticIDs()), + DiagID(DiagnosticIDs::create()), Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions()) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; diff --git a/clang/unittests/Lex/PPConditionalDirectiveRecordTest.cpp b/clang/unittests/Lex/PPConditionalDirectiveRecordTest.cpp index 54c1d020aa0ea..4a88bd4d3586f 100644 --- a/clang/unittests/Lex/PPConditionalDirectiveRecordTest.cpp +++ b/clang/unittests/Lex/PPConditionalDirectiveRecordTest.cpp @@ -29,8 +29,8 @@ namespace { class PPConditionalDirectiveRecordTest : public ::testing::Test { protected: PPConditionalDirectiveRecordTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); @@ -38,7 +38,6 @@ class PPConditionalDirectiveRecordTest : public ::testing::Test { FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp index 061cb136a552a..08d9b4f811234 100644 --- a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp +++ b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp @@ -31,8 +31,8 @@ namespace { class PPDependencyDirectivesTest : public ::testing::Test { protected: PPDependencyDirectivesTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-macos12"; Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); @@ -40,7 +40,6 @@ class PPDependencyDirectivesTest : public ::testing::Test { FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Lex/PPMemoryAllocationsTest.cpp b/clang/unittests/Lex/PPMemoryAllocationsTest.cpp index 4d83003e28b36..f873774eb2019 100644 --- a/clang/unittests/Lex/PPMemoryAllocationsTest.cpp +++ b/clang/unittests/Lex/PPMemoryAllocationsTest.cpp @@ -27,8 +27,8 @@ namespace { class PPMemoryAllocationsTest : public ::testing::Test { protected: PPMemoryAllocationsTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + : FileMgr(FileMgrOpts), + Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); @@ -36,7 +36,6 @@ class PPMemoryAllocationsTest : public ::testing::Test { FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; DiagnosticsEngine Diags; SourceManager SourceMgr; diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index 4b24800489c8e..31cbd05bc6582 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -71,8 +71,8 @@ class ExpectedDiagConsumer : public DiagnosticConsumer { class ParseHLSLRootSignatureTest : public ::testing::Test { protected: ParseHLSLRootSignatureTest() - : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), - Consumer(new ExpectedDiagConsumer()), Diags(DiagID, DiagOpts, Consumer), + : FileMgr(FileMgrOpts), Consumer(new ExpectedDiagConsumer()), + Diags(DiagnosticIDs::create(), DiagOpts, Consumer), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { // This is an arbitrarily chosen target triple to create the target info. TargetOpts->Triple = "dxil"; @@ -114,7 +114,6 @@ class ParseHLSLRootSignatureTest : public ::testing::Test { FileSystemOptions FileMgrOpts; FileManager FileMgr; - IntrusiveRefCntPtr DiagID; DiagnosticOptions DiagOpts; ExpectedDiagConsumer *Consumer; DiagnosticsEngine Diags; diff --git a/clang/unittests/Sema/SemaNoloadLookupTest.cpp b/clang/unittests/Sema/SemaNoloadLookupTest.cpp index 5a04f42697b99..e565372698e5e 100644 --- a/clang/unittests/Sema/SemaNoloadLookupTest.cpp +++ b/clang/unittests/Sema/SemaNoloadLookupTest.cpp @@ -82,7 +82,7 @@ class NoloadLookupTest : public ::testing::Test { EXPECT_TRUE(Invocation); CompilerInstance Instance(std::move(Invocation)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); Instance.getFrontendOpts().OutputFile = CacheBMIPath; GenerateReducedModuleInterfaceAction Action; EXPECT_TRUE(Instance.ExecuteAction(Action)); diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp index 970eeef3c953e..92ff76b016283 100644 --- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp +++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp @@ -87,7 +87,7 @@ export int aa = 43; Buf->release(); CompilerInstance Instance(std::move(Invocation)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); Instance.getFrontendOpts().OutputFile = BMIPath; @@ -122,7 +122,7 @@ export int aa = 43; CompilerInstance Clang(std::move(Invocation)); - Clang.setDiagnostics(Diags.get()); + Clang.setDiagnostics(Diags); FileManager *FM = Clang.createFileManager(CIOpts.VFS); Clang.createSourceManager(*FM); diff --git a/clang/unittests/Serialization/LoadSpecLazilyTest.cpp b/clang/unittests/Serialization/LoadSpecLazilyTest.cpp index 631547431ce7c..d7b55491fddac 100644 --- a/clang/unittests/Serialization/LoadSpecLazilyTest.cpp +++ b/clang/unittests/Serialization/LoadSpecLazilyTest.cpp @@ -80,7 +80,7 @@ class LoadSpecLazilyTest : public ::testing::Test { EXPECT_TRUE(Invocation); CompilerInstance Instance(std::move(Invocation)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); Instance.getFrontendOpts().OutputFile = CacheBMIPath; // Avoid memory leaks. Instance.getFrontendOpts().DisableFree = false; diff --git a/clang/unittests/Serialization/ModuleCacheTest.cpp b/clang/unittests/Serialization/ModuleCacheTest.cpp index de6e13a738cb8..1f64401a08314 100644 --- a/clang/unittests/Serialization/ModuleCacheTest.cpp +++ b/clang/unittests/Serialization/ModuleCacheTest.cpp @@ -121,7 +121,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPath) { createInvocationAndEnableFree(Args, CIOpts); ASSERT_TRUE(Invocation); CompilerInstance Instance(std::move(Invocation)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); SyntaxOnlyAction Action; ASSERT_TRUE(Instance.ExecuteAction(Action)); ASSERT_FALSE(Diags->hasErrorOccurred()); @@ -145,7 +145,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPath) { CompilerInstance Instance2(std::move(Invocation2), Instance.getPCHContainerOperations(), &Instance.getModuleCache()); - Instance2.setDiagnostics(Diags.get()); + Instance2.setDiagnostics(Diags); SyntaxOnlyAction Action2; ASSERT_FALSE(Instance2.ExecuteAction(Action2)); ASSERT_TRUE(Diags->hasErrorOccurred()); @@ -171,7 +171,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPathAllowErrors) { createInvocationAndEnableFree(Args, CIOpts); ASSERT_TRUE(Invocation); CompilerInstance Instance(std::move(Invocation)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); SyntaxOnlyAction Action; ASSERT_TRUE(Instance.ExecuteAction(Action)); ASSERT_FALSE(Diags->hasErrorOccurred()); @@ -189,7 +189,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPathAllowErrors) { CompilerInstance Instance2(std::move(Invocation2), Instance.getPCHContainerOperations(), &Instance.getModuleCache()); - Instance2.setDiagnostics(Diags.get()); + Instance2.setDiagnostics(Diags); SyntaxOnlyAction Action2; ASSERT_FALSE(Instance2.ExecuteAction(Action2)); ASSERT_TRUE(Diags->hasErrorOccurred()); diff --git a/clang/unittests/Serialization/NoCommentsTest.cpp b/clang/unittests/Serialization/NoCommentsTest.cpp index 05efeef990d43..ed96c7c7959a0 100644 --- a/clang/unittests/Serialization/NoCommentsTest.cpp +++ b/clang/unittests/Serialization/NoCommentsTest.cpp @@ -99,7 +99,7 @@ void foo() {} ASSERT_TRUE(Invocation); CompilerInstance Instance(std::move(Invocation)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); Instance.getFrontendOpts().OutputFile = CacheBMIPath; GenerateReducedModuleInterfaceAction Action; ASSERT_TRUE(Instance.ExecuteAction(Action)); diff --git a/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp b/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp index c43520f79b02c..f9d7736a77ee1 100644 --- a/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp +++ b/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp @@ -101,7 +101,7 @@ export using ::E; PreambleCallbacks Callbacks; llvm::ErrorOr BuiltPreamble = PrecompiledPreamble::Build( - *Invocation, Buffer.get(), Bounds, *Diags, VFS, + *Invocation, Buffer.get(), Bounds, Diags, VFS, std::make_shared(), /*StoreInMemory=*/false, /*StoragePath=*/TestDir, Callbacks); @@ -112,7 +112,7 @@ export using ::E; BuiltPreamble->OverridePreamble(*Invocation, VFS, Buffer.get()); auto Clang = std::make_unique(std::move(Invocation)); - Clang->setDiagnostics(Diags.get()); + Clang->setDiagnostics(Diags); if (auto VFSWithRemapping = createVFSFromCompilerInvocation( Clang->getInvocation(), Clang->getDiagnostics(), VFS)) diff --git a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp index 5b2988ed26336..743f851fc5fe1 100644 --- a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp +++ b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp @@ -106,7 +106,7 @@ export namespace Fibonacci Invocation->getFrontendOpts().DisableFree = false; CompilerInstance Instance(std::move(Invocation)); - Instance.setDiagnostics(Diags.get()); + Instance.setDiagnostics(Diags); std::string CacheBMIPath = llvm::Twine(TestDir + "/Cached.pcm").str(); Instance.getFrontendOpts().OutputFile = CacheBMIPath; diff --git a/clang/unittests/Tooling/RewriterTestContext.h b/clang/unittests/Tooling/RewriterTestContext.h index 2d697e276c5e8..3ac99a4c47e5f 100644 --- a/clang/unittests/Tooling/RewriterTestContext.h +++ b/clang/unittests/Tooling/RewriterTestContext.h @@ -49,8 +49,7 @@ struct RewriterDiagnosticConsumer : public DiagnosticConsumer { class RewriterTestContext { public: RewriterTestContext() - : Diagnostics(IntrusiveRefCntPtr(new DiagnosticIDs), - DiagOpts), + : Diagnostics(DiagnosticIDs::create(), DiagOpts), InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), OverlayFileSystem( new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())), diff --git a/clang/unittests/Tooling/Syntax/TokensTest.cpp b/clang/unittests/Tooling/Syntax/TokensTest.cpp index b5f44454e862d..e3da8eb45dafa 100644 --- a/clang/unittests/Tooling/Syntax/TokensTest.cpp +++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp @@ -133,7 +133,7 @@ class TokenCollectorTest : public ::testing::Test { CI->getPreprocessorOpts().addRemappedFile( FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release()); CompilerInstance Compiler(std::move(CI)); - Compiler.setDiagnostics(Diags.get()); + Compiler.setDiagnostics(Diags); Compiler.setFileManager(FileMgr.get()); Compiler.setSourceManager(SourceMgr.get()); @@ -250,7 +250,8 @@ class TokenCollectorTest : public ::testing::Test { // Data fields. DiagnosticOptions DiagOpts; llvm::IntrusiveRefCntPtr Diags = - new DiagnosticsEngine(new DiagnosticIDs, DiagOpts); + llvm::makeIntrusiveRefCnt(DiagnosticIDs::create(), + DiagOpts); IntrusiveRefCntPtr FS = new llvm::vfs::InMemoryFileSystem; llvm::IntrusiveRefCntPtr FileMgr = diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp index 9f22b1d64c913..4a25863b03245 100644 --- a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp @@ -152,7 +152,7 @@ SyntaxTreeTest::buildTree(StringRef Code, const TestClangConfig &ClangConfig) { Invocation->getPreprocessorOpts().addRemappedFile( FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release()); CompilerInstance Compiler(Invocation); - Compiler.setDiagnostics(Diags.get()); + Compiler.setDiagnostics(Diags); Compiler.setFileManager(FileMgr.get()); Compiler.setSourceManager(SourceMgr.get()); diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.h b/clang/unittests/Tooling/Syntax/TreeTestBase.h index 6110cffa708d9..f38380a5fdddb 100644 --- a/clang/unittests/Tooling/Syntax/TreeTestBase.h +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.h @@ -42,7 +42,8 @@ class SyntaxTreeTest : public ::testing::Test, // Data fields. DiagnosticOptions DiagOpts; IntrusiveRefCntPtr Diags = - new DiagnosticsEngine(new DiagnosticIDs, DiagOpts); + llvm::makeIntrusiveRefCnt(DiagnosticIDs::create(), + DiagOpts); IntrusiveRefCntPtr FS = new llvm::vfs::InMemoryFileSystem; IntrusiveRefCntPtr FileMgr = diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp index 2e0f91fb0521c..cd8dddad05282 100644 --- a/flang/lib/Frontend/CompilerInstance.cpp +++ b/flang/lib/Frontend/CompilerInstance.cpp @@ -233,10 +233,8 @@ clang::IntrusiveRefCntPtr CompilerInstance::createDiagnostics(clang::DiagnosticOptions &opts, clang::DiagnosticConsumer *client, bool shouldOwnClient) { - clang::IntrusiveRefCntPtr diagID( - new clang::DiagnosticIDs()); - clang::IntrusiveRefCntPtr diags( - new clang::DiagnosticsEngine(diagID, opts)); + auto diags = llvm::makeIntrusiveRefCnt( + clang::DiagnosticIDs::create(), opts); // Create the diagnostic client for reporting errors or for // implementing -verify. diff --git a/flang/tools/flang-driver/driver.cpp b/flang/tools/flang-driver/driver.cpp index 3a2dffc66428f..8321b165ba5bb 100644 --- a/flang/tools/flang-driver/driver.cpp +++ b/flang/tools/flang-driver/driver.cpp @@ -123,15 +123,14 @@ int main(int argc, const char **argv) { // Create DiagnosticsEngine for the compiler driver std::unique_ptr diagOpts = createAndPopulateDiagOpts(args); - llvm::IntrusiveRefCntPtr diagID( - new clang::DiagnosticIDs()); Fortran::frontend::TextDiagnosticPrinter *diagClient = new Fortran::frontend::TextDiagnosticPrinter(llvm::errs(), *diagOpts); diagClient->setPrefix( std::string(llvm::sys::path::stem(getExecutablePath(args[0])))); - clang::DiagnosticsEngine diags(diagID, *diagOpts, diagClient); + clang::DiagnosticsEngine diags(clang::DiagnosticIDs::create(), *diagOpts, + diagClient); // Prepare the driver clang::driver::Driver theDriver(driverPath, diff --git a/flang/tools/flang-driver/fc1_main.cpp b/flang/tools/flang-driver/fc1_main.cpp index f2cd513d0028c..d9b103dbe6c8c 100644 --- a/flang/tools/flang-driver/fc1_main.cpp +++ b/flang/tools/flang-driver/fc1_main.cpp @@ -65,10 +65,9 @@ int fc1_main(llvm::ArrayRef argv, const char *argv0) { // Create CompilerInvocation - use a dedicated instance of DiagnosticsEngine // for parsing the arguments - llvm::IntrusiveRefCntPtr diagID( - new clang::DiagnosticIDs()); clang::DiagnosticOptions diagOpts; - clang::DiagnosticsEngine diags(diagID, diagOpts, diagsBuffer); + clang::DiagnosticsEngine diags(clang::DiagnosticIDs::create(), diagOpts, + diagsBuffer); bool success = CompilerInvocation::createFromArgs(flang->getInvocation(), argv, diags, argv0); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index 06f3a7efac7a2..ff9ed9c27f70f 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -260,9 +260,8 @@ TokenVerifier::TokenVerifier(std::string body) { // Let's build the actual source code Clang needs and setup some utility // objects. - llvm::IntrusiveRefCntPtr diag_ids(new DiagnosticIDs()); DiagnosticOptions diags_opts; - DiagnosticsEngine diags(diag_ids, diags_opts); + DiagnosticsEngine diags(DiagnosticIDs::create(), diags_opts); clang::SourceManager SM(diags, file_mgr); auto buf = llvm::MemoryBuffer::getMemBuffer(body); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index cfd1e8efabf08..7c6ec4e2f5a26 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -746,7 +746,7 @@ ClangModulesDeclVendor::Create(Target &target) { // Make sure clang uses the same VFS as LLDB. instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); - instance->setDiagnostics(diagnostics_engine.get()); + instance->setDiagnostics(diagnostics_engine); std::unique_ptr action(new clang::SyntaxOnlyAction); diff --git a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp index 8cc5714d0f0fc..9cb5ea3078995 100644 --- a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp +++ b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp @@ -162,9 +162,8 @@ void ClangHighlighter::Highlight(const HighlightStyle &options, // Let's build the actual source code Clang needs and setup some utility // objects. std::string full_source = previous_lines.str() + line.str(); - llvm::IntrusiveRefCntPtr diag_ids(new DiagnosticIDs()); DiagnosticOptions diags_opts; - DiagnosticsEngine diags(diag_ids, diags_opts); + DiagnosticsEngine diags(DiagnosticIDs::create(), diags_opts); clang::SourceManager SM(diags, file_mgr); auto buf = llvm::MemoryBuffer::getMemBuffer(full_source); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index a44be15aca3e6..c119c927cf531 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -682,10 +682,9 @@ void TypeSystemClang::CreateASTContext() { m_file_manager_up = std::make_unique( file_system_options, FileSystem::Instance().GetVirtualFileSystem()); - llvm::IntrusiveRefCntPtr diag_id_sp(new DiagnosticIDs()); m_diagnostic_options_up = std::make_unique(); - m_diagnostics_engine_up = - std::make_unique(diag_id_sp, *m_diagnostic_options_up); + m_diagnostics_engine_up = std::make_unique( + DiagnosticIDs::create(), *m_diagnostic_options_up); m_source_manager_up = std::make_unique( *m_diagnostics_engine_up, *m_file_manager_up); From 3c62cabb60cecf8e169e05223dc26ba649e8d8ce Mon Sep 17 00:00:00 2001 From: James Y Knight Date: Fri, 1 Aug 2025 22:23:30 -0400 Subject: [PATCH 04/15] NFC: Clean up of IntrusiveRefCntPtr construction from raw pointers. (#151782) This commit handles the following types: - clang::ExternalASTSource - clang::TargetInfo - clang::ASTContext - clang::SourceManager - clang::FileManager Part of cleanup #151026 (cherry picked from commit 4205da0f130cf86ae6b89bfc36723e7ddba9b0b7) Conflicts: clang/lib/Frontend/ASTUnit.cpp clang/lib/Frontend/ChainedIncludesSource.cpp clang/lib/Frontend/CompilerInstance.cpp --- .../clang-include-fixer/IncludeFixer.cpp | 2 +- clang/include/clang/AST/ASTContext.h | 6 ++ clang/include/clang/Frontend/ASTUnit.h | 18 +++-- .../include/clang/Frontend/CompilerInstance.h | 6 +- clang/include/clang/Frontend/Utils.h | 2 +- .../clang/Sema/MultiplexExternalSemaSource.h | 9 +-- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Frontend/ASTUnit.cpp | 74 ++++++++++--------- clang/lib/Frontend/ChainedIncludesSource.cpp | 22 +++--- clang/lib/Frontend/CompilerInstance.cpp | 50 +++++++------ clang/lib/Frontend/FrontendAction.cpp | 33 ++++----- clang/lib/Frontend/PrecompiledPreamble.cpp | 7 +- clang/lib/Interpreter/CodeCompletion.cpp | 12 ++- .../lib/Sema/MultiplexExternalSemaSource.cpp | 25 +++---- clang/lib/Sema/Sema.cpp | 11 +-- .../StaticAnalyzer/Frontend/ModelInjector.cpp | 14 ++-- clang/lib/Tooling/Tooling.cpp | 12 +-- .../clang-installapi/ClangInstallAPI.cpp | 7 +- clang/tools/libclang/CIndexCodeCompletion.cpp | 9 ++- clang/tools/libclang/CXIndexDataConsumer.cpp | 6 +- clang/tools/libclang/CXIndexDataConsumer.h | 2 +- clang/tools/libclang/Indexing.cpp | 7 +- clang/unittests/AST/ASTImporterTest.cpp | 7 +- clang/unittests/AST/ExternalASTSourceTest.cpp | 9 ++- clang/unittests/Frontend/ASTUnitTest.cpp | 6 +- .../unittests/Frontend/FrontendActionTest.cpp | 3 +- clang/unittests/Frontend/PCHPreambleTest.cpp | 2 +- .../Frontend/ReparseWorkingDirTest.cpp | 3 +- .../unittests/Sema/ExternalSemaSourceTest.cpp | 22 +++--- clang/unittests/Support/TimeProfilerTest.cpp | 5 +- clang/unittests/Tooling/Syntax/TokensTest.cpp | 8 +- .../unittests/Tooling/Syntax/TreeTestBase.cpp | 4 +- clang/unittests/Tooling/Syntax/TreeTestBase.h | 4 +- clang/unittests/Tooling/ToolingTest.cpp | 28 +++---- .../ExpressionParser/Clang/ASTUtils.cpp | 5 +- .../Plugins/ExpressionParser/Clang/ASTUtils.h | 24 +++--- .../ExpressionParser/Clang/ClangASTSource.h | 4 +- .../Clang/ClangExpressionParser.cpp | 14 ++-- .../AppleObjCRuntime/AppleObjCDeclVendor.cpp | 6 +- .../TypeSystem/Clang/TypeSystemClang.cpp | 18 ++--- .../TypeSystem/Clang/TypeSystemClang.h | 2 +- 41 files changed, 270 insertions(+), 240 deletions(-) diff --git a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp index 7b0e4ecda8214..30bb313524cbe 100644 --- a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp +++ b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp @@ -53,7 +53,7 @@ class Action : public clang::ASTFrontendAction { Compiler->createSema(getTranslationUnitKind(), CompletionConsumer); SemaSource->setCompilerInstance(Compiler); - Compiler->getSema().addExternalSource(SemaSource.get()); + Compiler->getSema().addExternalSource(SemaSource); clang::ParseAST(Compiler->getSema(), Compiler->getFrontendOpts().ShowStats, Compiler->getFrontendOpts().SkipFunctionBodies); diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ebe539bca7909..b0abb491fc3fc 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1385,6 +1385,12 @@ class ASTContext : public RefCountedBase { return ExternalSource.get(); } + /// Retrieve a pointer to the external AST source associated + /// with this AST context, if any. Returns as an IntrusiveRefCntPtr. + IntrusiveRefCntPtr getExternalSourcePtr() const { + return ExternalSource; + } + /// Attach an AST mutation listener to the AST context. /// /// The AST mutation listener provides the ability to track modifications to diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index de878ab67eda9..5069c73ad6d99 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -449,6 +449,9 @@ class ASTUnit { const SourceManager &getSourceManager() const { return *SourceMgr; } SourceManager &getSourceManager() { return *SourceMgr; } + llvm::IntrusiveRefCntPtr getSourceManagerPtr() { + return SourceMgr; + } const Preprocessor &getPreprocessor() const { return *PP; } Preprocessor &getPreprocessor() { return *PP; } @@ -456,8 +459,11 @@ class ASTUnit { const ASTContext &getASTContext() const { return *Ctx; } ASTContext &getASTContext() { return *Ctx; } + llvm::IntrusiveRefCntPtr getASTContextPtr() { return Ctx; } - void setASTContext(ASTContext *ctx) { Ctx = ctx; } + void setASTContext(llvm::IntrusiveRefCntPtr ctx) { + Ctx = std::move(ctx); + } void setPreprocessor(std::shared_ptr pp); /// Enable source-range based diagnostic messages. @@ -493,6 +499,7 @@ class ASTUnit { const FileManager &getFileManager() const { return *FileMgr; } FileManager &getFileManager() { return *FileMgr; } + IntrusiveRefCntPtr getFileManagerPtr() { return FileMgr; } const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } @@ -801,8 +808,8 @@ class ASTUnit { std::shared_ptr CI, std::shared_ptr PCHContainerOps, std::shared_ptr DiagOpts, - IntrusiveRefCntPtr Diags, FileManager *FileMgr, - bool OnlyLocalDecls = false, + IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr FileMgr, bool OnlyLocalDecls = false, CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None, unsigned PrecompilePreambleAfterNParses = 0, TranslationUnitKind TUKind = TU_Complete, @@ -920,8 +927,9 @@ class ASTUnit { CodeCompleteConsumer &Consumer, std::shared_ptr PCHContainerOps, llvm::IntrusiveRefCntPtr Diag, - LangOptions &LangOpts, SourceManager &SourceMgr, - FileManager &FileMgr, + LangOptions &LangOpts, + llvm::IntrusiveRefCntPtr SourceMgr, + llvm::IntrusiveRefCntPtr FileMgr, SmallVectorImpl &StoredDiagnostics, SmallVectorImpl &OwnedBuffers, std::unique_ptr Act); diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index cd4957f5909dd..97a03bde858c0 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -478,7 +478,7 @@ class CompilerInstance : public ModuleLoader { } /// Replace the current file manager and virtual file system. - void setFileManager(FileManager *Value); + void setFileManager(IntrusiveRefCntPtr Value); /// Set the output manager. void setOutputBackend(IntrusiveRefCntPtr NewOutputs); @@ -518,7 +518,7 @@ class CompilerInstance : public ModuleLoader { } /// setSourceManager - Replace the current source manager. - void setSourceManager(SourceManager *Value); + void setSourceManager(llvm::IntrusiveRefCntPtr Value); /// @} /// @name Preprocessor @@ -563,7 +563,7 @@ class CompilerInstance : public ModuleLoader { } /// setASTContext - Replace the current AST context. - void setASTContext(ASTContext *Value); + void setASTContext(llvm::IntrusiveRefCntPtr Value); /// Replace the current Sema; the compiler instance takes ownership /// of S. diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h index 4e76006905f5a..88a43c6f4aad1 100644 --- a/clang/include/clang/Frontend/Utils.h +++ b/clang/include/clang/Frontend/Utils.h @@ -198,7 +198,7 @@ void AttachHeaderIncludeGen(Preprocessor &PP, /// memory, mainly for testing. IntrusiveRefCntPtr createChainedIncludesSource(CompilerInstance &CI, - IntrusiveRefCntPtr &Reader); + IntrusiveRefCntPtr &OutReader); /// Optional inputs to createInvocation. struct CreateInvocationOptions { diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 391c2177d75ec..8bcaa121b3039 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -40,7 +40,7 @@ class MultiplexExternalSemaSource : public ExternalSemaSource { static char ID; private: - SmallVector Sources; + SmallVector, 2> Sources; public: /// Constructs a new multiplexing external sema source and appends the @@ -49,15 +49,14 @@ class MultiplexExternalSemaSource : public ExternalSemaSource { ///\param[in] S1 - A non-null (old) ExternalSemaSource. ///\param[in] S2 - A non-null (new) ExternalSemaSource. /// - MultiplexExternalSemaSource(ExternalSemaSource *S1, ExternalSemaSource *S2); - - ~MultiplexExternalSemaSource() override; + MultiplexExternalSemaSource(llvm::IntrusiveRefCntPtr S1, + llvm::IntrusiveRefCntPtr S2); /// Appends new source to the source list. /// ///\param[in] Source - An ExternalSemaSource. /// - void AddSource(ExternalSemaSource *Source); + void AddSource(llvm::IntrusiveRefCntPtr Source); //===--------------------------------------------------------------------===// // ExternalASTSource. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 9bfc3b0774d89..8c4d598b9f442 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1136,7 +1136,7 @@ class Sema final : public SemaBase { /// ///\param[in] E - A non-null external sema source. /// - void addExternalSource(ExternalSemaSource *E); + void addExternalSource(IntrusiveRefCntPtr E); /// Print out statistics about the semantic analysis. void PrintStats() const; diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 66c3392d1d528..3a5339353bf67 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -822,11 +822,10 @@ std::unique_ptr ASTUnit::LoadFromASTFile( AST->CaptureDiagnostics = CaptureDiagnostics; AST->DiagOpts = DiagOpts; AST->Diagnostics = Diags; - AST->FileMgr = new FileManager(FileSystemOpts, VFS); + AST->FileMgr = llvm::makeIntrusiveRefCnt(FileSystemOpts, VFS); AST->UserFilesAreVolatile = UserFilesAreVolatile; - AST->SourceMgr = new SourceManager(AST->getDiagnostics(), - AST->getFileManager(), - UserFilesAreVolatile); + AST->SourceMgr = llvm::makeIntrusiveRefCnt( + AST->getDiagnostics(), AST->getFileManager(), UserFilesAreVolatile); AST->ModCache = createCrossProcessModuleCache(); AST->HSOpts = std::make_unique(HSOpts); AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front()); @@ -849,17 +848,19 @@ std::unique_ptr ASTUnit::LoadFromASTFile( Preprocessor &PP = *AST->PP; if (ToLoad >= LoadASTOnly) - AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(), - PP.getIdentifierTable(), PP.getSelectorTable(), - PP.getBuiltinInfo(), - AST->getTranslationUnitKind()); + AST->Ctx = llvm::makeIntrusiveRefCnt( + *AST->LangOpts, AST->getSourceManager(), PP.getIdentifierTable(), + PP.getSelectorTable(), PP.getBuiltinInfo(), + AST->getTranslationUnitKind()); DisableValidationForModuleKind disableValid = DisableValidationForModuleKind::None; if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) disableValid = DisableValidationForModuleKind::All; - AST->Reader = new ASTReader( - PP, *AST->ModCache, AST->Ctx.get(), PCHContainerRdr, {}, /*isysroot=*/"", + AST->Reader = llvm::makeIntrusiveRefCnt( + PP, *AST->ModCache, AST->Ctx.get(), PCHContainerRdr, + ArrayRef>(), + /*isysroot=*/"", /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors); unsigned Counter = 0; @@ -1180,9 +1181,11 @@ bool ASTUnit::Parse(std::shared_ptr PCHContainerOps, // changed above in AddImplicitPreamble. If VFS is nullptr, rely on // createFileManager to create one. if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) - Clang->setFileManager(&*FileMgr); - else - FileMgr = Clang->createFileManager(std::move(VFS)); + Clang->setFileManager(FileMgr); + else { + Clang->createFileManager(std::move(VFS)); + FileMgr = Clang->getFileManagerPtr(); + } // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -1215,15 +1218,15 @@ bool ASTUnit::Parse(std::shared_ptr PCHContainerOps, ResetForParse(); - SourceMgr = new SourceManager(getDiagnostics(), *FileMgr, - UserFilesAreVolatile); + SourceMgr = llvm::makeIntrusiveRefCnt( + getDiagnostics(), *FileMgr, +UserFilesAreVolatile); if (!OverrideMainBuffer) { checkAndRemoveNonDriverDiags(StoredDiagnostics); TopLevelDeclsInPreamble.clear(); } // Create the source manager. - Clang->setSourceManager(&getSourceManager()); + Clang->setSourceManager(getSourceManagerPtr()); // If the main file has been overridden due to the use of a preamble, // make that override happen and introduce the preamble. @@ -1488,13 +1491,13 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) { TheSema = CI.takeSema(); Consumer = CI.takeASTConsumer(); if (CI.hasASTContext()) - Ctx = &CI.getASTContext(); + Ctx = CI.getASTContextPtr(); if (CI.hasPreprocessor()) PP = CI.getPreprocessorPtr(); CI.setSourceManager(nullptr); CI.setFileManager(nullptr); if (CI.hasTarget()) - Target = &CI.getTarget(); + Target = CI.getTargetPtr(); Reader = CI.getASTReader(); HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure(); if (Invocation != CI.getInvocationPtr()) { @@ -1544,10 +1547,11 @@ ASTUnit::create(std::shared_ptr CI, AST->Diagnostics = Diags; AST->FileSystemOpts = CI->getFileSystemOpts(); AST->Invocation = std::move(CI); - AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); + AST->FileMgr = + llvm::makeIntrusiveRefCnt(AST->FileSystemOpts, VFS); AST->UserFilesAreVolatile = UserFilesAreVolatile; - AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr, - UserFilesAreVolatile); + AST->SourceMgr = llvm::makeIntrusiveRefCnt( + AST->getDiagnostics(), *AST->FileMgr, UserFilesAreVolatile); AST->ModCache = createCrossProcessModuleCache(); return AST; @@ -1635,10 +1639,10 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( AST->Reader = nullptr; // Create a file manager object to provide access to and cache the filesystem. - Clang->setFileManager(&AST->getFileManager()); + Clang->setFileManager(AST->getFileManagerPtr()); // Create the source manager. - Clang->setSourceManager(&AST->getSourceManager()); + Clang->setSourceManager(AST->getSourceManagerPtr()); FrontendAction *Act = Action; @@ -1732,8 +1736,9 @@ std::unique_ptr ASTUnit::LoadFromCompilerInvocation( std::shared_ptr CI, std::shared_ptr PCHContainerOps, std::shared_ptr DiagOpts, - IntrusiveRefCntPtr Diags, FileManager *FileMgr, - bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, + IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr FileMgr, bool OnlyLocalDecls, + CaptureDiagsKind CaptureDiagnostics, unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile) { @@ -1840,7 +1845,8 @@ std::unique_ptr ASTUnit::LoadFromCommandLine( AST->Diagnostics = Diags; AST->FileSystemOpts = CI->getFileSystemOpts(); VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS); - AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); + AST->FileMgr = + llvm::makeIntrusiveRefCnt(AST->FileSystemOpts, VFS); AST->StorePreamblesInMemory = StorePreamblesInMemory; AST->PreambleStoragePath = PreambleStoragePath; AST->ModCache = createCrossProcessModuleCache(); @@ -2201,7 +2207,8 @@ void ASTUnit::CodeComplete( CodeCompleteConsumer &Consumer, std::shared_ptr PCHContainerOps, llvm::IntrusiveRefCntPtr Diag, LangOptions &LangOpts, - SourceManager &SourceMgr, FileManager &FileMgr, + llvm::IntrusiveRefCntPtr SourceMgr, + llvm::IntrusiveRefCntPtr FileMgr, SmallVectorImpl &StoredDiagnostics, SmallVectorImpl &OwnedBuffers, std::unique_ptr Act) { @@ -2256,7 +2263,7 @@ void ASTUnit::CodeComplete( Clang->getDiagnostics(), &StoredDiagnostics, nullptr); ProcessWarningOptions(*Diag, Inv.getDiagnosticOpts(), - FileMgr.getVirtualFileSystem()); + FileMgr->getVirtualFileSystem()); // Create the target instance. if (!Clang->createTarget()) { @@ -2273,8 +2280,8 @@ void ASTUnit::CodeComplete( "IR inputs not support here!"); // Use the source and file managers that we were given. - Clang->setFileManager(&FileMgr); - Clang->setSourceManager(&SourceMgr); + Clang->setFileManager(FileMgr); + Clang->setSourceManager(SourceMgr); // Remap files. PreprocessorOpts.clearRemappedFiles(); @@ -2292,7 +2299,7 @@ void ASTUnit::CodeComplete( auto getUniqueID = [&FileMgr](StringRef Filename) -> std::optional { - if (auto Status = FileMgr.getVirtualFileSystem().status(Filename)) + if (auto Status = FileMgr->getVirtualFileSystem().status(Filename)) return Status->getUniqueID(); return std::nullopt; }; @@ -2313,7 +2320,8 @@ void ASTUnit::CodeComplete( std::unique_ptr OverrideMainBuffer; if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) { OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( - PCHContainerOps, Inv, &FileMgr.getVirtualFileSystem(), false, Line - 1); + PCHContainerOps, Inv, FileMgr->getVirtualFileSystemPtr(), false, + Line - 1); } // If the main file has been overridden due to the use of a preamble, @@ -2323,7 +2331,7 @@ void ASTUnit::CodeComplete( "No preamble was built, but OverrideMainBuffer is not null"); IntrusiveRefCntPtr VFS = - &FileMgr.getVirtualFileSystem(); + FileMgr->getVirtualFileSystemPtr(); Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS, OverrideMainBuffer.get()); // FIXME: there is no way to update VFS if it was changed by diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index 4a19a3384339b..5d1cd15fdeadf 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -53,17 +53,16 @@ class ChainedIncludesSource : public ExternalSemaSource { }; } // end anonymous namespace -static ASTReader * +static llvm::IntrusiveRefCntPtr createASTReader(CompilerInstance &CI, StringRef pchFile, SmallVectorImpl> &MemBufs, SmallVectorImpl &bufNames, ASTDeserializationListener *deserialListener = nullptr) { Preprocessor &PP = CI.getPreprocessor(); - std::unique_ptr Reader; - Reader.reset(new ASTReader( + auto Reader = llvm::makeIntrusiveRefCnt( PP, CI.getModuleCache(), &CI.getASTContext(), CI.getPCHContainerReader(), - /*Extensions=*/{}, - /*isysroot=*/"", DisableValidationForModuleKind::PCH)); + /*Extensions=*/ArrayRef>(), + /*isysroot=*/"", DisableValidationForModuleKind::PCH); for (unsigned ti = 0; ti < bufNames.size(); ++ti) { StringRef sr(bufNames[ti]); Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti])); @@ -74,7 +73,7 @@ createASTReader(CompilerInstance &CI, StringRef pchFile, case ASTReader::Success: // Set the predefines buffer as suggested by the PCH reader. PP.setPredefines(Reader->getSuggestedPredefines()); - return Reader.release(); + return Reader; case ASTReader::Failure: case ASTReader::Missing: @@ -87,8 +86,9 @@ createASTReader(CompilerInstance &CI, StringRef pchFile, return nullptr; } -IntrusiveRefCntPtr clang::createChainedIncludesSource( - CompilerInstance &CI, IntrusiveRefCntPtr &Reader) { +IntrusiveRefCntPtr +clang::createChainedIncludesSource(CompilerInstance &CI, + IntrusiveRefCntPtr &OutReader) { std::vector &includes = CI.getPreprocessorOpts().ChainedIncludes; assert(!includes.empty() && "No '-chain-include' in options!"); @@ -185,12 +185,12 @@ IntrusiveRefCntPtr clang::createChainedIncludesSource( assert(!SerialBufs.empty()); std::string pchName = includes.back() + ".pch-final"; serialBufNames.push_back(pchName); - Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames); - if (!Reader) + OutReader = createASTReader(CI, pchName, SerialBufs, serialBufNames); + if (!OutReader) return nullptr; auto ChainedSrc = llvm::makeIntrusiveRefCnt(std::move(CIs)); return llvm::makeIntrusiveRefCnt( - ChainedSrc.get(), Reader.get()); + std::move(ChainedSrc), OutReader); } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 0df627ec8dc89..c16726010ffb2 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -177,20 +177,23 @@ llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const { return getFileManager().getVirtualFileSystem(); } -void CompilerInstance::setFileManager(FileManager *Value) { - FileMgr = Value; +void CompilerInstance::setFileManager( + llvm::IntrusiveRefCntPtr Value) { + FileMgr = std::move(Value); } -void CompilerInstance::setSourceManager(SourceManager *Value) { - SourceMgr = Value; +void CompilerInstance::setSourceManager( + llvm::IntrusiveRefCntPtr Value) { + SourceMgr = std::move(Value); } void CompilerInstance::setPreprocessor(std::shared_ptr Value) { PP = std::move(Value); } -void CompilerInstance::setASTContext(ASTContext *Value) { - Context = Value; +void CompilerInstance::setASTContext( + llvm::IntrusiveRefCntPtr Value) { + Context = std::move(Value); if (Context && Consumer) getASTConsumer().Initialize(getASTContext()); @@ -398,14 +401,16 @@ FileManager *CompilerInstance::createFileManager( if (getFrontendOpts().ShowStats) VFS = llvm::makeIntrusiveRefCnt(std::move(VFS)); - FileMgr = new FileManager(getFileSystemOpts(), std::move(VFS)); + FileMgr = llvm::makeIntrusiveRefCnt(getFileSystemOpts(), + std::move(VFS)); return FileMgr.get(); } // Source Manager void CompilerInstance::createSourceManager(FileManager &FileMgr) { - SourceMgr = new SourceManager(getDiagnostics(), FileMgr); + SourceMgr = + llvm::makeIntrusiveRefCnt(getDiagnostics(), FileMgr); } // Initialize the remapping of files to alternative contents, e.g., @@ -577,11 +582,11 @@ std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) { void CompilerInstance::createASTContext() { Preprocessor &PP = getPreprocessor(); - auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(), - PP.getIdentifierTable(), PP.getSelectorTable(), - PP.getBuiltinInfo(), PP.TUKind); + auto Context = llvm::makeIntrusiveRefCnt( + getLangOpts(), PP.getSourceManager(), PP.getIdentifierTable(), + PP.getSelectorTable(), PP.getBuiltinInfo(), PP.TUKind); Context->InitBuiltinTypes(getTarget(), getAuxTarget()); - setASTContext(Context); + setASTContext(std::move(Context)); } // ExternalASTSource @@ -686,17 +691,17 @@ IntrusiveRefCntPtr CompilerInstance::createPCHExternalASTSource( const HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); - IntrusiveRefCntPtr Reader(new ASTReader( + auto Reader = llvm::makeIntrusiveRefCnt( PP, ModCache, &Context, PCHContainerRdr, Extensions, Sysroot.empty() ? "" : Sysroot.data(), DisableValidation, AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders, HSOpts.ModulesForceValidateUserHeaders, - HSOpts.ValidateASTInputFilesContent, UseGlobalModuleIndex)); + HSOpts.ValidateASTInputFilesContent, UseGlobalModuleIndex); // We need the external source to be set up before we read the AST, because // eagerly-deserialized declarations may use it. - Context.setExternalSource(Reader.get()); + Context.setExternalSource(Reader); Reader->setDeserializationListener( static_cast(DeserializationListener), @@ -882,7 +887,7 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind, // Attach the external sema source if there is any. if (ExternalSemaSrc) { - TheSema->addExternalSource(ExternalSemaSrc.get()); + TheSema->addExternalSource(ExternalSemaSrc); ExternalSemaSrc->InitializeSema(*TheSema); } } @@ -1397,7 +1402,7 @@ std::unique_ptr CompilerInstance::cloneForModuleCompileImpl( if (ThreadSafeConfig) { Instance.createFileManager(ThreadSafeConfig->getVFS()); } else if (FrontendOpts.ModulesShareFileManager) { - Instance.setFileManager(&getFileManager()); + Instance.setFileManager(getFileManagerPtr()); } else { Instance.createFileManager(&getVirtualFileSystem()); } @@ -1954,16 +1959,17 @@ void CompilerInstance::createASTReader() { if (timerGroup) ReadTimer = std::make_unique("reading_modules", "Reading modules", *timerGroup); - TheASTReader = new ASTReader( + TheASTReader = llvm::makeIntrusiveRefCnt( getPreprocessor(), getModuleCache(), &getASTContext(), getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions, Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHOrModuleValidation, /*AllowASTWithCompilerErrors=*/FEOpts.AllowPCMWithCompilerErrors, - /*AllowConfigurationMismatch=*/false, HSOpts.ModulesValidateSystemHeaders, - HSOpts.ModulesForceValidateUserHeaders, - HSOpts.ValidateASTInputFilesContent, - getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer)); + /*AllowConfigurationMismatch=*/false, + +HSOpts.ModulesValidateSystemHeaders, + +HSOpts.ModulesForceValidateUserHeaders, + +HSOpts.ValidateASTInputFilesContent, + +getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer)); if (hasASTConsumer()) { TheASTReader->setDeserializationListener( getASTConsumer().GetASTDeserializationListener()); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 0fa92aca510d2..cb184d4eacf3f 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -916,7 +916,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. - CI.setFileManager(&AST->getFileManager()); + CI.setFileManager(AST->getFileManagerPtr()); CI.createSourceManager(CI.getFileManager()); CI.getSourceManager().initializeForReplay(AST->getSourceManager()); @@ -983,13 +983,13 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. - CI.setFileManager(&AST->getFileManager()); - CI.setSourceManager(&AST->getSourceManager()); + CI.setFileManager(AST->getFileManagerPtr()); + CI.setSourceManager(AST->getSourceManagerPtr()); CI.setPreprocessor(AST->getPreprocessorPtr()); Preprocessor &PP = CI.getPreprocessor(); PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); - CI.setASTContext(&AST->getASTContext()); + CI.setASTContext(AST->getASTContextPtr()); setCurrentInput(Input, std::move(AST)); @@ -1295,11 +1295,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { // Convert headers to PCH and chain them. - IntrusiveRefCntPtr source, FinalReader; + IntrusiveRefCntPtr source; + IntrusiveRefCntPtr FinalReader; source = createChainedIncludesSource(CI, FinalReader); if (!source) return false; - CI.setASTReader(static_cast(FinalReader.get())); + CI.setASTReader(FinalReader); CI.getASTContext().setExternalSource(source); } else if (CI.getLangOpts().Modules || !CI.getPreprocessorOpts().ImplicitPCHInclude.empty() || @@ -1395,23 +1396,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // provides the layouts from that file. if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { - IntrusiveRefCntPtr - Override(new LayoutOverrideSource( - CI.getFrontendOpts().OverrideRecordLayoutsFile)); + auto Override = llvm::makeIntrusiveRefCnt( + CI.getFrontendOpts().OverrideRecordLayoutsFile); CI.getASTContext().setExternalSource(Override); } // Setup HLSL External Sema Source if (CI.getLangOpts().HLSL && CI.hasASTContext()) { - IntrusiveRefCntPtr HLSLSema( - new HLSLExternalSemaSource()); - if (auto *SemaSource = dyn_cast_if_present( - CI.getASTContext().getExternalSource())) { - IntrusiveRefCntPtr MultiSema( - new MultiplexExternalSemaSource(SemaSource, HLSLSema.get())); - CI.getASTContext().setExternalSource(MultiSema); + auto HLSLSema = llvm::makeIntrusiveRefCnt(); + if (auto SemaSource = dyn_cast_if_present( + CI.getASTContext().getExternalSourcePtr())) { + auto MultiSema = llvm::makeIntrusiveRefCnt( + std::move(SemaSource), std::move(HLSLSema)); + CI.getASTContext().setExternalSource(std::move(MultiSema)); } else - CI.getASTContext().setExternalSource(HLSLSema); + CI.getASTContext().setExternalSource(std::move(HLSLSema)); } FailureCleanup.release(); diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp index 431bd17f7b5c0..1d278b51b940f 100644 --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -483,11 +483,12 @@ llvm::ErrorOr PrecompiledPreamble::Build( VFS); // Create a file manager object to provide access to and cache the filesystem. - Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS)); + Clang->setFileManager( + llvm::makeIntrusiveRefCnt(Clang->getFileSystemOpts(), VFS)); // Create the source manager. - Clang->setSourceManager( - new SourceManager(*Diagnostics, Clang->getFileManager())); + Clang->setSourceManager(llvm::makeIntrusiveRefCnt( + *Diagnostics, Clang->getFileManager())); auto PreambleDepCollector = std::make_shared(); Clang->addDependencyCollector(PreambleDepCollector); diff --git a/clang/lib/Interpreter/CodeCompletion.cpp b/clang/lib/Interpreter/CodeCompletion.cpp index 5a0a6431acb30..864c4c8a9b56c 100644 --- a/clang/lib/Interpreter/CodeCompletion.cpp +++ b/clang/lib/Interpreter/CodeCompletion.cpp @@ -237,11 +237,9 @@ class ExternalSource : public clang::ExternalASTSource { // compiler instance before the super `ExecuteAction` triggers parsing void IncrementalSyntaxOnlyAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); - ExternalSource *myExternalSource = - new ExternalSource(CI.getASTContext(), CI.getFileManager(), - ParentCI->getASTContext(), ParentCI->getFileManager()); - llvm::IntrusiveRefCntPtr astContextExternalSource( - myExternalSource); + auto astContextExternalSource = llvm::makeIntrusiveRefCnt( + CI.getASTContext(), CI.getFileManager(), ParentCI->getASTContext(), + ParentCI->getFileManager()); CI.getASTContext().setExternalSource(astContextExternalSource); CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage( true); @@ -380,8 +378,8 @@ void ReplCodeCompleter::codeComplete(CompilerInstance *InterpCI, AU->CodeComplete(CodeCompletionFileName, 1, Col, RemappedFiles, false, false, false, consumer, std::make_shared(), diag, - InterpCI->getLangOpts(), AU->getSourceManager(), - AU->getFileManager(), sd, tb, std::move(Act)); + InterpCI->getLangOpts(), AU->getSourceManagerPtr(), + AU->getFileManagerPtr(), sd, tb, std::move(Act)); } } // namespace clang diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index fbfb242598c24..1f040c879d724 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -20,26 +20,19 @@ char MultiplexExternalSemaSource::ID; /// given element to it. /// MultiplexExternalSemaSource::MultiplexExternalSemaSource( - ExternalSemaSource *S1, ExternalSemaSource *S2) { - S1->Retain(); - S2->Retain(); - Sources.push_back(S1); - Sources.push_back(S2); -} - -// pin the vtable here. -MultiplexExternalSemaSource::~MultiplexExternalSemaSource() { - for (auto *S : Sources) - S->Release(); + llvm::IntrusiveRefCntPtr S1, + llvm::IntrusiveRefCntPtr S2) { + Sources.push_back(std::move(S1)); + Sources.push_back(std::move(S2)); } /// Appends new source to the source list. /// ///\param[in] source - An ExternalSemaSource. /// -void MultiplexExternalSemaSource::AddSource(ExternalSemaSource *Source) { - Source->Retain(); - Sources.push_back(Source); +void MultiplexExternalSemaSource::AddSource( + llvm::IntrusiveRefCntPtr Source) { + Sources.push_back(std::move(Source)); } //===----------------------------------------------------------------------===// @@ -92,7 +85,7 @@ CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers( CXXCtorInitializer ** MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) { - for (auto *S : Sources) + for (auto &S : Sources) if (auto *R = S->GetExternalCXXCtorInitializers(Offset)) return R; return nullptr; @@ -371,6 +364,6 @@ bool MultiplexExternalSemaSource::MaybeDiagnoseMissingCompleteType( void MultiplexExternalSemaSource::AssignedLambdaNumbering( CXXRecordDecl *Lambda) { - for (auto *Source : Sources) + for (auto &Source : Sources) Source->AssignedLambdaNumbering(Lambda); } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 5843568f3ac2d..ed6193b2118ed 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -773,18 +773,19 @@ ASTMutationListener *Sema::getASTMutationListener() const { return getASTConsumer().GetASTMutationListener(); } -void Sema::addExternalSource(ExternalSemaSource *E) { +void Sema::addExternalSource(IntrusiveRefCntPtr E) { assert(E && "Cannot use with NULL ptr"); if (!ExternalSource) { - ExternalSource = E; + ExternalSource = std::move(E); return; } - if (auto *Ex = dyn_cast(ExternalSource)) - Ex->AddSource(E); + if (auto *Ex = dyn_cast(ExternalSource.get())) + Ex->AddSource(std::move(E)); else - ExternalSource = new MultiplexExternalSemaSource(ExternalSource.get(), E); + ExternalSource = llvm::makeIntrusiveRefCnt( + ExternalSource, std::move(E)); } void Sema::PrintStats() const { diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp index 5d392afcb9825..7bc34f61255f4 100644 --- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp @@ -43,8 +43,8 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) { if (Bodies.count(D->getName()) != 0) return; - SourceManager &SM = CI.getSourceManager(); - FileID mainFileID = SM.getMainFileID(); + llvm::IntrusiveRefCntPtr SM = CI.getSourceManagerPtr(); + FileID mainFileID = SM->getMainFileID(); llvm::StringRef modelPath = CI.getAnalyzerOpts().ModelPath; @@ -80,14 +80,14 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) { new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), /*ShouldOwnClient=*/true); - Instance.getDiagnostics().setSourceManager(&SM); + Instance.getDiagnostics().setSourceManager(SM.get()); // The instance wants to take ownership, however DisableFree frontend option // is set to true to avoid double free issues - Instance.setFileManager(&CI.getFileManager()); - Instance.setSourceManager(&SM); + Instance.setFileManager(CI.getFileManagerPtr()); + Instance.setSourceManager(SM); Instance.setPreprocessor(CI.getPreprocessorPtr()); - Instance.setASTContext(&CI.getASTContext()); + Instance.setASTContext(CI.getASTContextPtr()); Instance.getPreprocessor().InitializeForModelFile(); @@ -108,5 +108,5 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) { // the main file id is changed to the model file during parsing and it needs // to be reset to the former main file id after parsing of the model file // is done. - SM.setMainFileID(mainFileID); + SM->setMainFileID(mainFileID); } diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index 53339566e310e..ea5942ac0141b 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -212,8 +212,8 @@ bool runToolOnCodeWithArgs( SmallString<16> FileNameStorage; StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), VFS)); + llvm::IntrusiveRefCntPtr Files = + llvm::makeIntrusiveRefCnt(FileSystemOptions(), VFS); ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster(); ToolInvocation Invocation( getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef), @@ -476,7 +476,8 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations, OverlayFileSystem(new llvm::vfs::OverlayFileSystem(std::move(BaseFS))), InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), Files(Files ? Files - : new FileManager(FileSystemOptions(), OverlayFileSystem)) { + : llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem)) { OverlayFileSystem->pushOverlay(InMemoryFileSystem); appendArgumentsAdjuster(getClangStripOutputAdjuster()); appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); @@ -697,8 +698,9 @@ std::unique_ptr buildASTFromCodeWithArgs( llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + llvm::IntrusiveRefCntPtr Files = + llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem); ToolInvocation Invocation( getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileName), FileName), diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index 8a9c497338700..327fb730ede77 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -89,8 +89,9 @@ static bool run(ArrayRef Args, const char *ProgName) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - IntrusiveRefCntPtr FM( - new FileManager(clang::FileSystemOptions(), OverlayFileSystem)); + IntrusiveRefCntPtr FM = + llvm::makeIntrusiveRefCnt(clang::FileSystemOptions(), + OverlayFileSystem); // Capture all options and diagnose any errors. Options Opts(*Diag, FM.get(), Args, ProgName); @@ -113,7 +114,7 @@ static bool run(ArrayRef Args, const char *ProgName) { // Set up compilation. std::unique_ptr CI(new CompilerInstance()); - CI->setFileManager(FM.get()); + CI->setFileManager(FM); CI->createDiagnostics(FM->getVirtualFileSystem()); if (!CI->hasDiagnostics()) return EXIT_FAILURE; diff --git a/clang/tools/libclang/CIndexCodeCompletion.cpp b/clang/tools/libclang/CIndexCodeCompletion.cpp index 16dfafd82399f..b2d4c0af6151b 100644 --- a/clang/tools/libclang/CIndexCodeCompletion.cpp +++ b/clang/tools/libclang/CIndexCodeCompletion.cpp @@ -360,7 +360,8 @@ AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults( Diag(llvm::makeIntrusiveRefCnt(DiagnosticIDs::create(), DiagOpts)), FileMgr(std::move(FileMgr)), - SourceMgr(new SourceManager(*Diag, *this->FileMgr)), + SourceMgr( + llvm::makeIntrusiveRefCnt(*Diag, *this->FileMgr)), CodeCompletionAllocator( std::make_shared()), Contexts(CXCompletionContext_Unknown), @@ -736,8 +737,8 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, } // Parse the resulting source file to find code-completion results. - AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults( - &AST->getFileManager()); + AllocatedCXCodeCompleteResults *Results = + new AllocatedCXCodeCompleteResults(AST->getFileManagerPtr()); Results->Results = nullptr; Results->NumResults = 0; @@ -765,7 +766,7 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, (options & CXCodeComplete_IncludeCodePatterns), IncludeBriefComments, Capture, CXXIdx->getPCHContainerOperations(), Results->Diag, - Results->LangOpts, *Results->SourceMgr, *Results->FileMgr, + Results->LangOpts, Results->SourceMgr, Results->FileMgr, Results->Diagnostics, Results->TemporaryBuffers, /*SyntaxOnlyAction=*/nullptr); diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp index 964d3b187adbf..bd95c5cdaccf9 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -415,9 +415,9 @@ const char *ScratchAlloc::copyCStr(StringRef Str) { return buf; } -void CXIndexDataConsumer::setASTContext(ASTContext &ctx) { - Ctx = &ctx; - cxtu::getASTUnit(CXTU)->setASTContext(&ctx); +void CXIndexDataConsumer::setASTContext(IntrusiveRefCntPtr ctx) { + Ctx = ctx.get(); + cxtu::getASTUnit(CXTU)->setASTContext(std::move(ctx)); } void CXIndexDataConsumer::setPreprocessor(std::shared_ptr PP) { diff --git a/clang/tools/libclang/CXIndexDataConsumer.h b/clang/tools/libclang/CXIndexDataConsumer.h index 54a3add3a9c8d..b207db7cde6d7 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.h +++ b/clang/tools/libclang/CXIndexDataConsumer.h @@ -339,7 +339,7 @@ class CXIndexDataConsumer : public index::IndexDataConsumer { ASTContext &getASTContext() const { return *Ctx; } CXTranslationUnit getCXTU() const { return CXTU; } - void setASTContext(ASTContext &ctx); + void setASTContext(llvm::IntrusiveRefCntPtr ctx); void setPreprocessor(std::shared_ptr PP) override; bool shouldSuppressRefs() const { diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp index 32a7147af3382..c142f142d5071 100644 --- a/clang/tools/libclang/Indexing.cpp +++ b/clang/tools/libclang/Indexing.cpp @@ -304,7 +304,8 @@ class IndexingConsumer : public ASTConsumer { : DataConsumer(dataConsumer) {} void Initialize(ASTContext &Context) override { - DataConsumer.setASTContext(Context); + // TODO: accept Context as IntrusiveRefCntPtr? + DataConsumer.setASTContext(&Context); DataConsumer.startedTranslationUnit(); } @@ -355,7 +356,7 @@ class IndexingFrontendAction : public ASTFrontendAction { DataConsumer->importedPCH(*File); } - DataConsumer->setASTContext(CI.getASTContext()); + DataConsumer->setASTContext(CI.getASTContextPtr()); Preprocessor &PP = CI.getPreprocessor(); PP.addPPCallbacks(std::make_unique(PP, *DataConsumer)); DataConsumer->setPreprocessor(CI.getPreprocessorPtr()); @@ -706,7 +707,7 @@ static CXErrorCode clang_indexTranslationUnit_Impl( else DataConsumer.enteredMainFile(std::nullopt); - DataConsumer.setASTContext(Unit->getASTContext()); + DataConsumer.setASTContext(Unit->getASTContextPtr()); DataConsumer.startedTranslationUnit(); indexPreprocessingRecord(*Unit, DataConsumer); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index c0fb642d817a0..ac38300142e34 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -6976,7 +6976,8 @@ TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) { // Set up DeclContextBits.HasLazyExternalLexicalLookups to true. ToTU->setMustBuildLookupTable(); struct TestExternalASTSource : ExternalASTSource {}; - ToTU->getASTContext().setExternalSource(new TestExternalASTSource()); + ToTU->getASTContext().setExternalSource( + llvm::makeIntrusiveRefCnt()); Decl *FromTU = getTuDecl( R"( @@ -8154,8 +8155,8 @@ TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) { // Create and add the test ExternalASTSource. std::vector CompletedTags; - IntrusiveRefCntPtr source = - new SourceWithCompletedTagList(CompletedTags); + auto source = + llvm::makeIntrusiveRefCnt(CompletedTags); clang::ASTContext &Context = FromTU->getASTContext(); Context.setExternalSource(std::move(source)); diff --git a/clang/unittests/AST/ExternalASTSourceTest.cpp b/clang/unittests/AST/ExternalASTSourceTest.cpp index 11715bb8ce7cd..21d4ce4dcf212 100644 --- a/clang/unittests/AST/ExternalASTSourceTest.cpp +++ b/clang/unittests/AST/ExternalASTSourceTest.cpp @@ -26,7 +26,8 @@ using namespace llvm; class TestFrontendAction : public ASTFrontendAction { public: - TestFrontendAction(ExternalASTSource *Source) : Source(Source) {} + TestFrontendAction(IntrusiveRefCntPtr Source) + : Source(std::move(Source)) {} private: void ExecuteAction() override { @@ -44,7 +45,8 @@ class TestFrontendAction : public ASTFrontendAction { IntrusiveRefCntPtr Source; }; -bool testExternalASTSource(ExternalASTSource *Source, StringRef FileContents) { +bool testExternalASTSource(llvm::IntrusiveRefCntPtr Source, + StringRef FileContents) { auto Invocation = std::make_shared(); Invocation->getPreprocessorOpts().addRemappedFile( @@ -80,6 +82,7 @@ TEST(ExternalASTSourceTest, FailedLookupOccursOnce) { }; unsigned Calls = 0; - ASSERT_TRUE(testExternalASTSource(new TestSource(Calls), "int j, k = j;")); + ASSERT_TRUE(testExternalASTSource( + llvm::makeIntrusiveRefCnt(Calls), "int j, k = j;")); EXPECT_EQ(1u, Calls); } diff --git a/clang/unittests/Frontend/ASTUnitTest.cpp b/clang/unittests/Frontend/ASTUnitTest.cpp index afa64b5e90a6d..35cd3de4d3b48 100644 --- a/clang/unittests/Frontend/ASTUnitTest.cpp +++ b/clang/unittests/Frontend/ASTUnitTest.cpp @@ -55,7 +55,8 @@ class ASTUnitTest : public ::testing::Test { if (!CInvok) return nullptr; - FileManager *FileMgr = new FileManager(FileSystemOptions(), VFS); + auto FileMgr = + llvm::makeIntrusiveRefCnt(FileSystemOptions(), VFS); PCHContainerOps = std::make_shared(); return ASTUnit::LoadFromCompilerInvocation( @@ -144,7 +145,8 @@ TEST_F(ASTUnitTest, ModuleTextualHeader) { CInvok = createInvocation(Args, std::move(CIOpts)); ASSERT_TRUE(CInvok); - FileManager *FileMgr = new FileManager(FileSystemOptions(), InMemoryFs); + auto FileMgr = + llvm::makeIntrusiveRefCnt(FileSystemOptions(), InMemoryFs); PCHContainerOps = std::make_shared(); auto AU = ASTUnit::LoadFromCompilerInvocation( diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp index 4e040783c923e..48c0cfd6a185a 100644 --- a/clang/unittests/Frontend/FrontendActionTest.cpp +++ b/clang/unittests/Frontend/FrontendActionTest.cpp @@ -244,7 +244,8 @@ TEST(ASTFrontendAction, ExternalSemaSource) { auto *TDC = new TypoDiagnosticConsumer; Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem(), TDC, /*ShouldOwnClient=*/true); - Compiler.setExternalSemaSource(new TypoExternalSemaSource(Compiler)); + Compiler.setExternalSemaSource( + llvm::makeIntrusiveRefCnt(Compiler)); SyntaxOnlyAction TestAction; ASSERT_TRUE(Compiler.ExecuteAction(TestAction)); diff --git a/clang/unittests/Frontend/PCHPreambleTest.cpp b/clang/unittests/Frontend/PCHPreambleTest.cpp index faad408193f62..06e585357dda5 100644 --- a/clang/unittests/Frontend/PCHPreambleTest.cpp +++ b/clang/unittests/Frontend/PCHPreambleTest.cpp @@ -100,7 +100,7 @@ class PCHPreambleTest : public ::testing::Test { CompilerInstance::createDiagnostics(*VFS, *DiagOpts, new DiagnosticConsumer)); - FileManager *FileMgr = new FileManager(FSOpts, VFS); + auto FileMgr = llvm::makeIntrusiveRefCnt(FSOpts, VFS); std::unique_ptr AST = ASTUnit::LoadFromCompilerInvocation( CI, PCHContainerOpts, DiagOpts, Diags, FileMgr, false, diff --git a/clang/unittests/Frontend/ReparseWorkingDirTest.cpp b/clang/unittests/Frontend/ReparseWorkingDirTest.cpp index 1b8051f80e9b8..c67891d95940b 100644 --- a/clang/unittests/Frontend/ReparseWorkingDirTest.cpp +++ b/clang/unittests/Frontend/ReparseWorkingDirTest.cpp @@ -62,7 +62,8 @@ class ReparseWorkingDirTest : public ::testing::Test { CompilerInstance::createDiagnostics(*VFS, *DiagOpts, new DiagnosticConsumer)); - FileManager *FileMgr = new FileManager(CI->getFileSystemOpts(), VFS); + auto FileMgr = + llvm::makeIntrusiveRefCnt(CI->getFileSystemOpts(), VFS); std::unique_ptr AST = ASTUnit::LoadFromCompilerInvocation( CI, PCHContainerOpts, DiagOpts, Diags, FileMgr, false, diff --git a/clang/unittests/Sema/ExternalSemaSourceTest.cpp b/clang/unittests/Sema/ExternalSemaSourceTest.cpp index cc9dd4175af55..2524ac3ea518b 100644 --- a/clang/unittests/Sema/ExternalSemaSourceTest.cpp +++ b/clang/unittests/Sema/ExternalSemaSourceTest.cpp @@ -181,7 +181,7 @@ class FunctionTypoProvider : public clang::ExternalSemaSource { // performing semantic analysis. class ExternalSemaSourceInstaller : public clang::ASTFrontendAction { std::vector Watchers; - std::vector Sources; + std::vector> Sources; std::unique_ptr OwnedClient; protected: @@ -212,8 +212,8 @@ class ExternalSemaSourceInstaller : public clang::ASTFrontendAction { } public: - void PushSource(clang::ExternalSemaSource *Source) { - Sources.push_back(Source); + void PushSource(llvm::IntrusiveRefCntPtr Source) { + Sources.push_back(std::move(Source)); } void PushWatcher(DiagnosticWatcher *Watcher) { Watchers.push_back(Watcher); } @@ -238,7 +238,7 @@ TEST(ExternalSemaSource, ExternalTypoCorrectionPrioritized) { auto Installer = std::make_unique(); auto Provider = makeIntrusiveRefCnt("AAB", "BBB"); DiagnosticWatcher Watcher("AAB", "BBB"); - Installer->PushSource(Provider.get()); + Installer->PushSource(Provider); Installer->PushWatcher(&Watcher); std::vector Args(1, "-std=c++11"); ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs( @@ -255,9 +255,9 @@ TEST(ExternalSemaSource, ExternalTypoCorrectionOrdering) { auto Second = makeIntrusiveRefCnt("AAB", "CCC"); auto Third = makeIntrusiveRefCnt("AAB", "DDD"); DiagnosticWatcher Watcher("AAB", "CCC"); - Installer->PushSource(First.get()); - Installer->PushSource(Second.get()); - Installer->PushSource(Third.get()); + Installer->PushSource(First); + Installer->PushSource(Second); + Installer->PushSource(Third); Installer->PushWatcher(&Watcher); std::vector Args(1, "-std=c++11"); ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs( @@ -273,7 +273,7 @@ TEST(ExternalSemaSource, ExternalTypoCorrectionOrdering) { TEST(ExternalSemaSource, TryOtherTacticsBeforeDiagnosing) { auto Installer = std::make_unique(); auto Diagnoser = makeIntrusiveRefCnt(false); - Installer->PushSource(Diagnoser.get()); + Installer->PushSource(Diagnoser); std::vector Args(1, "-std=c++11"); // This code hits the class template specialization/class member of a class // template specialization checks in Sema::RequireCompleteTypeImpl. @@ -291,9 +291,9 @@ TEST(ExternalSemaSource, FirstDiagnoserTaken) { auto First = makeIntrusiveRefCnt(false); auto Second = makeIntrusiveRefCnt(true); auto Third = makeIntrusiveRefCnt(true); - Installer->PushSource(First.get()); - Installer->PushSource(Second.get()); - Installer->PushSource(Third.get()); + Installer->PushSource(First); + Installer->PushSource(Second); + Installer->PushSource(Third); std::vector Args(1, "-std=c++11"); ASSERT_FALSE(clang::tooling::runToolOnCodeWithArgs( std::move(Installer), "class Incomplete; Incomplete IncompleteInstance;", diff --git a/clang/unittests/Support/TimeProfilerTest.cpp b/clang/unittests/Support/TimeProfilerTest.cpp index 85d36b5d21423..c762214dba41e 100644 --- a/clang/unittests/Support/TimeProfilerTest.cpp +++ b/clang/unittests/Support/TimeProfilerTest.cpp @@ -53,8 +53,7 @@ bool compileFromString(StringRef Code, StringRef Standard, StringRef File, FS->addFile(Header.getKey(), 0, MemoryBuffer::getMemBuffer(Header.getValue())); } - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), FS)); + auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), FS); auto Invocation = std::make_shared(); std::vector Args = {Standard.data(), File.data()}; @@ -65,7 +64,7 @@ bool compileFromString(StringRef Code, StringRef Standard, StringRef File, CompilerInstance Compiler(std::move(Invocation)); Compiler.createDiagnostics(Files->getVirtualFileSystem()); - Compiler.setFileManager(Files.get()); + Compiler.setFileManager(Files); class TestFrontendAction : public ASTFrontendAction { private: diff --git a/clang/unittests/Tooling/Syntax/TokensTest.cpp b/clang/unittests/Tooling/Syntax/TokensTest.cpp index e3da8eb45dafa..1195dddafcc4d 100644 --- a/clang/unittests/Tooling/Syntax/TokensTest.cpp +++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp @@ -134,8 +134,8 @@ class TokenCollectorTest : public ::testing::Test { FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release()); CompilerInstance Compiler(std::move(CI)); Compiler.setDiagnostics(Diags); - Compiler.setFileManager(FileMgr.get()); - Compiler.setSourceManager(SourceMgr.get()); + Compiler.setFileManager(FileMgr); + Compiler.setSourceManager(SourceMgr); this->Buffer = TokenBuffer(*SourceMgr); RecordTokens Recorder(this->Buffer); @@ -255,9 +255,9 @@ class TokenCollectorTest : public ::testing::Test { IntrusiveRefCntPtr FS = new llvm::vfs::InMemoryFileSystem; llvm::IntrusiveRefCntPtr FileMgr = - new FileManager(FileSystemOptions(), FS); + llvm::makeIntrusiveRefCnt(FileSystemOptions(), FS); llvm::IntrusiveRefCntPtr SourceMgr = - new SourceManager(*Diags, *FileMgr); + llvm::makeIntrusiveRefCnt(*Diags, *FileMgr); /// Contains last result of calling recordTokens(). TokenBuffer Buffer = TokenBuffer(*SourceMgr); }; diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp index 4a25863b03245..400a0d5a1801b 100644 --- a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp @@ -153,8 +153,8 @@ SyntaxTreeTest::buildTree(StringRef Code, const TestClangConfig &ClangConfig) { FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release()); CompilerInstance Compiler(Invocation); Compiler.setDiagnostics(Diags); - Compiler.setFileManager(FileMgr.get()); - Compiler.setSourceManager(SourceMgr.get()); + Compiler.setFileManager(FileMgr); + Compiler.setSourceManager(SourceMgr); syntax::TranslationUnit *Root = nullptr; BuildSyntaxTreeAction Recorder(Root, this->TM, this->TB, this->Arena); diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.h b/clang/unittests/Tooling/Syntax/TreeTestBase.h index f38380a5fdddb..633560dd0d103 100644 --- a/clang/unittests/Tooling/Syntax/TreeTestBase.h +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.h @@ -47,9 +47,9 @@ class SyntaxTreeTest : public ::testing::Test, IntrusiveRefCntPtr FS = new llvm::vfs::InMemoryFileSystem; IntrusiveRefCntPtr FileMgr = - new FileManager(FileSystemOptions(), FS); + llvm::makeIntrusiveRefCnt(FileSystemOptions(), FS); IntrusiveRefCntPtr SourceMgr = - new SourceManager(*Diags, *FileMgr); + llvm::makeIntrusiveRefCnt(*Diags, *FileMgr); std::shared_ptr Invocation; // Set after calling buildTree(). std::unique_ptr TB; diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp index 32af4b6b3b359..a713560b29078 100644 --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -193,8 +193,8 @@ TEST(ToolInvocation, TestMapVirtualFile) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem); std::vector Args; Args.push_back("tool-executable"); Args.push_back("-Idef"); @@ -219,8 +219,8 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem); std::vector Args; Args.push_back("tool-executable"); Args.push_back("-Idef"); @@ -245,8 +245,8 @@ TEST(ToolInvocation, DiagnosticsEngineProperlyInitializedForCC1Construction) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem); std::vector Args; Args.push_back("tool-executable"); @@ -274,8 +274,8 @@ TEST(ToolInvocation, CustomDiagnosticOptionsOverwriteParsedOnes) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem); std::vector Args; Args.push_back("tool-executable"); @@ -320,8 +320,8 @@ TEST(ToolInvocation, DiagConsumerExpectingSourceManager) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem); std::vector Args; Args.push_back("tool-executable"); // Note: intentional error; user probably meant -ferror-limit=0. @@ -346,8 +346,8 @@ TEST(ToolInvocation, CC1Args) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem); std::vector Args; Args.push_back("tool-executable"); Args.push_back("-cc1"); @@ -366,8 +366,8 @@ TEST(ToolInvocation, CC1ArgsInvalid) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); - llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), + OverlayFileSystem); std::vector Args; Args.push_back("tool-executable"); Args.push_back("-cc1"); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp index 5d67a51b26905..a95fce1c5aa96 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp @@ -18,10 +18,7 @@ lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() = default; void lldb_private::ASTConsumerForwarder::PrintStats() { m_c->PrintStats(); } -lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() { - for (auto *Source : Sources) - Source->Release(); -} +lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() = default; void lldb_private::SemaSourceWithPriorities::PrintStats() { for (size_t i = 0; i < Sources.size(); ++i) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h index 03c01707e6b31..7ec9a9fa41a30 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h @@ -34,8 +34,9 @@ class ExternalASTSourceWrapper : public ImporterBackedASTSource { llvm::IntrusiveRefCntPtr m_Source; public: - explicit ExternalASTSourceWrapper(ExternalASTSource *Source) - : m_Source(Source) { + explicit ExternalASTSourceWrapper( + llvm::IntrusiveRefCntPtr Source) + : m_Source(std::move(Source)) { assert(m_Source && "Can't wrap nullptr ExternalASTSource"); } @@ -285,7 +286,8 @@ class SemaSourceWithPriorities : public ImporterBackedASTSource { private: /// The sources ordered in decreasing priority. - llvm::SmallVector Sources; + llvm::SmallVector, 2> + Sources; public: /// Construct a SemaSourceWithPriorities with a 'high quality' source that @@ -293,16 +295,14 @@ class SemaSourceWithPriorities : public ImporterBackedASTSource { /// as a fallback. /// /// This class assumes shared ownership of the sources provided to it. - SemaSourceWithPriorities(clang::ExternalSemaSource *high_quality_source, - clang::ExternalSemaSource *low_quality_source) { + SemaSourceWithPriorities( + llvm::IntrusiveRefCntPtr high_quality_source, + llvm::IntrusiveRefCntPtr low_quality_source) { assert(high_quality_source); assert(low_quality_source); - high_quality_source->Retain(); - low_quality_source->Retain(); - - Sources.push_back(high_quality_source); - Sources.push_back(low_quality_source); + Sources.push_back(std::move(high_quality_source)); + Sources.push_back(std::move(low_quality_source)); } ~SemaSourceWithPriorities() override; @@ -383,7 +383,7 @@ class SemaSourceWithPriorities : public ImporterBackedASTSource { clang::CXXCtorInitializer ** GetExternalCXXCtorInitializers(uint64_t Offset) override { - for (auto *S : Sources) + for (const auto &S : Sources) if (auto *R = S->GetExternalCXXCtorInitializers(Offset)) return R; return nullptr; @@ -431,7 +431,7 @@ class SemaSourceWithPriorities : public ImporterBackedASTSource { } void CompleteType(clang::TagDecl *Tag) override { - for (clang::ExternalSemaSource *S : Sources) { + for (const auto &S : Sources) { S->CompleteType(Tag); // Stop after the first source completed the type. if (Tag->isCompleteDefinition()) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 7b6ab7114f159..64910d8900ee9 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -258,8 +258,8 @@ class ClangASTSource : public ImporterBackedASTSource, ClangASTSource &m_original; }; - clang::ExternalASTSource *CreateProxy() { - return new ClangASTSourceProxy(*this); + llvm::IntrusiveRefCntPtr CreateProxy() { + return llvm::makeIntrusiveRefCnt(*this); } protected: diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 2af4544f498cf..2b9c0d47433e2 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -1311,16 +1311,18 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, decl_map->InstallCodeGenerator(&m_compiler->getASTConsumer()); decl_map->InstallDiagnosticManager(diagnostic_manager); - clang::ExternalASTSource *ast_source = decl_map->CreateProxy(); + llvm::IntrusiveRefCntPtr ast_source = + decl_map->CreateProxy(); - auto *ast_source_wrapper = new ExternalASTSourceWrapper(ast_source); + auto ast_source_wrapper = + llvm::makeIntrusiveRefCnt(ast_source); if (ast_context.getExternalSource()) { - auto *module_wrapper = - new ExternalASTSourceWrapper(ast_context.getExternalSource()); + auto module_wrapper = llvm::makeIntrusiveRefCnt( + ast_context.getExternalSourcePtr()); - auto *multiplexer = - new SemaSourceWithPriorities(module_wrapper, ast_source_wrapper); + auto multiplexer = llvm::makeIntrusiveRefCnt( + module_wrapper, ast_source_wrapper); ast_context.setExternalSource(multiplexer); } else { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index b1c25aa4d17e6..a476610dccb79 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -146,9 +146,9 @@ AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) m_ast_ctx = std::make_shared( "AppleObjCDeclVendor AST", runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()); - m_external_source = new AppleObjCExternalASTSource(*this); - llvm::IntrusiveRefCntPtr external_source_owning_ptr( - m_external_source); + auto external_source_owning_ptr = + llvm::makeIntrusiveRefCnt(*this); + m_external_source = external_source_owning_ptr.get(); m_ast_ctx->getASTContext().setExternalSource(external_source_owning_ptr); } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index c119c927cf531..97a572a4b856b 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -632,10 +632,10 @@ void TypeSystemClang::SetTargetTriple(llvm::StringRef target_triple) { } void TypeSystemClang::SetExternalSource( - llvm::IntrusiveRefCntPtr &ast_source_up) { + llvm::IntrusiveRefCntPtr ast_source_sp) { ASTContext &ast = getASTContext(); ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true); - ast.setExternalSource(ast_source_up); + ast.setExternalSource(std::move(ast_source_sp)); } ASTContext &TypeSystemClang::getASTContext() const { @@ -718,9 +718,9 @@ void TypeSystemClang::CreateASTContext() { GetASTMap().Insert(m_ast_up.get(), this); - llvm::IntrusiveRefCntPtr ast_source_up( - new ClangExternalASTSourceCallbacks(*this)); - SetExternalSource(ast_source_up); + auto ast_source_sp = + llvm::makeIntrusiveRefCnt(*this); + SetExternalSource(ast_source_sp); } TypeSystemClang *TypeSystemClang::GetASTContext(clang::ASTContext *ast) { @@ -9838,8 +9838,8 @@ class SpecializedScratchAST : public TypeSystemClang { m_scratch_ast_source_up(std::move(ast_source)) { // Setup the ClangASTSource to complete this AST. m_scratch_ast_source_up->InstallASTContext(*this); - llvm::IntrusiveRefCntPtr proxy_ast_source( - m_scratch_ast_source_up->CreateProxy()); + llvm::IntrusiveRefCntPtr proxy_ast_source = + m_scratch_ast_source_up->CreateProxy(); SetExternalSource(proxy_ast_source); } @@ -9859,8 +9859,8 @@ ScratchTypeSystemClang::ScratchTypeSystemClang(Target &target, new ClangPersistentVariables(target.shared_from_this())) { m_scratch_ast_source_up = CreateASTSource(); m_scratch_ast_source_up->InstallASTContext(*this); - llvm::IntrusiveRefCntPtr proxy_ast_source( - m_scratch_ast_source_up->CreateProxy()); + llvm::IntrusiveRefCntPtr proxy_ast_source = + m_scratch_ast_source_up->CreateProxy(); SetExternalSource(proxy_ast_source); } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index a82e811e7914a..27ee06d4ef3d9 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -180,7 +180,7 @@ class TypeSystemClang : public TypeSystem { const char *GetTargetTriple(); void SetExternalSource( - llvm::IntrusiveRefCntPtr &ast_source_up); + llvm::IntrusiveRefCntPtr ast_source_sp); bool GetCompleteDecl(clang::Decl *decl) { return TypeSystemClang::GetCompleteDecl(&getASTContext(), decl); From af709462d87a9170ea52959f6b2e5a65dfedb45d Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Wed, 17 Sep 2025 09:15:46 -0700 Subject: [PATCH 05/15] Merge commit '30633f308941' from llvm.org/main into next (cherry picked from commit 95ea104fb4034a99b51750c067121420a4e5a728) Conflicts: clang/include/clang/Frontend/CompilerInstance.h clang/lib/Frontend/CompilerInstance.cpp --- .../clang-include-fixer/IncludeFixer.cpp | 3 +- clang-tools-extra/clangd/Compiler.cpp | 10 +--- .../include-cleaner/unittests/RecordTest.cpp | 5 +- .../include/clang/Frontend/CompilerInstance.h | 45 ++++++++++---- .../clang/Frontend/CompilerInvocation.h | 3 +- clang/lib/Frontend/ASTUnit.cpp | 8 ++- clang/lib/Frontend/ChainedIncludesSource.cpp | 1 + clang/lib/Frontend/CompileJobCache.cpp | 2 +- clang/lib/Frontend/CompilerInstance.cpp | 58 ++++++++++--------- clang/lib/Frontend/CompilerInvocation.cpp | 23 +++++--- clang/lib/Frontend/FrontendAction.cpp | 5 +- clang/lib/Frontend/PrecompiledPreamble.cpp | 6 +- .../lib/Frontend/Rewrite/FrontendActions.cpp | 2 +- clang/lib/Interpreter/Interpreter.cpp | 7 ++- .../StaticAnalyzer/Frontend/ModelInjector.cpp | 2 +- clang/lib/Testing/TestAST.cpp | 10 +++- .../DependencyScanningWorker.cpp | 12 ++-- clang/lib/Tooling/Tooling.cpp | 3 +- .../clang-import-test/clang-import-test.cpp | 4 +- .../clang-installapi/ClangInstallAPI.cpp | 2 +- clang/tools/driver/cc1_main.cpp | 8 ++- clang/unittests/AST/ExternalASTSourceTest.cpp | 3 +- clang/unittests/CodeGen/TestCompiler.h | 3 +- clang/unittests/Driver/ToolChainTest.cpp | 3 +- .../unittests/Frontend/CodeGenActionTest.cpp | 6 +- .../Frontend/CompilerInstanceTest.cpp | 4 +- .../unittests/Frontend/FrontendActionTest.cpp | 19 +++--- clang/unittests/Frontend/OutputStreamTest.cpp | 9 +-- .../Serialization/ForceCheckFileInputTest.cpp | 9 ++- .../Serialization/ModuleCacheTest.cpp | 4 ++ .../Serialization/NoCommentsTest.cpp | 1 + .../PreambleInNamedModulesTest.cpp | 8 +-- clang/unittests/Support/TimeProfilerTest.cpp | 6 +- .../DependencyScannerTest.cpp | 3 +- lldb/source/Commands/CommandObjectTarget.cpp | 4 +- .../Clang/ClangExpressionParser.cpp | 6 +- .../Clang/ClangModulesDeclVendor.cpp | 3 +- 37 files changed, 184 insertions(+), 126 deletions(-) diff --git a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp index 30bb313524cbe..d2ae13c022b23 100644 --- a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp +++ b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp @@ -94,8 +94,7 @@ bool IncludeFixerActionFactory::runInvocation( // Create the compiler's actual diagnostics engine. We want to drop all // diagnostics here. - Compiler.createDiagnostics(Files->getVirtualFileSystem(), - new clang::IgnoringDiagConsumer, + Compiler.createDiagnostics(new clang::IgnoringDiagConsumer, /*ShouldOwnClient=*/true); Compiler.createSourceManager(*Files); diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp index 8b3865c8a8e5c..6ebc2eac25745 100644 --- a/clang-tools-extra/clangd/Compiler.cpp +++ b/clang-tools-extra/clangd/Compiler.cpp @@ -147,13 +147,9 @@ prepareCompilerInstance(std::unique_ptr CI, } auto Clang = std::make_unique(std::move(CI)); - Clang->createDiagnostics(*VFS, &DiagsClient, false); - - if (auto VFSWithRemapping = createVFSFromCompilerInvocation( - Clang->getInvocation(), Clang->getDiagnostics(), VFS)) - VFS = VFSWithRemapping; - Clang->createFileManager(VFS); - + Clang->createVirtualFileSystem(VFS, &DiagsClient); + Clang->createDiagnostics(&DiagsClient, false); + Clang->createFileManager(); if (!Clang->createTarget()) return nullptr; diff --git a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp index 91d2697712b6e..a09ba01fb678c 100644 --- a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp @@ -625,9 +625,10 @@ TEST_F(PragmaIncludeTest, ExportInUnnamedBuffer) { *Diags, "clang")); auto Clang = std::make_unique(std::move(Invocation)); - Clang->createDiagnostics(*VFS); + Clang->createVirtualFileSystem(VFS); + Clang->createDiagnostics(); - auto *FM = Clang->createFileManager(VFS); + auto *FM = Clang->createFileManager(); ASSERT_TRUE(Clang->ExecuteAction(*Inputs.MakeAction())); EXPECT_THAT( PI.getExporters(llvm::cantFail(FM->getFileRef("foo.h")), *FM), diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 97a03bde858c0..2827074690286 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -87,6 +87,9 @@ class CompilerInstance : public ModuleLoader { /// The options used in this compiler instance. std::shared_ptr Invocation; + /// The virtual file system instance. + IntrusiveRefCntPtr VFS; + /// The diagnostics engine instance. IntrusiveRefCntPtr Diagnostics; @@ -453,7 +456,31 @@ class CompilerInstance : public ModuleLoader { /// @name Virtual File System /// @{ - llvm::vfs::FileSystem &getVirtualFileSystem() const; + bool hasVirtualFileSystem() const { return VFS != nullptr; } + + /// Create a virtual file system instance based on the invocation. + /// + /// @param BaseFS The file system that may be used when configuring the final + /// file system, and act as the underlying file system. Must not + /// be NULL. + /// @param DC If non-NULL, the diagnostic consumer to be used in case + /// configuring the file system emits diagnostics. Note that the + /// DiagnosticsEngine using the consumer won't obey the + /// --warning-suppression-mappings= flag. + void createVirtualFileSystem(IntrusiveRefCntPtr + BaseFS = llvm::vfs::getRealFileSystem(), + DiagnosticConsumer *DC = nullptr); + + /// Use the given file system. + void setVirtualFileSystem(IntrusiveRefCntPtr FS) { + VFS = std::move(FS); + } + + llvm::vfs::FileSystem &getVirtualFileSystem() const { return *VFS; } + + IntrusiveRefCntPtr getVirtualFileSystemPtr() const { + return VFS; + } /// @} /// @name File Manager @@ -691,32 +718,31 @@ class CompilerInstance : public ModuleLoader { /// Note that this routine also replaces the diagnostic client, /// allocating one if one is not provided. /// - /// \param VFS is used for any IO needed when creating DiagnosticsEngine. It - /// doesn't replace VFS in the CompilerInstance (if any). - /// /// \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(llvm::vfs::FileSystem &VFS, - DiagnosticConsumer *Client = nullptr, + void createDiagnostics(DiagnosticConsumer *Client = nullptr, bool ShouldOwnClient = true); - /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter. + /// Create a DiagnosticsEngine object. /// /// If no diagnostic client is provided, this creates a /// DiagnosticConsumer that is owned by the returned diagnostic /// object, if using directly the caller is responsible for /// releasing the returned DiagnosticsEngine's client eventually. /// + /// \param VFS The file system used to load the suppression mappings file. + /// /// \param Opts - The diagnostic options; note that the created text /// diagnostic object contains a reference to these options. /// /// \param Client If non-NULL, a diagnostic client that will be /// attached to (and, then, owned by) the returned DiagnosticsEngine - /// object. + /// object. If NULL, the returned DiagnosticsEngine will own a newly-created + /// client. /// /// \param CodeGenOpts If non-NULL, the code gen options in use, which may be /// used by some diagnostics printers (for logging purposes only). @@ -731,8 +757,7 @@ class CompilerInstance : public ModuleLoader { /// Create the file manager and replace any existing one with it. /// /// \return The new file manager on success, or null on failure. - FileManager * - createFileManager(IntrusiveRefCntPtr VFS = nullptr); + FileManager *createFileManager(); /// Create the source manager and replace any existing one with it. void createSourceManager(FileManager &FileMgr); diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h index 4bf5f8ec15b86..d3455d240d916 100644 --- a/clang/include/clang/Frontend/CompilerInvocation.h +++ b/clang/include/clang/Frontend/CompilerInvocation.h @@ -434,7 +434,8 @@ IntrusiveRefCntPtr createVFSFromCompilerInvocation( IntrusiveRefCntPtr createVFSFromCompilerInvocation( const CompilerInvocation &CI, DiagnosticsEngine &Diags, - IntrusiveRefCntPtr BaseFS); + IntrusiveRefCntPtr BaseFS, + std::shared_ptr OverrideCAS = nullptr); IntrusiveRefCntPtr createVFSFromOverlayFiles(ArrayRef VFSOverlayFiles, diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 3a5339353bf67..3ea1a73aeb3e0 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1180,10 +1180,12 @@ bool ASTUnit::Parse(std::shared_ptr PCHContainerOps, // Ensure that Clang has a FileManager with the right VFS, which may have // changed above in AddImplicitPreamble. If VFS is nullptr, rely on // createFileManager to create one. - if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) + if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) { + Clang->setVirtualFileSystem(std::move(VFS)); Clang->setFileManager(FileMgr); - else { - Clang->createFileManager(std::move(VFS)); + } else { + Clang->setVirtualFileSystem(std::move(VFS)); + Clang->createFileManager(); FileMgr = Clang->getFileManagerPtr(); } diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index 5d1cd15fdeadf..362551fd3b917 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -123,6 +123,7 @@ clang::createChainedIncludesSource(CompilerInstance &CI, auto Clang = std::make_unique( std::move(CInvok), CI.getPCHContainerOperations()); + Clang->createVirtualFileSystem(); Clang->setDiagnostics(Diags); Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts())); diff --git a/clang/lib/Frontend/CompileJobCache.cpp b/clang/lib/Frontend/CompileJobCache.cpp index 6e32eb80edb87..4d0355da01351 100644 --- a/clang/lib/Frontend/CompileJobCache.cpp +++ b/clang/lib/Frontend/CompileJobCache.cpp @@ -613,8 +613,8 @@ Expected> CompileJobCache::replayCachedResult( std::optional *OutMCOutputID) { CompilerInstance Clang(std::move(Invok)); llvm::raw_svector_ostream DiagOS(DiagText); + Clang.createVirtualFileSystem(llvm::vfs::getRealFileSystem()); Clang.createDiagnostics( - *llvm::vfs::getRealFileSystem(), new TextDiagnosticPrinter(DiagOS, Clang.getDiagnosticOpts())); Clang.setVerboseOutputStream(DiagOS); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index c16726010ffb2..c19e3b3d54542 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -173,12 +173,11 @@ bool CompilerInstance::createTarget() { return true; } -llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const { - return getFileManager().getVirtualFileSystem(); -} - -void CompilerInstance::setFileManager( - llvm::IntrusiveRefCntPtr Value) { +void CompilerInstance::setFileManager(IntrusiveRefCntPtr Value) { + if (!hasVirtualFileSystem()) + setVirtualFileSystem(Value->getVirtualFileSystemPtr()); + assert(Value == nullptr || + getVirtualFileSystemPtr() == Value->getVirtualFileSystemPtr()); FileMgr = std::move(Value); } @@ -298,6 +297,20 @@ static void collectVFSEntries(CompilerInstance &CI, MDC->addFile(E.VPath, E.RPath); } +void CompilerInstance::createVirtualFileSystem( + IntrusiveRefCntPtr BaseFS, DiagnosticConsumer *DC) { + DiagnosticOptions DiagOpts; + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DC, + /*ShouldOwnClient=*/false); + + VFS = createVFSFromCompilerInvocation(getInvocation(), Diags, + std::move(BaseFS), CAS); + // FIXME: Should this go into createVFSFromCompilerInvocation? + if (getFrontendOpts().ShowStats) + VFS = + llvm::makeIntrusiveRefCnt(std::move(VFS)); +} + // Diagnostics static void SetUpDiagnosticLog(DiagnosticOptions &DiagOpts, const CodeGenOptions *CodeGenOpts, @@ -349,11 +362,10 @@ static void SetupSerializedDiagnostics(DiagnosticOptions &DiagOpts, } } -void CompilerInstance::createDiagnostics(llvm::vfs::FileSystem &VFS, - DiagnosticConsumer *Client, +void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client, bool ShouldOwnClient) { - Diagnostics = createDiagnostics(VFS, getDiagnosticOpts(), Client, - ShouldOwnClient, &getCodeGenOpts()); + Diagnostics = createDiagnostics(getVirtualFileSystem(), getDiagnosticOpts(), + Client, ShouldOwnClient, &getCodeGenOpts()); } IntrusiveRefCntPtr CompilerInstance::createDiagnostics( @@ -391,18 +403,9 @@ IntrusiveRefCntPtr CompilerInstance::createDiagnostics( // File Manager -FileManager *CompilerInstance::createFileManager( - IntrusiveRefCntPtr VFS) { - if (!VFS) - VFS = FileMgr ? &FileMgr->getVirtualFileSystem() - : createVFSFromCompilerInvocation(getInvocation(), - getDiagnostics(), CAS); - assert(VFS && "FileManager has no VFS?"); - if (getFrontendOpts().ShowStats) - VFS = - llvm::makeIntrusiveRefCnt(std::move(VFS)); - FileMgr = llvm::makeIntrusiveRefCnt(getFileSystemOpts(), - std::move(VFS)); +FileManager *CompilerInstance::createFileManager() { + assert(VFS && "CompilerInstance needs a VFS for creating FileManager"); + FileMgr = llvm::makeIntrusiveRefCnt(getFileSystemOpts(), VFS); return FileMgr.get(); } @@ -1400,20 +1403,21 @@ std::unique_ptr CompilerInstance::cloneForModuleCompileImpl( auto &Inv = Instance.getInvocation(); if (ThreadSafeConfig) { - Instance.createFileManager(ThreadSafeConfig->getVFS()); + Instance.setVirtualFileSystem(ThreadSafeConfig->getVFS()); + Instance.createFileManager(); } else if (FrontendOpts.ModulesShareFileManager) { + Instance.setVirtualFileSystem(getVirtualFileSystemPtr()); Instance.setFileManager(getFileManagerPtr()); } else { - Instance.createFileManager(&getVirtualFileSystem()); + Instance.setVirtualFileSystem(getVirtualFileSystemPtr()); + Instance.createFileManager(); } if (ThreadSafeConfig) { - Instance.createDiagnostics(Instance.getVirtualFileSystem(), - &ThreadSafeConfig->getDiagConsumer(), + Instance.createDiagnostics(&ThreadSafeConfig->getDiagConsumer(), /*ShouldOwnClient=*/false); } else { Instance.createDiagnostics( - Instance.getVirtualFileSystem(), new ForwardingDiagnosticConsumer(getDiagnosticClient()), /*ShouldOwnClient=*/true); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index adeea731649d8..236b7da6f43ec 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1536,9 +1536,13 @@ static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) { static IntrusiveRefCntPtr createBaseFS(const FileSystemOptions &FSOpts, const FrontendOptions &FEOpts, const CASOptions &CASOpts, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr BaseFS, std::shared_ptr OverrideCAS) { + if (!OverrideCAS) + return BaseFS; + if (FSOpts.CASFileSystemRootID.empty() && FEOpts.CASIncludeTreeID.empty()) - return llvm::vfs::getRealFileSystem(); + return BaseFS; // If no CAS was provided, create one with CASOptions. std::shared_ptr CAS = std::move(OverrideCAS); @@ -2223,7 +2227,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, } if (!Opts.ProfileInstrumentUsePath.empty()) { - auto FS = createBaseFS(FSOpts, FEOpts, CASOpts, Diags, nullptr); + auto FS = createBaseFS(FSOpts, FEOpts, CASOpts, Diags, + llvm::vfs::getRealFileSystem(), nullptr); setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath, *FS, Diags); } @@ -5901,17 +5906,19 @@ clang::createVFSFromCompilerInvocation( const CompilerInvocation &CI, DiagnosticsEngine &Diags, std::shared_ptr OverrideCAS) { return createVFSFromCompilerInvocation( - CI, Diags, - createBaseFS(CI.getFileSystemOpts(), CI.getFrontendOpts(), - CI.getCASOpts(), Diags, std::move(OverrideCAS))); + CI, Diags, llvm::vfs::getRealFileSystem(), std::move(OverrideCAS)); } IntrusiveRefCntPtr clang::createVFSFromCompilerInvocation( const CompilerInvocation &CI, DiagnosticsEngine &Diags, - IntrusiveRefCntPtr BaseFS) { - return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles, - Diags, std::move(BaseFS)); + IntrusiveRefCntPtr BaseFS, + std::shared_ptr OverrideCAS) { + return createVFSFromOverlayFiles( + CI.getHeaderSearchOpts().VFSOverlayFiles, Diags, + createBaseFS(CI.getFileSystemOpts(), CI.getFrontendOpts(), + CI.getCASOpts(), Diags, std::move(BaseFS), + std::move(OverrideCAS))); } IntrusiveRefCntPtr clang::createVFSFromOverlayFiles( diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index cb184d4eacf3f..aecc36f65cbb0 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -916,6 +916,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. + CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr()); CI.setFileManager(AST->getFileManagerPtr()); CI.createSourceManager(CI.getFileManager()); CI.getSourceManager().initializeForReplay(AST->getSourceManager()); @@ -1006,7 +1007,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, return true; } - // Set up the file and source managers, if needed. + // Set up the file system, file and source managers, if needed. + if (!CI.hasVirtualFileSystem()) + CI.createVirtualFileSystem(); if (!CI.hasFileManager()) { if (!CI.createFileManager()) { return false; diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp index 1d278b51b940f..9600a1956020f 100644 --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -479,12 +479,10 @@ llvm::ErrorOr PrecompiledPreamble::Build( Diagnostics->Reset(); ProcessWarningOptions(*Diagnostics, Clang->getDiagnosticOpts(), *VFS); - VFS = createVFSFromCompilerInvocation(Clang->getInvocation(), *Diagnostics, - VFS); + Clang->createVirtualFileSystem(VFS, Diagnostics->getClient()); // Create a file manager object to provide access to and cache the filesystem. - Clang->setFileManager( - llvm::makeIntrusiveRefCnt(Clang->getFileSystemOpts(), VFS)); + Clang->createFileManager(); // Create the source manager. Clang->setSourceManager(llvm::makeIntrusiveRefCnt( diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp index 9d82af8ac7f91..e47aa4eba4f0e 100644 --- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp @@ -250,8 +250,8 @@ class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener { CompilerInstance Instance( std::make_shared(CI.getInvocation()), CI.getPCHContainerOperations(), &CI.getModuleCache()); + Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr()); Instance.createDiagnostics( - CI.getVirtualFileSystem(), new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), /*ShouldOwnClient=*/true); Instance.getFrontendOpts().DisableFree = false; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 9509c88003b56..921862b1bbb96 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -107,8 +107,10 @@ CreateCI(const llvm::opt::ArgStringList &Argv) { Clang->getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(Argv[0], nullptr); + Clang->createVirtualFileSystem(); + // Create the actual diagnostics engine. - Clang->createDiagnostics(*llvm::vfs::getRealFileSystem()); + Clang->createDiagnostics(); if (!Clang->hasDiagnostics()) return llvm::createStringError(llvm::errc::not_supported, "Initialization failed. " @@ -487,7 +489,8 @@ Interpreter::createWithCUDA(std::unique_ptr CI, std::make_unique( llvm::vfs::getRealFileSystem()); OverlayVFS->pushOverlay(IMVFS); - CI->createFileManager(OverlayVFS); + CI->createVirtualFileSystem(OverlayVFS); + CI->createFileManager(); llvm::Expected> InterpOrErr = Interpreter::create(std::move(CI)); diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp index 7bc34f61255f4..3526983097d14 100644 --- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp @@ -75,8 +75,8 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) { // behavior for models CompilerInstance Instance(std::move(Invocation), CI.getPCHContainerOperations()); + Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr()); Instance.createDiagnostics( - CI.getVirtualFileSystem(), new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), /*ShouldOwnClient=*/true); diff --git a/clang/lib/Testing/TestAST.cpp b/clang/lib/Testing/TestAST.cpp index b59a8d55129de..9ad0de95530fb 100644 --- a/clang/lib/Testing/TestAST.cpp +++ b/clang/lib/Testing/TestAST.cpp @@ -54,8 +54,10 @@ class StoreDiagnostics : public DiagnosticConsumer { // Fills in the bits of a CompilerInstance that weren't initialized yet. // Provides "empty" ASTContext etc if we fail before parsing gets started. void createMissingComponents(CompilerInstance &Clang) { + if (!Clang.hasVirtualFileSystem()) + Clang.createVirtualFileSystem(); if (!Clang.hasDiagnostics()) - Clang.createDiagnostics(*llvm::vfs::getRealFileSystem()); + Clang.createDiagnostics(); if (!Clang.hasFileManager()) Clang.createFileManager(); if (!Clang.hasSourceManager()) @@ -98,7 +100,9 @@ TestAST::TestAST(const TestInputs &In) { // Extra error conditions are reported through diagnostics, set that up first. bool ErrorOK = In.ErrorOK || llvm::StringRef(In.Code).contains("error-ok"); - Clang->createDiagnostics(*VFS, new StoreDiagnostics(Diagnostics, !ErrorOK)); + auto DiagConsumer = new StoreDiagnostics(Diagnostics, !ErrorOK); + Clang->createVirtualFileSystem(std::move(VFS), DiagConsumer); + Clang->createDiagnostics(DiagConsumer); // Parse cc1 argv, (typically [-std=c++20 input.cc]) into CompilerInvocation. std::vector Argv; @@ -115,7 +119,7 @@ TestAST::TestAST(const TestInputs &In) { } assert(!Clang->getInvocation().getFrontendOpts().DisableFree); - Clang->createFileManager(VFS); + Clang->createFileManager(); // Running the FrontendAction creates the other components: SourceManager, // Preprocessor, ASTContext, Sema. Preprocessor needs TargetInfo to be set. diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 73482a7c52fcf..828dbaca98bb0 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -566,12 +566,13 @@ class DependencyScanningAction { ScanInstance.getInvocation().getCASOpts() = CASOpts; ScanInstance.setBuildingModule(false); + ScanInstance.createVirtualFileSystem(FS, DiagConsumer); + // Create the compiler's actual diagnostics engine. if (!DiagGenerationAsCompilation) sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); - ScanInstance.createDiagnostics(*FS, DiagConsumer, - /*ShouldOwnClient=*/false); + ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); if (!ScanInstance.hasDiagnostics()) return false; if (VerboseOS) @@ -596,13 +597,8 @@ class DependencyScanningAction { ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage = any(Service.getOptimizeArgs() & ScanningOptimizations::VFS); - // Support for virtual file system overlays. - FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(), - ScanInstance.getDiagnostics(), - std::move(FS)); - // Create a new FileManager to match the invocation's FileSystemOptions. - auto *FileMgr = ScanInstance.createFileManager(FS); + auto *FileMgr = ScanInstance.createFileManager(); // Use the dependency scanning optimized file system if requested to do so. if (DepFS) { diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index ea5942ac0141b..25f84b54629a6 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -453,8 +453,7 @@ bool FrontendActionFactory::runInvocation( std::unique_ptr ScopedToolAction(create()); // Create the compiler's actual diagnostics engine. - Compiler.createDiagnostics(Files->getVirtualFileSystem(), DiagConsumer, - /*ShouldOwnClient=*/false); + Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); if (!Compiler.hasDiagnostics()) return false; diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp index 7f5df9259889b..5595c3612f517 100644 --- a/clang/tools/clang-import-test/clang-import-test.cpp +++ b/clang/tools/clang-import-test/clang-import-test.cpp @@ -207,8 +207,8 @@ std::unique_ptr BuildCompilerInstance() { auto Ins = std::make_unique(std::move(Inv)); - Ins->createDiagnostics(*llvm::vfs::getRealFileSystem(), DC.release(), - /*ShouldOwnClient=*/true); + Ins->createVirtualFileSystem(llvm::vfs::getRealFileSystem(), DC.get()); + Ins->createDiagnostics(DC.release(), /*ShouldOwnClient=*/true); TargetInfo *TI = TargetInfo::CreateTargetInfo( Ins->getDiagnostics(), Ins->getInvocation().getTargetOpts()); diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index 327fb730ede77..9a47db96df2e2 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -115,7 +115,7 @@ static bool run(ArrayRef Args, const char *ProgName) { // Set up compilation. std::unique_ptr CI(new CompilerInstance()); CI->setFileManager(FM); - CI->createDiagnostics(FM->getVirtualFileSystem()); + CI->createDiagnostics(); if (!CI->hasDiagnostics()) return EXIT_FAILURE; diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index 5588c7f17276b..df19f1f76b763 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -275,8 +275,11 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { Clang->getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(Argv0, MainAddr); + /// Create the actual file system. + Clang->createVirtualFileSystem(llvm::vfs::getRealFileSystem(), DiagsBuffer); + // Create the actual diagnostics engine. - Clang->createDiagnostics(*llvm::vfs::getRealFileSystem()); + Clang->createDiagnostics(); if (!Clang->hasDiagnostics()) return 1; @@ -347,8 +350,7 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { // options are stored in the compiler invocation and we can recreate the VFS // from the compiler invocation. if (!Clang->hasFileManager()) - Clang->createFileManager(createVFSFromCompilerInvocation( - Clang->getInvocation(), Clang->getDiagnostics())); + Clang->createFileManager(); llvm::vfs::OnDiskOutputBackend Backend; if (std::optional profilerOutput = diff --git a/clang/unittests/AST/ExternalASTSourceTest.cpp b/clang/unittests/AST/ExternalASTSourceTest.cpp index 21d4ce4dcf212..15483ad250976 100644 --- a/clang/unittests/AST/ExternalASTSourceTest.cpp +++ b/clang/unittests/AST/ExternalASTSourceTest.cpp @@ -59,7 +59,8 @@ bool testExternalASTSource(llvm::IntrusiveRefCntPtr Source, CompilerInvocation::CreateFromArgs(*Invocation, Args, *InvocationDiags); CompilerInstance Compiler(std::move(Invocation)); - Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + Compiler.createDiagnostics(); TestFrontendAction Action(Source); return Compiler.ExecuteAction(Action); diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h index a6fec7fb0945d..66e45dd259935 100644 --- a/clang/unittests/CodeGen/TestCompiler.h +++ b/clang/unittests/CodeGen/TestCompiler.h @@ -36,7 +36,8 @@ struct TestCompiler { clang::CodeGenOptions CGO = clang::CodeGenOptions()) { compiler.getLangOpts() = LO; compiler.getCodeGenOpts() = CGO; - compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + compiler.createDiagnostics(); std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple()); llvm::Triple Tr(TrStr); diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp index 3aff69c981531..53f1cc88adf28 100644 --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -579,7 +579,8 @@ TEST(CompilerInvocation, SplitSwarfSingleCrash) { TEST(ToolChainTest, UEFICallingConventionTest) { clang::CompilerInstance compiler; - compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + compiler.createDiagnostics(); std::string TrStr = "x86_64-unknown-uefi"; llvm::Triple Tr(TrStr); diff --git a/clang/unittests/Frontend/CodeGenActionTest.cpp b/clang/unittests/Frontend/CodeGenActionTest.cpp index b2792c44ba5fe..182afdc7ea313 100644 --- a/clang/unittests/Frontend/CodeGenActionTest.cpp +++ b/clang/unittests/Frontend/CodeGenActionTest.cpp @@ -52,7 +52,8 @@ TEST(CodeGenTest, TestNullCodeGen) { Invocation->getFrontendOpts().ProgramAction = EmitLLVM; Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance Compiler(std::move(Invocation)); - Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + Compiler.createDiagnostics(); EXPECT_TRUE(Compiler.hasDiagnostics()); std::unique_ptr Act(new NullCodeGenAction); @@ -69,7 +70,8 @@ TEST(CodeGenTest, CodeGenFromIRMemBuffer) { Invocation->getFrontendOpts().ProgramAction = frontend::EmitLLVMOnly; Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance Compiler(std::move(Invocation)); - Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + Compiler.createDiagnostics(); EXPECT_TRUE(Compiler.hasDiagnostics()); EmitLLVMOnlyAction Action; diff --git a/clang/unittests/Frontend/CompilerInstanceTest.cpp b/clang/unittests/Frontend/CompilerInstanceTest.cpp index 7c1b6539095fa..36cac5a5dd010 100644 --- a/clang/unittests/Frontend/CompilerInstanceTest.cpp +++ b/clang/unittests/Frontend/CompilerInstanceTest.cpp @@ -72,6 +72,7 @@ TEST(CompilerInstance, DefaultVFSOverlayFromInvocation) { // in the CompilerInvocation (as we don't explicitly set our own). CompilerInstance Instance(std::move(CInvok)); Instance.setDiagnostics(Diags); + Instance.createVirtualFileSystem(); Instance.createFileManager(); // Check if the virtual file exists which means that our VFS is used by the @@ -135,8 +136,9 @@ TEST(CompilerInstance, MultipleInputsCleansFileIDs) { ASSERT_TRUE(CInvok) << "could not create compiler invocation"; CompilerInstance Instance(std::move(CInvok)); + Instance.setVirtualFileSystem(VFS); Instance.setDiagnostics(Diags); - Instance.createFileManager(VFS); + Instance.createFileManager(); // Run once for `a.cc` and then for `a.h`. This makes sure we get the same // file ID for `b.h` in the second run as `a.h` from first run. diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp index 48c0cfd6a185a..c4003182c4b1d 100644 --- a/clang/unittests/Frontend/FrontendActionTest.cpp +++ b/clang/unittests/Frontend/FrontendActionTest.cpp @@ -91,7 +91,8 @@ TEST(ASTFrontendAction, Sanity) { invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance compiler(std::move(invocation)); - compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + compiler.createDiagnostics(); TestASTFrontendAction test_action; ASSERT_TRUE(compiler.ExecuteAction(test_action)); @@ -110,7 +111,8 @@ TEST(ASTFrontendAction, IncrementalParsing) { invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance compiler(std::move(invocation)); - compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + compiler.createDiagnostics(); TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true); ASSERT_TRUE(compiler.ExecuteAction(test_action)); @@ -136,7 +138,8 @@ TEST(ASTFrontendAction, LateTemplateIncrementalParsing) { invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance compiler(std::move(invocation)); - compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + compiler.createDiagnostics(); TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true, /*actOnEndOfTranslationUnit=*/true); @@ -181,7 +184,8 @@ TEST(PreprocessorFrontendAction, EndSourceFile) { Invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance Compiler(std::move(Invocation)); - Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + Compiler.createDiagnostics(); TestPPCallbacks *Callbacks = new TestPPCallbacks; TestPPCallbacksFrontendAction TestAction(Callbacks); @@ -242,8 +246,8 @@ TEST(ASTFrontendAction, ExternalSemaSource) { Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance Compiler(std::move(Invocation)); auto *TDC = new TypoDiagnosticConsumer; - Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem(), TDC, - /*ShouldOwnClient=*/true); + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + Compiler.createDiagnostics(TDC, /*ShouldOwnClient=*/true); Compiler.setExternalSemaSource( llvm::makeIntrusiveRefCnt(Compiler)); @@ -275,7 +279,8 @@ TEST(GeneratePCHFrontendAction, CacheGeneratedPCH) { Invocation->getFrontendOpts().ProgramAction = frontend::GeneratePCH; Invocation->getTargetOpts().Triple = "x86_64-apple-darwin19.0.0"; CompilerInstance Compiler(std::move(Invocation)); - Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + Compiler.createDiagnostics(); GeneratePCHAction TestAction; ASSERT_TRUE(Compiler.ExecuteAction(TestAction)); diff --git a/clang/unittests/Frontend/OutputStreamTest.cpp b/clang/unittests/Frontend/OutputStreamTest.cpp index dfb5a544cb88a..9e288f86351ca 100644 --- a/clang/unittests/Frontend/OutputStreamTest.cpp +++ b/clang/unittests/Frontend/OutputStreamTest.cpp @@ -38,7 +38,8 @@ TEST(FrontendOutputTests, TestOutputStream) { new raw_svector_ostream(IRBuffer)); Compiler.setOutputStream(std::move(IRStream)); - Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + Compiler.createDiagnostics(); bool Success = ExecuteCompilerInvocation(&Compiler); EXPECT_TRUE(Success); @@ -62,8 +63,8 @@ TEST(FrontendOutputTests, TestVerboseOutputStreamShared) { Compiler.setOutputStream(std::make_unique()); DiagnosticOptions DiagOpts; - Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem(), - new TextDiagnosticPrinter(llvm::nulls(), DiagOpts), + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); + Compiler.createDiagnostics(new TextDiagnosticPrinter(llvm::nulls(), DiagOpts), true); Compiler.setVerboseOutputStream(VerboseStream); @@ -92,8 +93,8 @@ TEST(FrontendOutputTests, TestVerboseOutputStreamOwned) { Compiler.setOutputStream(std::make_unique()); DiagnosticOptions DiagOpts; + Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); Compiler.createDiagnostics( - *llvm::vfs::getRealFileSystem(), new TextDiagnosticPrinter(llvm::nulls(), DiagOpts), true); Compiler.setVerboseOutputStream(std::move(VerboseStream)); diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp index 92ff76b016283..24e2fd65f3c0a 100644 --- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp +++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp @@ -91,10 +91,8 @@ export int aa = 43; Instance.getFrontendOpts().OutputFile = BMIPath; - if (auto VFSWithRemapping = createVFSFromCompilerInvocation( - Instance.getInvocation(), Instance.getDiagnostics(), CIOpts.VFS)) - CIOpts.VFS = VFSWithRemapping; - Instance.createFileManager(CIOpts.VFS); + Instance.createVirtualFileSystem(CIOpts.VFS); + Instance.createFileManager(); Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true; @@ -123,7 +121,8 @@ export int aa = 43; CompilerInstance Clang(std::move(Invocation)); Clang.setDiagnostics(Diags); - FileManager *FM = Clang.createFileManager(CIOpts.VFS); + Clang.createVirtualFileSystem(CIOpts.VFS); + FileManager *FM = Clang.createFileManager(); Clang.createSourceManager(*FM); EXPECT_TRUE(Clang.createTarget()); diff --git a/clang/unittests/Serialization/ModuleCacheTest.cpp b/clang/unittests/Serialization/ModuleCacheTest.cpp index 1f64401a08314..e9b8da3dba6af 100644 --- a/clang/unittests/Serialization/ModuleCacheTest.cpp +++ b/clang/unittests/Serialization/ModuleCacheTest.cpp @@ -121,6 +121,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPath) { createInvocationAndEnableFree(Args, CIOpts); ASSERT_TRUE(Invocation); CompilerInstance Instance(std::move(Invocation)); + Instance.setVirtualFileSystem(CIOpts.VFS); Instance.setDiagnostics(Diags); SyntaxOnlyAction Action; ASSERT_TRUE(Instance.ExecuteAction(Action)); @@ -145,6 +146,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPath) { CompilerInstance Instance2(std::move(Invocation2), Instance.getPCHContainerOperations(), &Instance.getModuleCache()); + Instance2.setVirtualFileSystem(CIOpts.VFS); Instance2.setDiagnostics(Diags); SyntaxOnlyAction Action2; ASSERT_FALSE(Instance2.ExecuteAction(Action2)); @@ -171,6 +173,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPathAllowErrors) { createInvocationAndEnableFree(Args, CIOpts); ASSERT_TRUE(Invocation); CompilerInstance Instance(std::move(Invocation)); + Instance.setVirtualFileSystem(CIOpts.VFS); Instance.setDiagnostics(Diags); SyntaxOnlyAction Action; ASSERT_TRUE(Instance.ExecuteAction(Action)); @@ -189,6 +192,7 @@ TEST_F(ModuleCacheTest, CachedModuleNewPathAllowErrors) { CompilerInstance Instance2(std::move(Invocation2), Instance.getPCHContainerOperations(), &Instance.getModuleCache()); + Instance2.setVirtualFileSystem(CIOpts.VFS); Instance2.setDiagnostics(Diags); SyntaxOnlyAction Action2; ASSERT_FALSE(Instance2.ExecuteAction(Action2)); diff --git a/clang/unittests/Serialization/NoCommentsTest.cpp b/clang/unittests/Serialization/NoCommentsTest.cpp index ed96c7c7959a0..01bb6999a7c90 100644 --- a/clang/unittests/Serialization/NoCommentsTest.cpp +++ b/clang/unittests/Serialization/NoCommentsTest.cpp @@ -99,6 +99,7 @@ void foo() {} ASSERT_TRUE(Invocation); CompilerInstance Instance(std::move(Invocation)); + Instance.createVirtualFileSystem(CIOpts.VFS); Instance.setDiagnostics(Diags); Instance.getFrontendOpts().OutputFile = CacheBMIPath; GenerateReducedModuleInterfaceAction Action; diff --git a/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp b/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp index f9d7736a77ee1..55ee72875ead2 100644 --- a/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp +++ b/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp @@ -113,12 +113,8 @@ export using ::E; auto Clang = std::make_unique(std::move(Invocation)); Clang->setDiagnostics(Diags); - - if (auto VFSWithRemapping = createVFSFromCompilerInvocation( - Clang->getInvocation(), Clang->getDiagnostics(), VFS)) - VFS = VFSWithRemapping; - - Clang->createFileManager(VFS); + Clang->createVirtualFileSystem(VFS); + Clang->createFileManager(); EXPECT_TRUE(Clang->createTarget()); Buffer.release(); diff --git a/clang/unittests/Support/TimeProfilerTest.cpp b/clang/unittests/Support/TimeProfilerTest.cpp index c762214dba41e..d85743da31358 100644 --- a/clang/unittests/Support/TimeProfilerTest.cpp +++ b/clang/unittests/Support/TimeProfilerTest.cpp @@ -53,7 +53,6 @@ bool compileFromString(StringRef Code, StringRef Standard, StringRef File, FS->addFile(Header.getKey(), 0, MemoryBuffer::getMemBuffer(Header.getValue())); } - auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), FS); auto Invocation = std::make_shared(); std::vector Args = {Standard.data(), File.data()}; @@ -63,8 +62,9 @@ bool compileFromString(StringRef Code, StringRef Standard, StringRef File, CompilerInvocation::CreateFromArgs(*Invocation, Args, *InvocationDiags); CompilerInstance Compiler(std::move(Invocation)); - Compiler.createDiagnostics(Files->getVirtualFileSystem()); - Compiler.setFileManager(Files); + Compiler.setVirtualFileSystem(std::move(FS)); + Compiler.createDiagnostics(); + Compiler.createFileManager(); class TestFrontendAction : public ASTFrontendAction { private: diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp index 256a276702c67..ec5e36e07272b 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp @@ -65,8 +65,7 @@ class TestDependencyScanningAction : public tooling::ToolAction { std::move(PCHContainerOps)); Compiler.setFileManager(FileMgr); - Compiler.createDiagnostics(FileMgr->getVirtualFileSystem(), DiagConsumer, - /*ShouldOwnClient=*/false); + Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); if (!Compiler.hasDiagnostics()) return false; diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index dbebbbd38093e..62d245734c288 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -2210,7 +2210,9 @@ class CommandObjectTargetModulesDumpClangPCMInfo : public CommandObjectParsed { const char *clang_args[] = {"clang", pcm_path}; clang::CompilerInstance compiler(clang::createInvocation(clang_args)); - compiler.createDiagnostics(*FileSystem::Instance().GetVirtualFileSystem()); + compiler.setVirtualFileSystem( + FileSystem::Instance().GetVirtualFileSystem()); + compiler.createDiagnostics(); // Pass empty deleter to not attempt to free memory that was allocated // outside of the current scope, possibly statically. diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 2b9c0d47433e2..f1f114474db82 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -769,14 +769,16 @@ ClangExpressionParser::ClangExpressionParser( m_compiler = std::make_unique(); // Make sure clang uses the same VFS as LLDB. - m_compiler->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); + m_compiler->setVirtualFileSystem( + FileSystem::Instance().GetVirtualFileSystem()); + m_compiler->createFileManager(); // 2. Configure the compiler with a set of default options that are // appropriate for most situations. SetupTargetOpts(*m_compiler, *target_sp); // 3. Create and install the target on the compiler. - m_compiler->createDiagnostics(m_compiler->getVirtualFileSystem()); + m_compiler->createDiagnostics(); // Limit the number of error diagnostics we emit. // A value of 0 means no limit for both LLDB and Clang. m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit()); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index 7c6ec4e2f5a26..9822f3cb39277 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -745,7 +745,8 @@ ClangModulesDeclVendor::Create(Target &target) { auto instance = std::make_unique(invocation); // Make sure clang uses the same VFS as LLDB. - instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); + instance->setVirtualFileSystem(FileSystem::Instance().GetVirtualFileSystem()); + instance->createFileManager(); instance->setDiagnostics(diagnostics_engine); std::unique_ptr action(new clang::SyntaxOnlyAction); From 93b3165d8ecb097739975c72fad38fa3c371cd7e Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Thu, 18 Sep 2025 11:14:37 -0700 Subject: [PATCH 06/15] Merge pull request #11450 from swiftlang/jan_svoboda/cas-fix-early-vfs [clang] Fix CAS initialization after upstream #158381 (cherry picked from commit 6d730024d6bc072ef25b5415036ec79f122bce13) --- clang/include/clang/Frontend/CompilerInstance.h | 2 +- clang/lib/Frontend/CompileJobCache.cpp | 2 +- clang/lib/Frontend/CompilerInstance.cpp | 10 +++++++--- clang/lib/Frontend/CompilerInvocation.cpp | 3 --- .../DependencyScanning/IncludeTreeActionController.cpp | 3 ++- clang/test/CAS/output-path-error.c | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 2827074690286..38318c26d5c1f 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -1030,7 +1030,7 @@ class CompilerInstance : public ModuleLoader { std::pair, std::shared_ptr> - createCASDatabases(); + getOrCreateCASDatabases(); }; } // end namespace clang diff --git a/clang/lib/Frontend/CompileJobCache.cpp b/clang/lib/Frontend/CompileJobCache.cpp index 4d0355da01351..81597274ca5b8 100644 --- a/clang/lib/Frontend/CompileJobCache.cpp +++ b/clang/lib/Frontend/CompileJobCache.cpp @@ -296,7 +296,7 @@ std::optional CompileJobCache::initialize(CompilerInstance &Clang) { if (!CacheCompileJob) return std::nullopt; - std::tie(CAS, Cache) = Clang.createCASDatabases(); + std::tie(CAS, Cache) = Clang.getOrCreateCASDatabases(); if (!CAS || !Cache) return 1; // Exit with error! diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index c19e3b3d54542..b95d5565f5cb7 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -303,6 +303,10 @@ void CompilerInstance::createVirtualFileSystem( DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DC, /*ShouldOwnClient=*/false); + std::tie(CAS, ActionCache) = + getInvocation().getCASOpts().getOrCreateDatabases( + Diags, /*CreateEmptyCASOnFailure=*/false); + VFS = createVFSFromCompilerInvocation(getInvocation(), Diags, std::move(BaseFS), CAS); // FIXME: Should this go into createVFSFromCompilerInvocation? @@ -974,7 +978,7 @@ llvm::vfs::OutputBackend &CompilerInstance::getOrCreateOutputBackend() { std::pair, std::shared_ptr> -CompilerInstance::createCASDatabases() { +CompilerInstance::getOrCreateCASDatabases() { // Create a new CAS databases from the CompilerInvocation. Future calls to // createFileManager() will use the same CAS. std::tie(CAS, ActionCache) = @@ -986,13 +990,13 @@ CompilerInstance::createCASDatabases() { llvm::cas::ObjectStore &CompilerInstance::getOrCreateObjectStore() { if (!CAS) - createCASDatabases(); + getOrCreateCASDatabases(); return *CAS; } llvm::cas::ActionCache &CompilerInstance::getOrCreateActionCache() { if (!ActionCache) - createCASDatabases(); + getOrCreateCASDatabases(); return *ActionCache; } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 236b7da6f43ec..697457e2ee93d 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1538,9 +1538,6 @@ createBaseFS(const FileSystemOptions &FSOpts, const FrontendOptions &FEOpts, const CASOptions &CASOpts, DiagnosticsEngine &Diags, IntrusiveRefCntPtr BaseFS, std::shared_ptr OverrideCAS) { - if (!OverrideCAS) - return BaseFS; - if (FSOpts.CASFileSystemRootID.empty() && FEOpts.CASIncludeTreeID.empty()) return BaseFS; diff --git a/clang/lib/Tooling/DependencyScanning/IncludeTreeActionController.cpp b/clang/lib/Tooling/DependencyScanning/IncludeTreeActionController.cpp index e27bd3e218017..c6900f9b84290 100644 --- a/clang/lib/Tooling/DependencyScanning/IncludeTreeActionController.cpp +++ b/clang/lib/Tooling/DependencyScanning/IncludeTreeActionController.cpp @@ -282,10 +282,11 @@ void dependencies::addReversePrefixMappingFileSystem( llvm::PrefixMapper ReverseMapper; ReverseMapper.addInverseRange(PrefixMapper.getMappings()); ReverseMapper.sort(); - std::unique_ptr FS = + IntrusiveRefCntPtr FS = llvm::vfs::createPrefixMappingFileSystem( std::move(ReverseMapper), &ScanInstance.getVirtualFileSystem()); + ScanInstance.setVirtualFileSystem(FS); ScanInstance.getFileManager().setVirtualFileSystem(std::move(FS)); } diff --git a/clang/test/CAS/output-path-error.c b/clang/test/CAS/output-path-error.c index b217ba48402cf..a221f3bb29bf0 100644 --- a/clang/test/CAS/output-path-error.c +++ b/clang/test/CAS/output-path-error.c @@ -19,4 +19,4 @@ // RUN: cat %t/output.txt | FileCheck %s --check-prefix=ERROR // CACHE-MISS: remark: compile job cache miss -// ERROR: fatal error: CAS missing expected root-id +// ERROR: fatal error: CAS filesystem cannot be initialized from root-id 'llvmcas://{{.*}}': cannot get reference to root FS From b17b0474da245a4899581f84c7576eb34a2847b0 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Mon, 15 Sep 2025 09:37:19 -0700 Subject: [PATCH 07/15] [clang] Avoid reparsing VFS overlay files for module dep collector (#158372) This PR uses the new-ish `llvm::vfs::FileSystem::visit()` interface to collect VFS overlay entries from an existing `FileSystem` instance rather than parsing the VFS YAML file anew. This prevents duplicate diagnostics as observed by `clang/test/VFS/broken-vfs-module-dep.c`. (cherry picked from commit 4957c473bc73a3a0bf1037adec770547c4a0aa02) --- clang/lib/Frontend/CompilerInstance.cpp | 15 ++++----------- clang/test/VFS/broken-vfs-module-dep.c | 1 - llvm/include/llvm/Support/VirtualFileSystem.h | 10 +++------- llvm/lib/Support/VirtualFileSystem.cpp | 16 +++------------- 4 files changed, 10 insertions(+), 32 deletions(-) diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index b95d5565f5cb7..09b0cf07598fb 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -279,19 +279,12 @@ static void collectIncludePCH(CompilerInstance &CI, static void collectVFSEntries(CompilerInstance &CI, std::shared_ptr MDC) { - if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) - return; - // Collect all VFS found. SmallVector VFSEntries; - for (const std::string &VFSFile : CI.getHeaderSearchOpts().VFSOverlayFiles) { - llvm::ErrorOr> Buffer = - llvm::MemoryBuffer::getFile(VFSFile); - if (!Buffer) - return; - llvm::vfs::collectVFSFromYAML(std::move(Buffer.get()), - /*DiagHandler*/ nullptr, VFSFile, VFSEntries); - } + CI.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &VFS) { + if (auto *RedirectingVFS = dyn_cast(&VFS)) + llvm::vfs::collectVFSEntries(*RedirectingVFS, VFSEntries); + }); for (auto &E : VFSEntries) MDC->addFile(E.VPath, E.RPath); diff --git a/clang/test/VFS/broken-vfs-module-dep.c b/clang/test/VFS/broken-vfs-module-dep.c index 2336306de8c6d..1c371a13e85c9 100644 --- a/clang/test/VFS/broken-vfs-module-dep.c +++ b/clang/test/VFS/broken-vfs-module-dep.c @@ -2,6 +2,5 @@ // RUN: mkdir -p %t // RUN: not %clang_cc1 -module-dependency-dir %t -ivfsoverlay %S/Inputs/invalid-yaml.yaml %s 2>&1 | FileCheck %s -// CHECK: error: Unexpected token // CHECK: error: Unexpected token // CHECK: 1 error generated diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 0b94f5b5f34a5..2dd696faaba48 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -1178,14 +1178,10 @@ class LLVM_ABI RedirectingFileSystem }; /// Collect all pairs of entries from the -/// \p YAMLFilePath. This is used by the module dependency collector to forward +/// \p VFS. This is used by the module dependency collector to forward /// the entries into the reproducer output VFS YAML file. -LLVM_ABI void collectVFSFromYAML( - std::unique_ptr Buffer, - llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, - SmallVectorImpl &CollectedEntries, - void *DiagContext = nullptr, - IntrusiveRefCntPtr ExternalFS = getRealFileSystem()); +void collectVFSEntries(RedirectingFileSystem &VFS, + SmallVectorImpl &CollectedEntries); class YAMLVFSWriter { std::vector Mappings; diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index da5e74867a598..afcfcc7d3f4c3 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -2726,19 +2726,9 @@ static void getVFSEntries(RedirectingFileSystem::Entry *SrcE, Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath())); } -void vfs::collectVFSFromYAML(std::unique_ptr Buffer, - SourceMgr::DiagHandlerTy DiagHandler, - StringRef YAMLFilePath, - SmallVectorImpl &CollectedEntries, - void *DiagContext, - IntrusiveRefCntPtr ExternalFS) { - std::unique_ptr VFS = RedirectingFileSystem::create( - std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext, - std::move(ExternalFS)); - if (!VFS) - return; - ErrorOr RootResult = - VFS->lookupPath("/"); +void vfs::collectVFSEntries(RedirectingFileSystem &VFS, + SmallVectorImpl &CollectedEntries) { + ErrorOr RootResult = VFS.lookupPath("/"); if (!RootResult) return; SmallVector Components; From d4213591df7a7ac2d99761a39c94ada6870773f9 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Mon, 15 Sep 2025 14:30:13 -0700 Subject: [PATCH 08/15] [clang] Don't fail `ExecuteCompilerInvocation()` due to caller errors (#158695) This PR changes the behavior of `clang::ExecuteCompilerInvocation()` so that it only returns early when the `DiagnosticsEngine` emitted errors **within** the function. Handling errors emitted before the function got called is a responsibility of the caller. Necessary for #158381. (cherry picked from commit f33fb0d7b2af203c42d0e7096b29560dda3e71ce) --- clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index a084b883e1b6a..3a8f0d8dd8545 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -214,6 +214,8 @@ CreateFrontendAction(CompilerInstance &CI) { } bool ExecuteCompilerInvocation(CompilerInstance *Clang) { + unsigned NumErrorsBefore = Clang->getDiagnostics().getNumErrors(); + // Honor -help. if (Clang->getFrontendOpts().ShowHelp) { driver::getDriverOptTable().printHelp( @@ -309,9 +311,12 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) { } #endif - // If there were errors in processing arguments, don't do anything else. - if (Clang->getDiagnostics().hasErrorOccurred()) + // If there were errors in the above, don't do anything else. + // This intentionally ignores errors emitted before this function to + // accommodate lenient callers that decided to make progress despite errors. + if (Clang->getDiagnostics().getNumErrors() != NumErrorsBefore) return false; + // Create and execute the frontend action. std::unique_ptr Act(CreateFrontendAction(*Clang)); if (!Act) From 4db01ae73a6bd0b849df467eea1539dfb53ee58a Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Thu, 18 Sep 2025 10:51:21 -0700 Subject: [PATCH 09/15] [clang] Only set non-empty bypass to scan VFS (#159605) Normalizing an empty modules cache path results in an incorrect non-empty path (the working directory). This PR conditionalizes more code to avoid this. Tested downstream by swift/llvm-project and the `DependencyScanningCAPITests.DependencyScanningFSCacheOutOfDate` unit test. (cherry picked from commit 5a339b074e625a7e9c92ae98b93a2bb5e1ae9524) --- .../DependencyScanning/DependencyScanningWorker.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 828dbaca98bb0..b7f8b6b9b0f23 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -602,13 +602,14 @@ class DependencyScanningAction { // Use the dependency scanning optimized file system if requested to do so. if (DepFS) { - SmallString<256> ModulesCachePath; - normalizeModuleCachePath( - *FileMgr, ScanInstance.getHeaderSearchOpts().ModuleCachePath, - ModulesCachePath); DepFS->resetBypassedPathPrefix(); - if (!ModulesCachePath.empty()) + if (!ScanInstance.getHeaderSearchOpts().ModuleCachePath.empty()) { + SmallString<256> ModulesCachePath; + normalizeModuleCachePath( + *FileMgr, ScanInstance.getHeaderSearchOpts().ModuleCachePath, + ModulesCachePath); DepFS->setBypassedPathPrefix(ModulesCachePath); + } ScanInstance.setDependencyDirectivesGetter( std::make_unique(*FileMgr)); From 6398a13a9f6a07e7480d485bd53a1ad971579867 Mon Sep 17 00:00:00 2001 From: git apple-llvm automerger Date: Fri, 26 Sep 2025 18:10:59 -0700 Subject: [PATCH 10/15] Merge commit '0e35f56d40d3' from llvm.org/main into next (cherry picked from commit 3efcc0f02dec8c6f56c90976dc2642f857ac32e2) Conflicts: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp --- .../Tooling/DependencyScanning/CMakeLists.txt | 1 + .../DependencyScannerImpl.cpp | 757 +++++++++++++++++ .../DependencyScannerImpl.h | 91 ++ .../DependencyScanningWorker.cpp | 786 +----------------- 4 files changed, 850 insertions(+), 785 deletions(-) create mode 100644 clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp create mode 100644 clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h diff --git a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt index 917b3f5810e96..e559592189b93 100644 --- a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt +++ b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt @@ -14,6 +14,7 @@ add_clang_library(clangDependencyScanning DependencyScanningWorker.cpp DependencyScanningTool.cpp IncludeTreeActionController.cpp + DependencyScannerImpl.cpp InProcessModuleCache.cpp ModuleDepCollector.cpp ScanAndUpdateArgs.cpp diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp new file mode 100644 index 0000000000000..10a0f54e2dc72 --- /dev/null +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp @@ -0,0 +1,757 @@ +//===- DependencyScanner.cpp - Performs module dependency scanning --------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "DependencyScannerImpl.h" +#include "clang/Basic/DiagnosticCAS.h" +#include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Basic/DiagnosticSerialization.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/MultiplexConsumer.h" +#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" +#include "clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h" + +using namespace clang; +using namespace tooling; +using namespace dependencies; +using llvm::Error; + +namespace { +/// Forwards the gatherered dependencies to the consumer. +class DependencyConsumerForwarder : public DependencyFileGenerator { +public: + DependencyConsumerForwarder(std::unique_ptr Opts, + StringRef WorkingDirectory, DependencyConsumer &C, + bool EmitDependencyFile) + : DependencyFileGenerator(*Opts), WorkingDirectory(WorkingDirectory), + Opts(std::move(Opts)), C(C), EmitDependencyFile(EmitDependencyFile) {} + + void finishedMainFile(DiagnosticsEngine &Diags) override { + C.handleDependencyOutputOpts(*Opts); + llvm::SmallString<256> CanonPath; + for (const auto &File : getDependencies()) { + CanonPath = File; + llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true); + llvm::sys::fs::make_absolute(WorkingDirectory, CanonPath); + C.handleFileDependency(CanonPath); + } + if (EmitDependencyFile) + DependencyFileGenerator::finishedMainFile(Diags); + } + +private: + StringRef WorkingDirectory; + std::unique_ptr Opts; + DependencyConsumer &C; + bool EmitDependencyFile = false; +}; + +static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts, + const HeaderSearchOptions &ExistingHSOpts, + DiagnosticsEngine *Diags, + const LangOptions &LangOpts) { + if (LangOpts.Modules) { + if (HSOpts.VFSOverlayFiles != ExistingHSOpts.VFSOverlayFiles) { + if (Diags) { + Diags->Report(diag::warn_pch_vfsoverlay_mismatch); + auto VFSNote = [&](int Type, ArrayRef VFSOverlays) { + if (VFSOverlays.empty()) { + Diags->Report(diag::note_pch_vfsoverlay_empty) << Type; + } else { + std::string Files = llvm::join(VFSOverlays, "\n"); + Diags->Report(diag::note_pch_vfsoverlay_files) << Type << Files; + } + }; + VFSNote(0, HSOpts.VFSOverlayFiles); + VFSNote(1, ExistingHSOpts.VFSOverlayFiles); + } + } + } + return false; +} + +using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles); + +/// A listener that collects the imported modules and the input +/// files. While visiting, collect vfsoverlays and file inputs that determine +/// whether prebuilt modules fully resolve in stable directories. +class PrebuiltModuleListener : public ASTReaderListener { +public: + PrebuiltModuleListener(CompilerInstance &CI, + PrebuiltModuleFilesT &PrebuiltModuleFiles, + llvm::SmallVector &NewModuleFiles, + PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, + DiagnosticsEngine &Diags, + const ArrayRef StableDirs) + : CI(CI), PrebuiltModuleFiles(PrebuiltModuleFiles), + NewModuleFiles(NewModuleFiles), + PrebuiltModulesASTMap(PrebuiltModulesASTMap), Diags(Diags), + StableDirs(StableDirs) {} + + bool needsImportVisitation() const override { return true; } + bool needsInputFileVisitation() override { return true; } + bool needsSystemInputFileVisitation() override { return true; } + + /// Accumulate the modules are transitively depended on by the initial + /// prebuilt module. + void visitImport(StringRef ModuleName, StringRef Filename) override { + if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second) + NewModuleFiles.push_back(Filename.str()); + + auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(Filename); + PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second; + if (PrebuiltMapEntry.second) + PrebuiltModule.setInStableDir(!StableDirs.empty()); + + if (auto It = PrebuiltModulesASTMap.find(CurrentFile); + It != PrebuiltModulesASTMap.end() && CurrentFile != Filename) + PrebuiltModule.addDependent(It->getKey()); + } + + /// For each input file discovered, check whether it's external path is in a + /// stable directory. Traversal is stopped if the current module is not + /// considered stable. + bool visitInputFile(StringRef FilenameAsRequested, StringRef Filename, + bool isSystem, bool isOverridden, + bool isExplicitModule) override { + if (StableDirs.empty()) + return false; + auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile); + if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end()) || + (!PrebuiltEntryIt->second.isInStableDir())) + return false; + + PrebuiltEntryIt->second.setInStableDir( + isPathInStableDir(StableDirs, Filename)); + return PrebuiltEntryIt->second.isInStableDir(); + } + + /// Update which module that is being actively traversed. + void visitModuleFile(StringRef Filename, + serialization::ModuleKind Kind) override { + // If the CurrentFile is not + // considered stable, update any of it's transitive dependents. + auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile); + if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end()) && + !PrebuiltEntryIt->second.isInStableDir()) + PrebuiltEntryIt->second.updateDependentsNotInStableDirs( + PrebuiltModulesASTMap); + CurrentFile = Filename; + } + + /// Check the header search options for a given module when considering + /// if the module comes from stable directories. + bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + StringRef ModuleFilename, + StringRef SpecificModuleCachePath, + bool Complain) override { + + auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile); + PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second; + if (PrebuiltMapEntry.second) + PrebuiltModule.setInStableDir(!StableDirs.empty()); + + if (PrebuiltModule.isInStableDir()) + PrebuiltModule.setInStableDir(areOptionsInStableDir(StableDirs, HSOpts)); + + return false; + } + + /// Accumulate vfsoverlays used to build these prebuilt modules. + bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts, + bool Complain) override { + + auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile); + PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second; + if (PrebuiltMapEntry.second) + PrebuiltModule.setInStableDir(!StableDirs.empty()); + + PrebuiltModule.setVFS( + llvm::StringSet<>(llvm::from_range, HSOpts.VFSOverlayFiles)); + + return checkHeaderSearchPaths(HSOpts, CI.getHeaderSearchOpts(), + Complain ? &Diags : nullptr, + CI.getLangOpts()); + } + + bool readModuleCacheKey(StringRef ModuleName, StringRef Filename, + StringRef CacheKey) override { + CI.getFrontendOpts().ModuleCacheKeys.emplace_back(std::string(Filename), + std::string(CacheKey)); + // FIXME: add name/path of the importing module? + return CI.addCachedModuleFile(Filename, CacheKey, "imported module"); + } + +private: + CompilerInstance &CI; + PrebuiltModuleFilesT &PrebuiltModuleFiles; + llvm::SmallVector &NewModuleFiles; + PrebuiltModulesAttrsMap &PrebuiltModulesASTMap; + DiagnosticsEngine &Diags; + std::string CurrentFile; + const ArrayRef StableDirs; +}; + +/// Visit the given prebuilt module and collect all of the modules it +/// transitively imports and contributing input files. +static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename, + CompilerInstance &CI, + PrebuiltModuleFilesT &ModuleFiles, + PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, + DiagnosticsEngine &Diags, + const ArrayRef StableDirs) { + // List of module files to be processed. + llvm::SmallVector Worklist; + PrebuiltModuleListener Listener(CI, ModuleFiles, Worklist, + PrebuiltModulesASTMap, Diags, StableDirs); + + Listener.visitModuleFile(PrebuiltModuleFilename, + serialization::MK_ExplicitModule); + if (ASTReader::readASTFileControlBlock( + PrebuiltModuleFilename, CI.getFileManager(), CI.getModuleCache(), + CI.getPCHContainerReader(), + /*FindModuleFileExtensions=*/false, Listener, + /*ValidateDiagnosticOptions=*/false, ASTReader::ARR_OutOfDate)) + return true; + + while (!Worklist.empty()) { + Listener.visitModuleFile(Worklist.back(), serialization::MK_ExplicitModule); + if (ASTReader::readASTFileControlBlock( + Worklist.pop_back_val(), CI.getFileManager(), CI.getModuleCache(), + CI.getPCHContainerReader(), + /*FindModuleFileExtensions=*/false, Listener, + /*ValidateDiagnosticOptions=*/false)) + return true; + } + return false; +} + +/// Transform arbitrary file name into an object-like file name. +static std::string makeObjFileName(StringRef FileName) { + SmallString<128> ObjFileName(FileName); + llvm::sys::path::replace_extension(ObjFileName, "o"); + return std::string(ObjFileName); +} + +/// Deduce the dependency target based on the output file and input files. +static std::string +deduceDepTarget(const std::string &OutputFile, + const SmallVectorImpl &InputFiles) { + if (OutputFile != "-") + return OutputFile; + + if (InputFiles.empty() || !InputFiles.front().isFile()) + return "clang-scan-deps\\ dependency"; + + return makeObjFileName(InputFiles.front().getFile()); +} + +// Clang implements -D and -U by splatting text into a predefines buffer. This +// allows constructs such as `-DFඞ=3 "-D F\u{0D9E} 4 3 2”` to be accepted and +// define the same macro, or adding C++ style comments before the macro name. +// +// This function checks that the first non-space characters in the macro +// obviously form an identifier that can be uniqued on without lexing. Failing +// to do this could lead to changing the final definition of a macro. +// +// We could set up a preprocessor and actually lex the name, but that's very +// heavyweight for a situation that will almost never happen in practice. +static std::optional getSimpleMacroName(StringRef Macro) { + StringRef Name = Macro.split("=").first.ltrim(" \t"); + std::size_t I = 0; + + auto FinishName = [&]() -> std::optional { + StringRef SimpleName = Name.slice(0, I); + if (SimpleName.empty()) + return std::nullopt; + return SimpleName; + }; + + for (; I != Name.size(); ++I) { + switch (Name[I]) { + case '(': // Start of macro parameter list + case ' ': // End of macro name + case '\t': + return FinishName(); + case '_': + continue; + default: + if (llvm::isAlnum(Name[I])) + continue; + return std::nullopt; + } + } + return FinishName(); +} + +static void canonicalizeDefines(PreprocessorOptions &PPOpts) { + using MacroOpt = std::pair; + std::vector SimpleNames; + SimpleNames.reserve(PPOpts.Macros.size()); + std::size_t Index = 0; + for (const auto &M : PPOpts.Macros) { + auto SName = getSimpleMacroName(M.first); + // Skip optimizing if we can't guarantee we can preserve relative order. + if (!SName) + return; + SimpleNames.emplace_back(*SName, Index); + ++Index; + } + + llvm::stable_sort(SimpleNames, llvm::less_first()); + // Keep the last instance of each macro name by going in reverse + auto NewEnd = std::unique( + SimpleNames.rbegin(), SimpleNames.rend(), + [](const MacroOpt &A, const MacroOpt &B) { return A.first == B.first; }); + SimpleNames.erase(SimpleNames.begin(), NewEnd.base()); + + // Apply permutation. + decltype(PPOpts.Macros) NewMacros; + NewMacros.reserve(SimpleNames.size()); + for (std::size_t I = 0, E = SimpleNames.size(); I != E; ++I) { + std::size_t OriginalIndex = SimpleNames[I].second; + // We still emit undefines here as they may be undefining a predefined macro + NewMacros.push_back(std::move(PPOpts.Macros[OriginalIndex])); + } + std::swap(PPOpts.Macros, NewMacros); +} + +/// Builds a dependency file after reversing prefix mappings. This allows +/// emitting a .d file that has real paths where they would otherwise be +/// canonicalized. +class ReversePrefixMappingDependencyFileGenerator + : public DependencyFileGenerator { + llvm::PrefixMapper ReverseMapper; + +public: + ReversePrefixMappingDependencyFileGenerator( + const DependencyOutputOptions &Opts) + : DependencyFileGenerator(Opts) {} + + void initialize(const CompilerInvocation &CI) { + llvm::PrefixMapper Mapper; + DepscanPrefixMapping::configurePrefixMapper(CI, Mapper); + if (Mapper.empty()) + return; + + ReverseMapper.addInverseRange(Mapper.getMappings()); + ReverseMapper.sort(); + } + + void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, + bool IsModuleFile, bool IsMissing) override { + if (ReverseMapper.empty()) + return DependencyFileGenerator::maybeAddDependency( + Filename, FromModule, IsSystem, IsModuleFile, IsMissing); + + // We may get canonicalized paths if prefix headers/PCH are used, so make + // sure to remap them back to original source paths. + SmallString<256> New{Filename}; + ReverseMapper.mapInPlace(New); + return DependencyFileGenerator::maybeAddDependency( + New, FromModule, IsSystem, IsModuleFile, IsMissing); + } +}; + +/// See \c WrapScanModuleBuildAction. +class WrapScanModuleBuildConsumer : public ASTConsumer { +public: + WrapScanModuleBuildConsumer(CompilerInstance &CI, + DependencyActionController &Controller) + : CI(CI), Controller(Controller) {} + + void HandleTranslationUnit(ASTContext &Ctx) override { + if (auto E = Controller.finalizeModuleBuild(CI)) + Ctx.getDiagnostics().Report(diag::err_cas_depscan_failed) << std::move(E); + } + +private: + CompilerInstance &CI; + DependencyActionController &Controller; +}; + +/// A wrapper for implicit module build actions in the scanner. +class WrapScanModuleBuildAction : public WrapperFrontendAction { +public: + WrapScanModuleBuildAction(std::unique_ptr WrappedAction, + DependencyActionController &Controller) + : WrapperFrontendAction(std::move(WrappedAction)), + Controller(Controller) {} + +private: + bool BeginInvocation(CompilerInstance &CI) override { + if (auto E = Controller.initializeModuleBuild(CI)) { + CI.getDiagnostics().Report(diag::err_cas_depscan_failed) << std::move(E); + return false; + } + return WrapperFrontendAction::BeginInvocation(CI); + } + + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { + auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); + if (!OtherConsumer) + return nullptr; + Module *M = CI.getPreprocessor().getCurrentModule(); + assert(M && "WrapScanModuleBuildAction should only be used with module"); + if (!M) + return OtherConsumer; + auto Consumer = + std::make_unique(CI, Controller); + std::vector> Consumers; + Consumers.push_back(std::move(Consumer)); + Consumers.push_back(std::move(OtherConsumer)); + return std::make_unique(std::move(Consumers)); + } + +private: + DependencyActionController &Controller; +}; + +class ScanningDependencyDirectivesGetter : public DependencyDirectivesGetter { + DependencyScanningWorkerFilesystem *DepFS; + +public: + ScanningDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(nullptr) { + FileMgr.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) { + auto *DFS = llvm::dyn_cast(&FS); + if (DFS) { + assert(!DepFS && "Found multiple scanning VFSs"); + DepFS = DFS; + } + }); + assert(DepFS && "Did not find scanning VFS"); + } + + std::unique_ptr + cloneFor(FileManager &FileMgr) override { + return std::make_unique(FileMgr); + } + + std::optional> + operator()(FileEntryRef File) override { + return DepFS->getDirectiveTokens(File.getName()); + } +}; + +// FIXME: Make this thread-safe by pulling the FS out of `FileManager`. +class CASDependencyDirectivesGetter : public DependencyDirectivesGetter { + DependencyScanningCASFilesystem *DepCASFS; + +public: + CASDependencyDirectivesGetter(DependencyScanningCASFilesystem *DepCASFS) + : DepCASFS(DepCASFS) {} + + std::unique_ptr + cloneFor(FileManager &FileMgr) override { + (void)FileMgr; + return std::make_unique(DepCASFS); + } + + std::optional> + operator()(FileEntryRef File) override { + return DepCASFS->getDirectiveTokens(File.getName()); + } +}; +} // namespace + +/// Sanitize diagnostic options for dependency scan. +void clang::tooling::dependencies::sanitizeDiagOpts( + DiagnosticOptions &DiagOpts) { + // Don't print 'X warnings and Y errors generated'. + DiagOpts.ShowCarets = false; + // Don't write out diagnostic file. + DiagOpts.DiagnosticSerializationFile.clear(); + // Don't emit warnings except for scanning specific warnings. + // TODO: It would be useful to add a more principled way to ignore all + // warnings that come from source code. The issue is that we need to + // ignore warnings that could be surpressed by + // `#pragma clang diagnostic`, while still allowing some scanning + // warnings for things we're not ready to turn into errors yet. + // See `test/ClangScanDeps/diagnostic-pragmas.c` for an example. + llvm::erase_if(DiagOpts.Warnings, [](StringRef Warning) { + return llvm::StringSwitch(Warning) + .Cases("pch-vfs-diff", "error=pch-vfs-diff", false) + .StartsWith("no-error=", false) + .Default(true); + }); +} + +bool DependencyScanningAction::runInvocation( + std::shared_ptr Invocation, + IntrusiveRefCntPtr FS, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagConsumer) { + // Making sure that we canonicalize the defines before we create the deep + // copy to avoid unnecessary variants in the scanner and in the resulting + // explicit command lines. + if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros)) + canonicalizeDefines(Invocation->getPreprocessorOpts()); + + // Make a deep copy of the original Clang invocation. + CompilerInvocation OriginalInvocation(*Invocation); + + if (Scanned) { + CompilerInstance &ScanInstance = *ScanInstanceStorage; + auto reportError = [&ScanInstance](Error &&E) -> bool { + ScanInstance.getDiagnostics().Report(diag::err_cas_depscan_failed) + << std::move(E); + return false; + }; + + // Scanning runs once for the first -cc1 invocation in a chain of driver + // jobs. For any dependent jobs, reuse the scanning result and just + // update the LastCC1Arguments to correspond to the new invocation. + // FIXME: to support multi-arch builds, each arch requires a separate scan + if (MDC) + MDC->applyDiscoveredDependencies(OriginalInvocation); + + if (Error E = Controller.finalize(ScanInstance, OriginalInvocation)) + return reportError(std::move(E)); + + LastCC1Arguments = OriginalInvocation.getCC1CommandLine(); + LastCC1CacheKey = Controller.getCacheKey(OriginalInvocation); + return true; + } + + Scanned = true; + + // Create a compiler instance to handle the actual work. + auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries()); + ScanInstanceStorage.emplace(std::move(Invocation), std::move(PCHContainerOps), + ModCache.get()); + CompilerInstance &ScanInstance = *ScanInstanceStorage; + ScanInstance.getInvocation().getCASOpts() = CASOpts; + ScanInstance.setBuildingModule(false); + + ScanInstance.createVirtualFileSystem(FS, DiagConsumer); + + // Create the compiler's actual diagnostics engine. + if (!DiagGenerationAsCompilation) + sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); + assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); + ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); + if (!ScanInstance.hasDiagnostics()) + return false; + if (VerboseOS) + ScanInstance.setVerboseOutputStream(*VerboseOS); + + ScanInstance.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath = + true; + + if (ScanInstance.getHeaderSearchOpts().ModulesValidateOncePerBuildSession) + ScanInstance.getHeaderSearchOpts().BuildSessionTimestamp = + Service.getBuildSessionTimestamp(); + + ScanInstance.getFrontendOpts().DisableFree = false; + ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false; + ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false; + // This will prevent us compiling individual modules asynchronously since + // FileManager is not thread-safe, but it does improve performance for now. + ScanInstance.getFrontendOpts().ModulesShareFileManager = true; + if (DepCASFS) + ScanInstance.getFrontendOpts().ModulesShareFileManager = false; + ScanInstance.getHeaderSearchOpts().ModuleFormat = "raw"; + ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage = + any(Service.getOptimizeArgs() & ScanningOptimizations::VFS); + + // Create a new FileManager to match the invocation's FileSystemOptions. + auto *FileMgr = ScanInstance.createFileManager(); + + // Use the dependency scanning optimized file system if requested to do so. + if (DepFS) { + DepFS->resetBypassedPathPrefix(); + if (!ScanInstance.getHeaderSearchOpts().ModuleCachePath.empty()) { + SmallString<256> ModulesCachePath; + normalizeModuleCachePath( + *FileMgr, ScanInstance.getHeaderSearchOpts().ModuleCachePath, + ModulesCachePath); + DepFS->setBypassedPathPrefix(ModulesCachePath); + } + + ScanInstance.setDependencyDirectivesGetter( + std::make_unique(*FileMgr)); + } + + // CAS Implementation. + if (DepCASFS) + ScanInstance.setDependencyDirectivesGetter( + std::make_unique(DepCASFS.get())); + + ScanInstance.createSourceManager(*FileMgr); + + // Create a collection of stable directories derived from the ScanInstance + // for determining whether module dependencies would fully resolve from + // those directories. + llvm::SmallVector StableDirs; + const StringRef Sysroot = ScanInstance.getHeaderSearchOpts().Sysroot; + if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot)) + StableDirs = {Sysroot, ScanInstance.getHeaderSearchOpts().ResourceDir}; + + // Store a mapping of prebuilt module files and their properties like header + // search options. This will prevent the implicit build to create duplicate + // modules and will force reuse of the existing prebuilt module files + // instead. + PrebuiltModulesAttrsMap PrebuiltModulesASTMap; + + if (!ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty()) + if (visitPrebuiltModule( + ScanInstance.getPreprocessorOpts().ImplicitPCHInclude, ScanInstance, + ScanInstance.getHeaderSearchOpts().PrebuiltModuleFiles, + PrebuiltModulesASTMap, ScanInstance.getDiagnostics(), StableDirs)) + return false; + + // Create the dependency collector that will collect the produced + // dependencies. + // + // This also moves the existing dependency output options from the + // invocation to the collector. The options in the invocation are reset, + // which ensures that the compiler won't create new dependency collectors, + // and thus won't write out the extra '.d' files to disk. + auto Opts = std::make_unique(); + std::swap(*Opts, ScanInstance.getInvocation().getDependencyOutputOpts()); + // We need at least one -MT equivalent for the generator of make dependency + // files to work. + if (Opts->Targets.empty()) + Opts->Targets = {deduceDepTarget(ScanInstance.getFrontendOpts().OutputFile, + ScanInstance.getFrontendOpts().Inputs)}; + if (Service.getFormat() == ScanningOutputFormat::Make) { + // Only 'Make' scanning needs to force this because that mode depends on + // getting the dependencies directly from \p DependencyFileGenerator. + Opts->IncludeSystemHeaders = true; + } + + auto reportError = [&ScanInstance](Error &&E) -> bool { + ScanInstance.getDiagnostics().Report(diag::err_cas_depscan_failed) + << std::move(E); + return false; + }; + + // FIXME: The caller APIs in \p DependencyScanningTool expect a specific + // DependencyCollector to get attached to the preprocessor in order to + // function properly (e.g. \p FullDependencyConsumer needs \p + // ModuleDepCollector) but this association is very indirect via the value + // of the \p ScanningOutputFormat. We should remove \p Format field from + // \p DependencyScanningAction, and have the callers pass in a + // “DependencyCollector factory” so the connection of collector<->consumer + // is explicit in each \p DependencyScanningTool function. + switch (Service.getFormat()) { + case ScanningOutputFormat::Make: + case ScanningOutputFormat::Tree: + ScanInstance.addDependencyCollector( + std::make_shared( + std::move(Opts), WorkingDirectory, Consumer, EmitDependencyFile)); + break; + case ScanningOutputFormat::IncludeTree: + case ScanningOutputFormat::P1689: + case ScanningOutputFormat::Full: + case ScanningOutputFormat::FullTree: + case ScanningOutputFormat::FullIncludeTree: + if (EmitDependencyFile) { + auto DFG = + std::make_shared(*Opts); + DFG->initialize(ScanInstance.getInvocation()); + ScanInstance.addDependencyCollector(std::move(DFG)); + } + + MDC = std::make_shared( + Service, std::move(Opts), ScanInstance, Consumer, Controller, + OriginalInvocation, std::move(PrebuiltModulesASTMap), StableDirs); + ScanInstance.addDependencyCollector(MDC); + ScanInstance.setGenModuleActionWrapper( + [&Controller = Controller](const FrontendOptions &Opts, + std::unique_ptr Wrapped) { + return std::make_unique(std::move(Wrapped), + Controller); + }); + break; + } + + // Consider different header search and diagnostic options to create + // different modules. This avoids the unsound aliasing of module PCMs. + // + // TODO: Implement diagnostic bucketing to reduce the impact of strict + // context hashing. + ScanInstance.getHeaderSearchOpts().ModulesStrictContextHash = true; + ScanInstance.getHeaderSearchOpts().ModulesSerializeOnlyPreprocessor = true; + ScanInstance.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true; + ScanInstance.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true; + ScanInstance.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = true; + ScanInstance.getHeaderSearchOpts().ModulesForceValidateUserHeaders = false; + + // Avoid some checks and module map parsing when loading PCM files. + ScanInstance.getPreprocessorOpts().ModulesCheckRelocated = false; + + std::unique_ptr Action; + + if (Service.getFormat() == ScanningOutputFormat::P1689) + Action = std::make_unique(); + else if (ModuleName) + Action = std::make_unique(*ModuleName); + else + Action = std::make_unique(); + + // Normally this would be handled by GeneratePCHAction + if (ScanInstance.getFrontendOpts().ProgramAction == frontend::GeneratePCH) + ScanInstance.getLangOpts().CompilingPCH = true; + + if (Error E = Controller.initialize(ScanInstance, OriginalInvocation)) + return reportError(std::move(E)); + + if (ScanInstance.getDiagnostics().hasErrorOccurred()) + return false; + + // ExecuteAction is responsible for calling finish. + DiagConsumerFinished = true; + + if (!ScanInstance.ExecuteAction(*Action)) + return false; + + if (MDC) + MDC->applyDiscoveredDependencies(OriginalInvocation); + + if (Error E = Controller.finalize(ScanInstance, OriginalInvocation)) + return reportError(std::move(E)); + + // Forward any CAS results to consumer. + std::string ID = OriginalInvocation.getFileSystemOpts().CASFileSystemRootID; + if (!ID.empty()) + Consumer.handleCASFileSystemRootID(std::move(ID)); + ID = OriginalInvocation.getFrontendOpts().CASIncludeTreeID; + if (!ID.empty()) + Consumer.handleIncludeTreeID(std::move(ID)); + + LastCC1Arguments = OriginalInvocation.getCC1CommandLine(); + LastCC1CacheKey = Controller.getCacheKey(OriginalInvocation); + + return true; +} + +std::vector DependencyScanningAction::takeLastCC1Arguments() { + std::vector Result; + std::swap(Result, LastCC1Arguments); // Reset LastCC1Arguments to empty. + return Result; +} + +std::optional DependencyScanningAction::takeLastCC1CacheKey() { + std::optional Result; + std::swap(Result, LastCC1CacheKey); + return Result; +} + +IntrusiveRefCntPtr +DependencyScanningAction::getDepScanFS() { + if (DepFS) { + assert(!DepCASFS && "CAS DepFS should not be set"); + return DepFS; + } + if (DepCASFS) { + assert(!DepFS && "DepFS should not be set"); + return DepCASFS; + } + return nullptr; +} diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h new file mode 100644 index 0000000000000..3c131f844e380 --- /dev/null +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h @@ -0,0 +1,91 @@ +//===- DependencyScanner.h - Performs module dependency scanning *- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNER_H +#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNER_H + +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Serialization/ObjectFilePCHContainerReader.h" +#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" +#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" + +namespace clang { +class DiagnosticConsumer; + +namespace tooling { +namespace dependencies { +class DependencyScanningService; +class DependencyConsumer; +class DependencyActionController; +class DependencyScanningWorkerFilesystem; + +class DependencyScanningAction { +public: + DependencyScanningAction( + DependencyScanningService &Service, StringRef WorkingDirectory, + DependencyConsumer &Consumer, DependencyActionController &Controller, + llvm::IntrusiveRefCntPtr DepFS, + llvm::IntrusiveRefCntPtr DepCASFS, + llvm::IntrusiveRefCntPtr CacheFS, + bool EmitDependencyFile, bool DiagGenerationAsCompilation, + const CASOptions &CASOpts, + std::optional ModuleName = std::nullopt, + raw_ostream *VerboseOS = nullptr) + : Service(Service), WorkingDirectory(WorkingDirectory), + Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)), + DepCASFS(std::move(DepCASFS)), CacheFS(std::move(CacheFS)), + CASOpts(CASOpts), EmitDependencyFile(EmitDependencyFile), + DiagGenerationAsCompilation(DiagGenerationAsCompilation), + ModuleName(ModuleName), VerboseOS(VerboseOS) {} + bool runInvocation(std::shared_ptr Invocation, + IntrusiveRefCntPtr FS, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagConsumer); + + bool hasScanned() const { return Scanned; } + bool hasDiagConsumerFinished() const { return DiagConsumerFinished; } + + /// Take the cc1 arguments corresponding to the most recent invocation used + /// with this action. Any modifications implied by the discovered dependencies + /// will have already been applied. + std::vector takeLastCC1Arguments(); + + std::optional takeLastCC1CacheKey(); + + IntrusiveRefCntPtr getDepScanFS(); + +private: + DependencyScanningService &Service; + StringRef WorkingDirectory; + DependencyConsumer &Consumer; + DependencyActionController &Controller; + llvm::IntrusiveRefCntPtr DepFS; + llvm::IntrusiveRefCntPtr DepCASFS; + llvm::IntrusiveRefCntPtr CacheFS; + const CASOptions &CASOpts; + bool EmitDependencyFile = false; + bool DiagGenerationAsCompilation; + std::optional ModuleName; + std::optional ScanInstanceStorage; + std::shared_ptr MDC; + std::vector LastCC1Arguments; + std::optional LastCC1CacheKey; + bool Scanned = false; + bool DiagConsumerFinished = false; + raw_ostream *VerboseOS; +}; + +// Helper functions +void sanitizeDiagOpts(DiagnosticOptions &DiagOpts); + +} // namespace dependencies +} // namespace tooling +} // namespace clang + +#endif diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index b7f8b6b9b0f23..eba46e44f20f6 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" -#include "clang/Basic/DiagnosticCAS.h" +#include "DependencyScannerImpl.h" #include "clang/Basic/DiagnosticDriver.h" #include "clang/Basic/DiagnosticFrontend.h" #include "clang/Basic/DiagnosticSerialization.h" @@ -19,7 +19,6 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" -#include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/PreprocessorOptions.h" @@ -27,7 +26,6 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningService.h" #include "clang/Tooling/DependencyScanning/InProcessModuleCache.h" #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" -#include "clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/CAS/CASProvidingFileSystem.h" #include "llvm/CAS/CachingOnDiskFileSystem.h" @@ -44,788 +42,6 @@ using namespace tooling; using namespace dependencies; using llvm::Error; -namespace { - -/// Forwards the gatherered dependencies to the consumer. -class DependencyConsumerForwarder : public DependencyFileGenerator { -public: - DependencyConsumerForwarder(std::unique_ptr Opts, - StringRef WorkingDirectory, DependencyConsumer &C, - bool EmitDependencyFile) - : DependencyFileGenerator(*Opts), WorkingDirectory(WorkingDirectory), - Opts(std::move(Opts)), C(C), EmitDependencyFile(EmitDependencyFile) {} - - void finishedMainFile(DiagnosticsEngine &Diags) override { - C.handleDependencyOutputOpts(*Opts); - llvm::SmallString<256> CanonPath; - for (const auto &File : getDependencies()) { - CanonPath = File; - llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true); - llvm::sys::fs::make_absolute(WorkingDirectory, CanonPath); - C.handleFileDependency(CanonPath); - } - if (EmitDependencyFile) - DependencyFileGenerator::finishedMainFile(Diags); - } - -private: - StringRef WorkingDirectory; - std::unique_ptr Opts; - DependencyConsumer &C; - bool EmitDependencyFile = false; -}; - -static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts, - const HeaderSearchOptions &ExistingHSOpts, - DiagnosticsEngine *Diags, - const LangOptions &LangOpts) { - if (LangOpts.Modules) { - if (HSOpts.VFSOverlayFiles != ExistingHSOpts.VFSOverlayFiles) { - if (Diags) { - Diags->Report(diag::warn_pch_vfsoverlay_mismatch); - auto VFSNote = [&](int Type, ArrayRef VFSOverlays) { - if (VFSOverlays.empty()) { - Diags->Report(diag::note_pch_vfsoverlay_empty) << Type; - } else { - std::string Files = llvm::join(VFSOverlays, "\n"); - Diags->Report(diag::note_pch_vfsoverlay_files) << Type << Files; - } - }; - VFSNote(0, HSOpts.VFSOverlayFiles); - VFSNote(1, ExistingHSOpts.VFSOverlayFiles); - } - } - } - return false; -} - -using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles); - -/// A listener that collects the imported modules and the input -/// files. While visiting, collect vfsoverlays and file inputs that determine -/// whether prebuilt modules fully resolve in stable directories. -class PrebuiltModuleListener : public ASTReaderListener { -public: - PrebuiltModuleListener(CompilerInstance &CI, - PrebuiltModuleFilesT &PrebuiltModuleFiles, - llvm::SmallVector &NewModuleFiles, - PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, - DiagnosticsEngine &Diags, - const ArrayRef StableDirs) - : CI(CI), PrebuiltModuleFiles(PrebuiltModuleFiles), - NewModuleFiles(NewModuleFiles), - PrebuiltModulesASTMap(PrebuiltModulesASTMap), Diags(Diags), - StableDirs(StableDirs) {} - - bool needsImportVisitation() const override { return true; } - bool needsInputFileVisitation() override { return true; } - bool needsSystemInputFileVisitation() override { return true; } - - /// Accumulate the modules are transitively depended on by the initial - /// prebuilt module. - void visitImport(StringRef ModuleName, StringRef Filename) override { - if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second) - NewModuleFiles.push_back(Filename.str()); - - auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(Filename); - PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second; - if (PrebuiltMapEntry.second) - PrebuiltModule.setInStableDir(!StableDirs.empty()); - - if (auto It = PrebuiltModulesASTMap.find(CurrentFile); - It != PrebuiltModulesASTMap.end() && CurrentFile != Filename) - PrebuiltModule.addDependent(It->getKey()); - } - - /// For each input file discovered, check whether it's external path is in a - /// stable directory. Traversal is stopped if the current module is not - /// considered stable. - bool visitInputFile(StringRef FilenameAsRequested, StringRef Filename, - bool isSystem, bool isOverridden, - bool isExplicitModule) override { - if (StableDirs.empty()) - return false; - auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile); - if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end()) || - (!PrebuiltEntryIt->second.isInStableDir())) - return false; - - PrebuiltEntryIt->second.setInStableDir( - isPathInStableDir(StableDirs, Filename)); - return PrebuiltEntryIt->second.isInStableDir(); - } - - /// Update which module that is being actively traversed. - void visitModuleFile(StringRef Filename, - serialization::ModuleKind Kind) override { - // If the CurrentFile is not - // considered stable, update any of it's transitive dependents. - auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile); - if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end()) && - !PrebuiltEntryIt->second.isInStableDir()) - PrebuiltEntryIt->second.updateDependentsNotInStableDirs( - PrebuiltModulesASTMap); - CurrentFile = Filename; - } - - /// Check the header search options for a given module when considering - /// if the module comes from stable directories. - bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef ModuleFilename, - StringRef SpecificModuleCachePath, - bool Complain) override { - - auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile); - PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second; - if (PrebuiltMapEntry.second) - PrebuiltModule.setInStableDir(!StableDirs.empty()); - - if (PrebuiltModule.isInStableDir()) - PrebuiltModule.setInStableDir(areOptionsInStableDir(StableDirs, HSOpts)); - - return false; - } - - /// Accumulate vfsoverlays used to build these prebuilt modules. - bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts, - bool Complain) override { - - auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile); - PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second; - if (PrebuiltMapEntry.second) - PrebuiltModule.setInStableDir(!StableDirs.empty()); - - PrebuiltModule.setVFS( - llvm::StringSet<>(llvm::from_range, HSOpts.VFSOverlayFiles)); - - return checkHeaderSearchPaths( - HSOpts, CI.getHeaderSearchOpts(), Complain ? &Diags : nullptr, CI.getLangOpts()); - } - - bool readModuleCacheKey(StringRef ModuleName, StringRef Filename, - StringRef CacheKey) override { - CI.getFrontendOpts().ModuleCacheKeys.emplace_back(std::string(Filename), - std::string(CacheKey)); - // FIXME: add name/path of the importing module? - return CI.addCachedModuleFile(Filename, CacheKey, "imported module"); - } - -private: - CompilerInstance &CI; - PrebuiltModuleFilesT &PrebuiltModuleFiles; - llvm::SmallVector &NewModuleFiles; - PrebuiltModulesAttrsMap &PrebuiltModulesASTMap; - DiagnosticsEngine &Diags; - std::string CurrentFile; - const ArrayRef StableDirs; -}; - -/// Visit the given prebuilt module and collect all of the modules it -/// transitively imports and contributing input files. -static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename, - CompilerInstance &CI, - PrebuiltModuleFilesT &ModuleFiles, - PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, - DiagnosticsEngine &Diags, - const ArrayRef StableDirs) { - // List of module files to be processed. - llvm::SmallVector Worklist; - PrebuiltModuleListener Listener(CI, ModuleFiles, Worklist, - PrebuiltModulesASTMap, Diags, StableDirs); - - Listener.visitModuleFile(PrebuiltModuleFilename, - serialization::MK_ExplicitModule); - if (ASTReader::readASTFileControlBlock( - PrebuiltModuleFilename, CI.getFileManager(), CI.getModuleCache(), - CI.getPCHContainerReader(), - /*FindModuleFileExtensions=*/false, Listener, - /*ValidateDiagnosticOptions=*/false, ASTReader::ARR_OutOfDate)) - return true; - - while (!Worklist.empty()) { - Listener.visitModuleFile(Worklist.back(), serialization::MK_ExplicitModule); - if (ASTReader::readASTFileControlBlock( - Worklist.pop_back_val(), CI.getFileManager(), CI.getModuleCache(), - CI.getPCHContainerReader(), - /*FindModuleFileExtensions=*/false, Listener, - /*ValidateDiagnosticOptions=*/false)) - return true; - } - return false; -} - -/// Transform arbitrary file name into an object-like file name. -static std::string makeObjFileName(StringRef FileName) { - SmallString<128> ObjFileName(FileName); - llvm::sys::path::replace_extension(ObjFileName, "o"); - return std::string(ObjFileName); -} - -/// Deduce the dependency target based on the output file and input files. -static std::string -deduceDepTarget(const std::string &OutputFile, - const SmallVectorImpl &InputFiles) { - if (OutputFile != "-") - return OutputFile; - - if (InputFiles.empty() || !InputFiles.front().isFile()) - return "clang-scan-deps\\ dependency"; - - return makeObjFileName(InputFiles.front().getFile()); -} - -/// Sanitize diagnostic options for dependency scan. -static void sanitizeDiagOpts(DiagnosticOptions &DiagOpts) { - // Don't print 'X warnings and Y errors generated'. - DiagOpts.ShowCarets = false; - // Don't write out diagnostic file. - DiagOpts.DiagnosticSerializationFile.clear(); - // Don't emit warnings except for scanning specific warnings. - // TODO: It would be useful to add a more principled way to ignore all - // warnings that come from source code. The issue is that we need to - // ignore warnings that could be surpressed by - // `#pragma clang diagnostic`, while still allowing some scanning - // warnings for things we're not ready to turn into errors yet. - // See `test/ClangScanDeps/diagnostic-pragmas.c` for an example. - llvm::erase_if(DiagOpts.Warnings, [](StringRef Warning) { - return llvm::StringSwitch(Warning) - .Cases("pch-vfs-diff", "error=pch-vfs-diff", false) - .StartsWith("no-error=", false) - .Default(true); - }); -} - -// Clang implements -D and -U by splatting text into a predefines buffer. This -// allows constructs such as `-DFඞ=3 "-D F\u{0D9E} 4 3 2”` to be accepted and -// define the same macro, or adding C++ style comments before the macro name. -// -// This function checks that the first non-space characters in the macro -// obviously form an identifier that can be uniqued on without lexing. Failing -// to do this could lead to changing the final definition of a macro. -// -// We could set up a preprocessor and actually lex the name, but that's very -// heavyweight for a situation that will almost never happen in practice. -static std::optional getSimpleMacroName(StringRef Macro) { - StringRef Name = Macro.split("=").first.ltrim(" \t"); - std::size_t I = 0; - - auto FinishName = [&]() -> std::optional { - StringRef SimpleName = Name.slice(0, I); - if (SimpleName.empty()) - return std::nullopt; - return SimpleName; - }; - - for (; I != Name.size(); ++I) { - switch (Name[I]) { - case '(': // Start of macro parameter list - case ' ': // End of macro name - case '\t': - return FinishName(); - case '_': - continue; - default: - if (llvm::isAlnum(Name[I])) - continue; - return std::nullopt; - } - } - return FinishName(); -} - -static void canonicalizeDefines(PreprocessorOptions &PPOpts) { - using MacroOpt = std::pair; - std::vector SimpleNames; - SimpleNames.reserve(PPOpts.Macros.size()); - std::size_t Index = 0; - for (const auto &M : PPOpts.Macros) { - auto SName = getSimpleMacroName(M.first); - // Skip optimizing if we can't guarantee we can preserve relative order. - if (!SName) - return; - SimpleNames.emplace_back(*SName, Index); - ++Index; - } - - llvm::stable_sort(SimpleNames, llvm::less_first()); - // Keep the last instance of each macro name by going in reverse - auto NewEnd = std::unique( - SimpleNames.rbegin(), SimpleNames.rend(), - [](const MacroOpt &A, const MacroOpt &B) { return A.first == B.first; }); - SimpleNames.erase(SimpleNames.begin(), NewEnd.base()); - - // Apply permutation. - decltype(PPOpts.Macros) NewMacros; - NewMacros.reserve(SimpleNames.size()); - for (std::size_t I = 0, E = SimpleNames.size(); I != E; ++I) { - std::size_t OriginalIndex = SimpleNames[I].second; - // We still emit undefines here as they may be undefining a predefined macro - NewMacros.push_back(std::move(PPOpts.Macros[OriginalIndex])); - } - std::swap(PPOpts.Macros, NewMacros); -} - -/// Builds a dependency file after reversing prefix mappings. This allows -/// emitting a .d file that has real paths where they would otherwise be -/// canonicalized. -class ReversePrefixMappingDependencyFileGenerator - : public DependencyFileGenerator { - llvm::PrefixMapper ReverseMapper; - -public: - ReversePrefixMappingDependencyFileGenerator( - const DependencyOutputOptions &Opts) - : DependencyFileGenerator(Opts) {} - - void initialize(const CompilerInvocation &CI) { - llvm::PrefixMapper Mapper; - DepscanPrefixMapping::configurePrefixMapper(CI, Mapper); - if (Mapper.empty()) - return; - - ReverseMapper.addInverseRange(Mapper.getMappings()); - ReverseMapper.sort(); - } - - void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, - bool IsModuleFile, bool IsMissing) override { - if (ReverseMapper.empty()) - return DependencyFileGenerator::maybeAddDependency( - Filename, FromModule, IsSystem, IsModuleFile, IsMissing); - - // We may get canonicalized paths if prefix headers/PCH are used, so make - // sure to remap them back to original source paths. - SmallString<256> New{Filename}; - ReverseMapper.mapInPlace(New); - return DependencyFileGenerator::maybeAddDependency( - New, FromModule, IsSystem, IsModuleFile, IsMissing); - } -}; - -/// See \c WrapScanModuleBuildAction. -class WrapScanModuleBuildConsumer : public ASTConsumer { -public: - WrapScanModuleBuildConsumer(CompilerInstance &CI, - DependencyActionController &Controller) - : CI(CI), Controller(Controller) {} - - void HandleTranslationUnit(ASTContext &Ctx) override { - if (auto E = Controller.finalizeModuleBuild(CI)) - Ctx.getDiagnostics().Report(diag::err_cas_depscan_failed) << std::move(E); - } - -private: - CompilerInstance &CI; - DependencyActionController &Controller; -}; - -/// A wrapper for implicit module build actions in the scanner. -class WrapScanModuleBuildAction : public WrapperFrontendAction { -public: - WrapScanModuleBuildAction(std::unique_ptr WrappedAction, - DependencyActionController &Controller) - : WrapperFrontendAction(std::move(WrappedAction)), - Controller(Controller) {} - -private: - bool BeginInvocation(CompilerInstance &CI) override { - if (auto E = Controller.initializeModuleBuild(CI)) { - CI.getDiagnostics().Report(diag::err_cas_depscan_failed) << std::move(E); - return false; - } - return WrapperFrontendAction::BeginInvocation(CI); - } - - std::unique_ptr CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override { - auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); - if (!OtherConsumer) - return nullptr; - Module *M = CI.getPreprocessor().getCurrentModule(); - assert(M && "WrapScanModuleBuildAction should only be used with module"); - if (!M) - return OtherConsumer; - auto Consumer = - std::make_unique(CI, Controller); - std::vector> Consumers; - Consumers.push_back(std::move(Consumer)); - Consumers.push_back(std::move(OtherConsumer)); - return std::make_unique(std::move(Consumers)); - } - -private: - DependencyActionController &Controller; -}; - -class ScanningDependencyDirectivesGetter : public DependencyDirectivesGetter { - DependencyScanningWorkerFilesystem *DepFS; - -public: - ScanningDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(nullptr) { - FileMgr.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) { - auto *DFS = llvm::dyn_cast(&FS); - if (DFS) { - assert(!DepFS && "Found multiple scanning VFSs"); - DepFS = DFS; - } - }); - assert(DepFS && "Did not find scanning VFS"); - } - - std::unique_ptr - cloneFor(FileManager &FileMgr) override { - return std::make_unique(FileMgr); - } - - std::optional> - operator()(FileEntryRef File) override { - return DepFS->getDirectiveTokens(File.getName()); - } -}; - -// FIXME: Make this thread-safe by pulling the FS out of `FileManager`. -class CASDependencyDirectivesGetter : public DependencyDirectivesGetter { - DependencyScanningCASFilesystem *DepCASFS; - -public: - CASDependencyDirectivesGetter(DependencyScanningCASFilesystem *DepCASFS) - : DepCASFS(DepCASFS) {} - - std::unique_ptr - cloneFor(FileManager &FileMgr) override { - (void)FileMgr; - return std::make_unique(DepCASFS); - } - - std::optional> - operator()(FileEntryRef File) override { - return DepCASFS->getDirectiveTokens(File.getName()); - } -}; - -/// A clang tool that runs the preprocessor in a mode that's optimized for -/// dependency scanning for the given compiler invocation. -class DependencyScanningAction { -public: - DependencyScanningAction( - DependencyScanningService &Service, StringRef WorkingDirectory, - DependencyConsumer &Consumer, DependencyActionController &Controller, - llvm::IntrusiveRefCntPtr DepFS, - llvm::IntrusiveRefCntPtr DepCASFS, - llvm::IntrusiveRefCntPtr CacheFS, - bool EmitDependencyFile, bool DiagGenerationAsCompilation, - const CASOptions &CASOpts, - std::optional ModuleName = std::nullopt, - raw_ostream *VerboseOS = nullptr) - : Service(Service), WorkingDirectory(WorkingDirectory), - Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)), - DepCASFS(std::move(DepCASFS)), CacheFS(std::move(CacheFS)), - CASOpts(CASOpts), EmitDependencyFile(EmitDependencyFile), - DiagGenerationAsCompilation(DiagGenerationAsCompilation), - ModuleName(ModuleName), VerboseOS(VerboseOS) {} - - bool runInvocation(std::shared_ptr Invocation, - IntrusiveRefCntPtr FS, - std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagConsumer) { - // Make a deep copy of the original Clang invocation. - CompilerInvocation OriginalInvocation(*Invocation); - if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros)) - canonicalizeDefines(OriginalInvocation.getPreprocessorOpts()); - - if (Scanned) { - CompilerInstance &ScanInstance = *ScanInstanceStorage; - auto reportError = [&ScanInstance](Error &&E) -> bool { - ScanInstance.getDiagnostics().Report(diag::err_cas_depscan_failed) - << std::move(E); - return false; - }; - - // Scanning runs once for the first -cc1 invocation in a chain of driver - // jobs. For any dependent jobs, reuse the scanning result and just - // update the LastCC1Arguments to correspond to the new invocation. - // FIXME: to support multi-arch builds, each arch requires a separate scan - if (MDC) - MDC->applyDiscoveredDependencies(OriginalInvocation); - - if (Error E = Controller.finalize(ScanInstance, OriginalInvocation)) - return reportError(std::move(E)); - - LastCC1Arguments = OriginalInvocation.getCC1CommandLine(); - LastCC1CacheKey = Controller.getCacheKey(OriginalInvocation); - return true; - } - - Scanned = true; - - // Create a compiler instance to handle the actual work. - auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries()); - ScanInstanceStorage.emplace(std::move(Invocation), - std::move(PCHContainerOps), ModCache.get()); - CompilerInstance &ScanInstance = *ScanInstanceStorage; - ScanInstance.getInvocation().getCASOpts() = CASOpts; - ScanInstance.setBuildingModule(false); - - ScanInstance.createVirtualFileSystem(FS, DiagConsumer); - - // Create the compiler's actual diagnostics engine. - if (!DiagGenerationAsCompilation) - sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); - assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); - ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); - if (!ScanInstance.hasDiagnostics()) - return false; - if (VerboseOS) - ScanInstance.setVerboseOutputStream(*VerboseOS); - - ScanInstance.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath = - true; - - if (ScanInstance.getHeaderSearchOpts().ModulesValidateOncePerBuildSession) - ScanInstance.getHeaderSearchOpts().BuildSessionTimestamp = - Service.getBuildSessionTimestamp(); - - ScanInstance.getFrontendOpts().DisableFree = false; - ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false; - ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false; - // This will prevent us compiling individual modules asynchronously since - // FileManager is not thread-safe, but it does improve performance for now. - ScanInstance.getFrontendOpts().ModulesShareFileManager = true; - if (DepCASFS) - ScanInstance.getFrontendOpts().ModulesShareFileManager = false; - ScanInstance.getHeaderSearchOpts().ModuleFormat = "raw"; - ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage = - any(Service.getOptimizeArgs() & ScanningOptimizations::VFS); - - // Create a new FileManager to match the invocation's FileSystemOptions. - auto *FileMgr = ScanInstance.createFileManager(); - - // Use the dependency scanning optimized file system if requested to do so. - if (DepFS) { - DepFS->resetBypassedPathPrefix(); - if (!ScanInstance.getHeaderSearchOpts().ModuleCachePath.empty()) { - SmallString<256> ModulesCachePath; - normalizeModuleCachePath( - *FileMgr, ScanInstance.getHeaderSearchOpts().ModuleCachePath, - ModulesCachePath); - DepFS->setBypassedPathPrefix(ModulesCachePath); - } - - ScanInstance.setDependencyDirectivesGetter( - std::make_unique(*FileMgr)); - } - - // CAS Implementation. - if (DepCASFS) - ScanInstance.setDependencyDirectivesGetter( - std::make_unique(DepCASFS.get())); - - ScanInstance.createSourceManager(*FileMgr); - - // Create a collection of stable directories derived from the ScanInstance - // for determining whether module dependencies would fully resolve from - // those directories. - llvm::SmallVector StableDirs; - const StringRef Sysroot = ScanInstance.getHeaderSearchOpts().Sysroot; - if (!Sysroot.empty() && - (llvm::sys::path::root_directory(Sysroot) != Sysroot)) - StableDirs = {Sysroot, ScanInstance.getHeaderSearchOpts().ResourceDir}; - - // Store a mapping of prebuilt module files and their properties like header - // search options. This will prevent the implicit build to create duplicate - // modules and will force reuse of the existing prebuilt module files - // instead. - PrebuiltModulesAttrsMap PrebuiltModulesASTMap; - - if (!ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty()) - if (visitPrebuiltModule( - ScanInstance.getPreprocessorOpts().ImplicitPCHInclude, - ScanInstance, - ScanInstance.getHeaderSearchOpts().PrebuiltModuleFiles, - PrebuiltModulesASTMap, ScanInstance.getDiagnostics(), StableDirs)) - return false; - - // Create the dependency collector that will collect the produced - // dependencies. - // - // This also moves the existing dependency output options from the - // invocation to the collector. The options in the invocation are reset, - // which ensures that the compiler won't create new dependency collectors, - // and thus won't write out the extra '.d' files to disk. - auto Opts = std::make_unique(); - std::swap(*Opts, ScanInstance.getInvocation().getDependencyOutputOpts()); - // We need at least one -MT equivalent for the generator of make dependency - // files to work. - if (Opts->Targets.empty()) - Opts->Targets = { - deduceDepTarget(ScanInstance.getFrontendOpts().OutputFile, - ScanInstance.getFrontendOpts().Inputs)}; - if (Service.getFormat() == ScanningOutputFormat::Make) { - // Only 'Make' scanning needs to force this because that mode depends on - // getting the dependencies directly from \p DependencyFileGenerator. - Opts->IncludeSystemHeaders = true; - } - - auto reportError = [&ScanInstance](Error &&E) -> bool { - ScanInstance.getDiagnostics().Report(diag::err_cas_depscan_failed) - << std::move(E); - return false; - }; - - // FIXME: The caller APIs in \p DependencyScanningTool expect a specific - // DependencyCollector to get attached to the preprocessor in order to - // function properly (e.g. \p FullDependencyConsumer needs \p - // ModuleDepCollector) but this association is very indirect via the value - // of the \p ScanningOutputFormat. We should remove \p Format field from - // \p DependencyScanningAction, and have the callers pass in a - // “DependencyCollector factory” so the connection of collector<->consumer - // is explicit in each \p DependencyScanningTool function. - switch (Service.getFormat()) { - case ScanningOutputFormat::Make: - case ScanningOutputFormat::Tree: - ScanInstance.addDependencyCollector( - std::make_shared( - std::move(Opts), WorkingDirectory, Consumer, EmitDependencyFile)); - break; - case ScanningOutputFormat::IncludeTree: - case ScanningOutputFormat::P1689: - case ScanningOutputFormat::Full: - case ScanningOutputFormat::FullTree: - case ScanningOutputFormat::FullIncludeTree: - if (EmitDependencyFile) { - auto DFG = - std::make_shared( - *Opts); - DFG->initialize(ScanInstance.getInvocation()); - ScanInstance.addDependencyCollector(std::move(DFG)); - } - - MDC = std::make_shared( - Service, std::move(Opts), ScanInstance, Consumer, Controller, - OriginalInvocation, std::move(PrebuiltModulesASTMap), StableDirs); - ScanInstance.addDependencyCollector(MDC); - ScanInstance.setGenModuleActionWrapper( - [&Controller = Controller](const FrontendOptions &Opts, - std::unique_ptr Wrapped) { - return std::make_unique( - std::move(Wrapped), Controller); - }); - break; - } - - // Consider different header search and diagnostic options to create - // different modules. This avoids the unsound aliasing of module PCMs. - // - // TODO: Implement diagnostic bucketing to reduce the impact of strict - // context hashing. - ScanInstance.getHeaderSearchOpts().ModulesStrictContextHash = true; - ScanInstance.getHeaderSearchOpts().ModulesSerializeOnlyPreprocessor = true; - ScanInstance.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true; - ScanInstance.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true; - ScanInstance.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = - true; - ScanInstance.getHeaderSearchOpts().ModulesForceValidateUserHeaders = false; - - // Avoid some checks and module map parsing when loading PCM files. - ScanInstance.getPreprocessorOpts().ModulesCheckRelocated = false; - - std::unique_ptr Action; - - if (Service.getFormat() == ScanningOutputFormat::P1689) - Action = std::make_unique(); - else if (ModuleName) - Action = std::make_unique(*ModuleName); - else - Action = std::make_unique(); - - // Normally this would be handled by GeneratePCHAction - if (ScanInstance.getFrontendOpts().ProgramAction == frontend::GeneratePCH) - ScanInstance.getLangOpts().CompilingPCH = true; - - if (Error E = Controller.initialize(ScanInstance, OriginalInvocation)) - return reportError(std::move(E)); - - if (ScanInstance.getDiagnostics().hasErrorOccurred()) - return false; - - // ExecuteAction is responsible for calling finish. - DiagConsumerFinished = true; - - if (!ScanInstance.ExecuteAction(*Action)) - return false; - - if (MDC) - MDC->applyDiscoveredDependencies(OriginalInvocation); - - if (Error E = Controller.finalize(ScanInstance, OriginalInvocation)) - return reportError(std::move(E)); - - // Forward any CAS results to consumer. - std::string ID = OriginalInvocation.getFileSystemOpts().CASFileSystemRootID; - if (!ID.empty()) - Consumer.handleCASFileSystemRootID(std::move(ID)); - ID = OriginalInvocation.getFrontendOpts().CASIncludeTreeID; - if (!ID.empty()) - Consumer.handleIncludeTreeID(std::move(ID)); - - LastCC1Arguments = OriginalInvocation.getCC1CommandLine(); - LastCC1CacheKey = Controller.getCacheKey(OriginalInvocation); - - return true; - } - - bool hasScanned() const { return Scanned; } - bool hasDiagConsumerFinished() const { return DiagConsumerFinished; } - - /// Take the cc1 arguments corresponding to the most recent invocation used - /// with this action. Any modifications implied by the discovered dependencies - /// will have already been applied. - std::vector takeLastCC1Arguments() { - std::vector Result; - std::swap(Result, LastCC1Arguments); // Reset LastCC1Arguments to empty. - return Result; - } - - std::optional takeLastCC1CacheKey() { - std::optional Result; - std::swap(Result, LastCC1CacheKey); - return Result; - } - - IntrusiveRefCntPtr getDepScanFS() { - if (DepFS) { - assert(!DepCASFS && "CAS DepFS should not be set"); - return DepFS; - } - if (DepCASFS) { - assert(!DepFS && "DepFS should not be set"); - return DepCASFS; - } - return nullptr; - } - - DependencyScanningService &Service; - StringRef WorkingDirectory; - DependencyConsumer &Consumer; - DependencyActionController &Controller; - llvm::IntrusiveRefCntPtr DepFS; - llvm::IntrusiveRefCntPtr DepCASFS; - llvm::IntrusiveRefCntPtr CacheFS; - const CASOptions &CASOpts; - bool EmitDependencyFile = false; - bool DiagGenerationAsCompilation; - std::optional ModuleName; - std::optional ScanInstanceStorage; - std::shared_ptr MDC; - std::vector LastCC1Arguments; - std::optional LastCC1CacheKey; - bool Scanned = false; - bool DiagConsumerFinished = false; - raw_ostream *VerboseOS; -}; - -} // end anonymous namespace - DependencyScanningWorker::DependencyScanningWorker( DependencyScanningService &Service, llvm::IntrusiveRefCntPtr FS) From 98baff9aed5964bd6cd38fd9c01aa3957ec92e96 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Thu, 2 Oct 2025 11:01:27 -0700 Subject: [PATCH 11/15] [clang] NFCI: Clean up `CompilerInstance::create{File,Source}Manager()` (#160748) The `CompilerInstance::createSourceManager()` function currently accepts the `FileManager` to be used. However, all clients call `CompilerInstance::createFileManager()` prior to creating the `SourceManager`, and it never makes sense to use a `FileManager` in the `SourceManager` that's different from the rest of the compiler. Passing the `FileManager` explicitly is redundant, error-prone, and deviates from the style of other `CompilerInstance` initialization APIs. This PR therefore removes the `FileManager` parameter from `createSourceManager()` and also stops returning the `FileManager` pointer from `createFileManager()`, since that was its primary use. Now, `createSourceManager()` internally calls `getFileManager()` instead. (cherry picked from commit b86ddae1da651f921125a9864b45a5b11bc3b1c0) Conflicts: clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp --- .../clang-include-fixer/IncludeFixer.cpp | 2 +- .../include-cleaner/unittests/RecordTest.cpp | 7 ++++--- clang/include/clang/Frontend/CompilerInstance.h | 6 ++---- clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 3 +-- clang/lib/Frontend/ChainedIncludesSource.cpp | 2 +- clang/lib/Frontend/CompilerInstance.cpp | 13 +++++++------ clang/lib/Frontend/FrontendAction.cpp | 11 ++++------- clang/lib/Testing/TestAST.cpp | 2 +- .../DependencyScanning/DependencyScannerImpl.cpp | 11 ++++++----- clang/lib/Tooling/Tooling.cpp | 2 +- clang/tools/clang-import-test/clang-import-test.cpp | 2 +- clang/unittests/CodeGen/TestCompiler.h | 2 +- .../Serialization/ForceCheckFileInputTest.cpp | 4 ++-- .../DependencyScanning/DependencyScannerTest.cpp | 2 +- .../Clang/ClangExpressionParser.cpp | 2 +- 15 files changed, 34 insertions(+), 37 deletions(-) diff --git a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp index d2ae13c022b23..e825547ba0134 100644 --- a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp +++ b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp @@ -96,7 +96,7 @@ bool IncludeFixerActionFactory::runInvocation( // diagnostics here. Compiler.createDiagnostics(new clang::IgnoringDiagConsumer, /*ShouldOwnClient=*/true); - Compiler.createSourceManager(*Files); + Compiler.createSourceManager(); // We abort on fatal errors so don't let a large number of errors become // fatal. A missing #include can cause thousands of errors. diff --git a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp index a09ba01fb678c..fc8b23ffcb17c 100644 --- a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp @@ -628,11 +628,12 @@ TEST_F(PragmaIncludeTest, ExportInUnnamedBuffer) { Clang->createVirtualFileSystem(VFS); Clang->createDiagnostics(); - auto *FM = Clang->createFileManager(); + Clang->createFileManager(); + FileManager &FM = Clang->getFileManager(); ASSERT_TRUE(Clang->ExecuteAction(*Inputs.MakeAction())); EXPECT_THAT( - PI.getExporters(llvm::cantFail(FM->getFileRef("foo.h")), *FM), - testing::ElementsAre(llvm::cantFail(FM->getFileRef("exporter.h")))); + PI.getExporters(llvm::cantFail(FM.getFileRef("foo.h")), FM), + testing::ElementsAre(llvm::cantFail(FM.getFileRef("exporter.h")))); } TEST_F(PragmaIncludeTest, OutlivesFMAndSM) { diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 38318c26d5c1f..35d56dab124de 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -755,12 +755,10 @@ class CompilerInstance : public ModuleLoader { const CodeGenOptions *CodeGenOpts = nullptr); /// Create the file manager and replace any existing one with it. - /// - /// \return The new file manager on success, or null on failure. - FileManager *createFileManager(); + void createFileManager(); /// Create the source manager and replace any existing one with it. - void createSourceManager(FileManager &FileMgr); + void createSourceManager(); /// Create the preprocessor, using the invocation, file, and source managers, /// and replace any existing one with it. diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index 1087eb3001856..6966d4097d64a 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -444,8 +444,7 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) { return true; if (!CI.hasFileManager()) - if (!CI.createFileManager()) - return false; + CI.createFileManager(); auto Kind = Inputs[0].getKind(); diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index 362551fd3b917..89dca7f7aa804 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -128,7 +128,7 @@ clang::createChainedIncludesSource(CompilerInstance &CI, Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts())); Clang->createFileManager(); - Clang->createSourceManager(Clang->getFileManager()); + Clang->createSourceManager(); Clang->createPreprocessor(TU_Prefix); Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(), &Clang->getPreprocessor()); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 09b0cf07598fb..3ea9a27719959 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -400,17 +400,18 @@ IntrusiveRefCntPtr CompilerInstance::createDiagnostics( // File Manager -FileManager *CompilerInstance::createFileManager() { +void CompilerInstance::createFileManager() { assert(VFS && "CompilerInstance needs a VFS for creating FileManager"); FileMgr = llvm::makeIntrusiveRefCnt(getFileSystemOpts(), VFS); - return FileMgr.get(); } // Source Manager -void CompilerInstance::createSourceManager(FileManager &FileMgr) { - SourceMgr = - llvm::makeIntrusiveRefCnt(getDiagnostics(), FileMgr); +void CompilerInstance::createSourceManager() { + assert(Diagnostics && "DiagnosticsEngine needed for creating SourceManager"); + assert(FileMgr && "FileManager needed for creating SourceManager"); + SourceMgr = llvm::makeIntrusiveRefCnt(getDiagnostics(), + getFileManager()); } // Initialize the remapping of files to alternative contents, e.g., @@ -1421,7 +1422,7 @@ std::unique_ptr CompilerInstance::cloneForModuleCompileImpl( if (llvm::is_contained(DiagOpts.SystemHeaderWarningsModules, ModuleName)) Instance.getDiagnostics().setSuppressSystemWarnings(false); - Instance.createSourceManager(Instance.getFileManager()); + Instance.createSourceManager(); SourceManager &SourceMgr = Instance.getSourceManager(); if (ThreadSafeConfig) { diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index aecc36f65cbb0..f2a3237f4d632 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -918,7 +918,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // file, otherwise the CompilerInstance will happily destroy them. CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr()); CI.setFileManager(AST->getFileManagerPtr()); - CI.createSourceManager(CI.getFileManager()); + CI.createSourceManager(); CI.getSourceManager().initializeForReplay(AST->getSourceManager()); // Preload all the module files loaded transitively by the AST unit. Also @@ -1010,13 +1010,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Set up the file system, file and source managers, if needed. if (!CI.hasVirtualFileSystem()) CI.createVirtualFileSystem(); - if (!CI.hasFileManager()) { - if (!CI.createFileManager()) { - return false; - } - } + if (!CI.hasFileManager()) + CI.createFileManager(); if (!CI.hasSourceManager()) { - CI.createSourceManager(CI.getFileManager()); + CI.createSourceManager(); if (CI.getDiagnosticOpts().getFormat() == DiagnosticOptions::SARIF) { static_cast(&CI.getDiagnosticClient()) ->setSarifWriter( diff --git a/clang/lib/Testing/TestAST.cpp b/clang/lib/Testing/TestAST.cpp index 9ad0de95530fb..d3338956f3043 100644 --- a/clang/lib/Testing/TestAST.cpp +++ b/clang/lib/Testing/TestAST.cpp @@ -61,7 +61,7 @@ void createMissingComponents(CompilerInstance &Clang) { if (!Clang.hasFileManager()) Clang.createFileManager(); if (!Clang.hasSourceManager()) - Clang.createSourceManager(Clang.getFileManager()); + Clang.createSourceManager(); if (!Clang.hasTarget()) Clang.createTarget(); if (!Clang.hasPreprocessor()) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp index 10a0f54e2dc72..249a3c3d4868c 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp @@ -560,7 +560,7 @@ bool DependencyScanningAction::runInvocation( any(Service.getOptimizeArgs() & ScanningOptimizations::VFS); // Create a new FileManager to match the invocation's FileSystemOptions. - auto *FileMgr = ScanInstance.createFileManager(); + ScanInstance.createFileManager(); // Use the dependency scanning optimized file system if requested to do so. if (DepFS) { @@ -568,13 +568,14 @@ bool DependencyScanningAction::runInvocation( if (!ScanInstance.getHeaderSearchOpts().ModuleCachePath.empty()) { SmallString<256> ModulesCachePath; normalizeModuleCachePath( - *FileMgr, ScanInstance.getHeaderSearchOpts().ModuleCachePath, - ModulesCachePath); + ScanInstance.getFileManager(), + ScanInstance.getHeaderSearchOpts().ModuleCachePath, ModulesCachePath); DepFS->setBypassedPathPrefix(ModulesCachePath); } ScanInstance.setDependencyDirectivesGetter( - std::make_unique(*FileMgr)); + std::make_unique( + ScanInstance.getFileManager())); } // CAS Implementation. @@ -582,7 +583,7 @@ bool DependencyScanningAction::runInvocation( ScanInstance.setDependencyDirectivesGetter( std::make_unique(DepCASFS.get())); - ScanInstance.createSourceManager(*FileMgr); + ScanInstance.createSourceManager(); // Create a collection of stable directories derived from the ScanInstance // for determining whether module dependencies would fully resolve from diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index 25f84b54629a6..c30c55110c3a3 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -457,7 +457,7 @@ bool FrontendActionFactory::runInvocation( if (!Compiler.hasDiagnostics()) return false; - Compiler.createSourceManager(*Files); + Compiler.createSourceManager(); const bool Success = Compiler.ExecuteAction(*ScopedToolAction); diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp index 5595c3612f517..2ad194f8e170b 100644 --- a/clang/tools/clang-import-test/clang-import-test.cpp +++ b/clang/tools/clang-import-test/clang-import-test.cpp @@ -216,7 +216,7 @@ std::unique_ptr BuildCompilerInstance() { Ins->getTarget().adjust(Ins->getDiagnostics(), Ins->getLangOpts(), /*AuxTarget=*/nullptr); Ins->createFileManager(); - Ins->createSourceManager(Ins->getFileManager()); + Ins->createSourceManager(); Ins->createPreprocessor(TU_Complete); return Ins; diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h index 66e45dd259935..1dec035f185c7 100644 --- a/clang/unittests/CodeGen/TestCompiler.h +++ b/clang/unittests/CodeGen/TestCompiler.h @@ -52,7 +52,7 @@ struct TestCompiler { PtrSize = TInfo.getPointerWidth(clang::LangAS::Default) / 8; compiler.createFileManager(); - compiler.createSourceManager(compiler.getFileManager()); + compiler.createSourceManager(); compiler.createPreprocessor(clang::TU_Prefix); compiler.createASTContext(); diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp index 24e2fd65f3c0a..edf33ae04230b 100644 --- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp +++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp @@ -122,8 +122,8 @@ export int aa = 43; Clang.setDiagnostics(Diags); Clang.createVirtualFileSystem(CIOpts.VFS); - FileManager *FM = Clang.createFileManager(); - Clang.createSourceManager(*FM); + Clang.createFileManager(); + Clang.createSourceManager(); EXPECT_TRUE(Clang.createTarget()); Clang.createPreprocessor(TU_Complete); diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp index ec5e36e07272b..7ea585edca401 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp @@ -69,7 +69,7 @@ class TestDependencyScanningAction : public tooling::ToolAction { if (!Compiler.hasDiagnostics()) return false; - Compiler.createSourceManager(*FileMgr); + Compiler.createSourceManager(); Compiler.addDependencyCollector(std::make_shared( Compiler.getInvocation().getDependencyOutputOpts(), Deps)); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index f1f114474db82..7691dfd2ccd17 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -841,7 +841,7 @@ ClangExpressionParser::ClangExpressionParser( // 6. Set up the source management objects inside the compiler m_compiler->createFileManager(); if (!m_compiler->hasSourceManager()) - m_compiler->createSourceManager(m_compiler->getFileManager()); + m_compiler->createSourceManager(); m_compiler->createPreprocessor(TU_Complete); switch (expr.Language().AsLanguageType()) { From dad6f367b88918e81c92d724f35299984e3488b8 Mon Sep 17 00:00:00 2001 From: git apple-llvm automerger Date: Fri, 3 Oct 2025 19:52:20 -0700 Subject: [PATCH 12/15] Merge commit '436861645247' from llvm.org/main into next (cherry picked from commit 286ea7d9fada1bee6fc2933327e1c7b5f2899fb5) Conflicts: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp --- .../Tooling/DependencyScanning/CMakeLists.txt | 1 - .../DependencyScannerImpl.cpp | 343 ++++++++++++++---- .../DependencyScannerImpl.h | 84 ++++- .../DependencyScanningWorker.cpp | 206 ++--------- 4 files changed, 393 insertions(+), 241 deletions(-) diff --git a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt index e559592189b93..a6a23ab18b330 100644 --- a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt +++ b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt @@ -30,6 +30,5 @@ add_clang_library(clangDependencyScanning clangFrontend clangLex clangSerialization - clangTooling ${LLVM_PTHREAD_LIB} ) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp index 249a3c3d4868c..de7367c4c9b76 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp @@ -10,10 +10,13 @@ #include "clang/Basic/DiagnosticCAS.h" #include "clang/Basic/DiagnosticFrontend.h" #include "clang/Basic/DiagnosticSerialization.h" +#include "clang/Driver/Driver.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" #include "clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h" +#include "llvm/CAS/CASProvidingFileSystem.h" +#include "llvm/TargetParser/Host.h" using namespace clang; using namespace tooling; @@ -457,11 +460,9 @@ class CASDependencyDirectivesGetter : public DependencyDirectivesGetter { return DepCASFS->getDirectiveTokens(File.getName()); } }; -} // namespace /// Sanitize diagnostic options for dependency scan. -void clang::tooling::dependencies::sanitizeDiagOpts( - DiagnosticOptions &DiagOpts) { +void sanitizeDiagOpts(DiagnosticOptions &DiagOpts) { // Don't print 'X warnings and Y errors generated'. DiagOpts.ShowCarets = false; // Don't write out diagnostic file. @@ -480,52 +481,158 @@ void clang::tooling::dependencies::sanitizeDiagOpts( .Default(true); }); } +} // namespace -bool DependencyScanningAction::runInvocation( - std::shared_ptr Invocation, - IntrusiveRefCntPtr FS, - std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagConsumer) { - // Making sure that we canonicalize the defines before we create the deep - // copy to avoid unnecessary variants in the scanner and in the resulting - // explicit command lines. - if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros)) - canonicalizeDefines(Invocation->getPreprocessorOpts()); +namespace clang::tooling::dependencies { +std::unique_ptr +createDiagOptions(ArrayRef CommandLine) { + std::vector CLI; + for (const std::string &Arg : CommandLine) + CLI.push_back(Arg.c_str()); + auto DiagOpts = CreateAndPopulateDiagOpts(CLI); + sanitizeDiagOpts(*DiagOpts); + return DiagOpts; +} - // Make a deep copy of the original Clang invocation. - CompilerInvocation OriginalInvocation(*Invocation); +DignosticsEngineWithDiagOpts::DignosticsEngineWithDiagOpts( + ArrayRef CommandLine, + IntrusiveRefCntPtr FS, DiagnosticConsumer &DC) { + std::vector CCommandLine(CommandLine.size(), nullptr); + llvm::transform(CommandLine, CCommandLine.begin(), + [](const std::string &Str) { return Str.c_str(); }); + DiagOpts = CreateAndPopulateDiagOpts(CCommandLine); + sanitizeDiagOpts(*DiagOpts); + DiagEngine = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC, + /*ShouldOwnClient=*/false); +} - if (Scanned) { - CompilerInstance &ScanInstance = *ScanInstanceStorage; - auto reportError = [&ScanInstance](Error &&E) -> bool { - ScanInstance.getDiagnostics().Report(diag::err_cas_depscan_failed) - << std::move(E); - return false; - }; +std::pair, std::unique_ptr> +buildCompilation(ArrayRef ArgStrs, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr FS) { + SmallVector Argv; + Argv.reserve(ArgStrs.size()); + for (const std::string &Arg : ArgStrs) + Argv.push_back(Arg.c_str()); + + std::unique_ptr Driver = std::make_unique( + Argv[0], llvm::sys::getDefaultTargetTriple(), Diags, + "clang LLVM compiler", FS); + Driver->setTitle("clang_based_tool"); + + llvm::BumpPtrAllocator Alloc; + bool CLMode = driver::IsClangCL( + driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1))); + + if (llvm::Error E = + driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) { + Diags.Report(diag::err_drv_expand_response_file) + << llvm::toString(std::move(E)); + return std::make_pair(nullptr, nullptr); + } - // Scanning runs once for the first -cc1 invocation in a chain of driver - // jobs. For any dependent jobs, reuse the scanning result and just - // update the LastCC1Arguments to correspond to the new invocation. - // FIXME: to support multi-arch builds, each arch requires a separate scan - if (MDC) - MDC->applyDiscoveredDependencies(OriginalInvocation); + std::unique_ptr Compilation( + Driver->BuildCompilation(Argv)); + if (!Compilation) + return std::make_pair(nullptr, nullptr); - if (Error E = Controller.finalize(ScanInstance, OriginalInvocation)) - return reportError(std::move(E)); + if (Compilation->containsError()) + return std::make_pair(nullptr, nullptr); - LastCC1Arguments = OriginalInvocation.getCC1CommandLine(); - LastCC1CacheKey = Controller.getCacheKey(OriginalInvocation); - return true; + return std::make_pair(std::move(Driver), std::move(Compilation)); +} + +std::unique_ptr +createCompilerInvocation(ArrayRef CommandLine, + DiagnosticsEngine &Diags) { + llvm::opt::ArgStringList Argv; + for (const std::string &Str : ArrayRef(CommandLine).drop_front()) + Argv.push_back(Str.c_str()); + + auto Invocation = std::make_unique(); + if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) { + // FIXME: Should we just go on like cc1_main does? + return nullptr; } + return Invocation; +} - Scanned = true; +std::pair, std::vector> +initVFSForTUBuferScanning( + IntrusiveRefCntPtr BaseFS, + ArrayRef CommandLine, StringRef WorkingDirectory, + llvm::MemoryBufferRef TUBuffer, std::shared_ptr CAS, + IntrusiveRefCntPtr DepCASFS) { + // Reset what might have been modified in the previous worker invocation. + BaseFS->setCurrentWorkingDirectory(WorkingDirectory); + + IntrusiveRefCntPtr ModifiedFS; + auto OverlayFS = + llvm::makeIntrusiveRefCnt(BaseFS); + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory); + auto InputPath = TUBuffer.getBufferIdentifier(); + InMemoryFS->addFile( + InputPath, 0, llvm::MemoryBuffer::getMemBufferCopy(TUBuffer.getBuffer())); + IntrusiveRefCntPtr InMemoryOverlay = InMemoryFS; + + // If we are using a CAS but not dependency CASFS, we need to provide the + // fake input file in a CASProvidingFS for include-tree. + if (CAS && !DepCASFS) + InMemoryOverlay = + llvm::cas::createCASProvidingFileSystem(CAS, std::move(InMemoryFS)); + + OverlayFS->pushOverlay(InMemoryOverlay); + ModifiedFS = OverlayFS; + std::vector ModifiedCommandLine(CommandLine); + ModifiedCommandLine.emplace_back(InputPath); + + return std::make_pair(ModifiedFS, ModifiedCommandLine); +} - // Create a compiler instance to handle the actual work. - auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries()); - ScanInstanceStorage.emplace(std::move(Invocation), std::move(PCHContainerOps), - ModCache.get()); - CompilerInstance &ScanInstance = *ScanInstanceStorage; - ScanInstance.getInvocation().getCASOpts() = CASOpts; +std::pair, std::vector> +initVFSForByNameScanning( + IntrusiveRefCntPtr BaseFS, + ArrayRef CommandLine, StringRef WorkingDirectory, + StringRef ModuleName, std::shared_ptr CAS, + IntrusiveRefCntPtr DepCASFS) { + // Reset what might have been modified in the previous worker invocation. + BaseFS->setCurrentWorkingDirectory(WorkingDirectory); + + // If we're scanning based on a module name alone, we don't expect the client + // to provide us with an input file. However, the driver really wants to have + // one. Let's just make it up to make the driver happy. + auto OverlayFS = + llvm::makeIntrusiveRefCnt(BaseFS); + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory); + SmallString<128> FakeInputPath; + // TODO: We should retry the creation if the path already exists. + llvm::sys::fs::createUniquePath(ModuleName + "-%%%%%%%%.input", FakeInputPath, + /*MakeAbsolute=*/false); + InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer("")); + IntrusiveRefCntPtr InMemoryOverlay = InMemoryFS; + + // If we are using a CAS but not dependency CASFS, we need to provide the + // fake input file in a CASProvidingFS for include-tree. + if (CAS && !DepCASFS) + InMemoryOverlay = + llvm::cas::createCASProvidingFileSystem(CAS, std::move(InMemoryFS)); + + OverlayFS->pushOverlay(InMemoryOverlay); + + std::vector ModifiedCommandLine(CommandLine); + ModifiedCommandLine.emplace_back(FakeInputPath); + + return std::make_pair(OverlayFS, ModifiedCommandLine); +} + +bool initializeScanCompilerInstance( + CompilerInstance &ScanInstance, + IntrusiveRefCntPtr FS, + DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service, + IntrusiveRefCntPtr DepFS, + bool DiagGenerationAsCompilation, raw_ostream *VerboseOS, + llvm::IntrusiveRefCntPtr DepCASFS) { ScanInstance.setBuildingModule(false); ScanInstance.createVirtualFileSystem(FS, DiagConsumer); @@ -533,7 +640,7 @@ bool DependencyScanningAction::runInvocation( // Create the compiler's actual diagnostics engine. if (!DiagGenerationAsCompilation) sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); - assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); + ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); if (!ScanInstance.hasDiagnostics()) return false; @@ -585,6 +692,26 @@ bool DependencyScanningAction::runInvocation( ScanInstance.createSourceManager(); + // Consider different header search and diagnostic options to create + // different modules. This avoids the unsound aliasing of module PCMs. + // + // TODO: Implement diagnostic bucketing to reduce the impact of strict + // context hashing. + ScanInstance.getHeaderSearchOpts().ModulesStrictContextHash = true; + ScanInstance.getHeaderSearchOpts().ModulesSerializeOnlyPreprocessor = true; + ScanInstance.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true; + ScanInstance.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true; + ScanInstance.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = true; + ScanInstance.getHeaderSearchOpts().ModulesForceValidateUserHeaders = false; + + // Avoid some checks and module map parsing when loading PCM files. + ScanInstance.getPreprocessorOpts().ModulesCheckRelocated = false; + + return true; +} + +llvm::SmallVector +getInitialStableDirs(const CompilerInstance &ScanInstance) { // Create a collection of stable directories derived from the ScanInstance // for determining whether module dependencies would fully resolve from // those directories. @@ -592,7 +719,12 @@ bool DependencyScanningAction::runInvocation( const StringRef Sysroot = ScanInstance.getHeaderSearchOpts().Sysroot; if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot)) StableDirs = {Sysroot, ScanInstance.getHeaderSearchOpts().ResourceDir}; + return StableDirs; +} +std::optional +computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, + llvm::SmallVector &StableDirs) { // Store a mapping of prebuilt module files and their properties like header // search options. This will prevent the implicit build to create duplicate // modules and will force reuse of the existing prebuilt module files @@ -604,12 +736,15 @@ bool DependencyScanningAction::runInvocation( ScanInstance.getPreprocessorOpts().ImplicitPCHInclude, ScanInstance, ScanInstance.getHeaderSearchOpts().PrebuiltModuleFiles, PrebuiltModulesASTMap, ScanInstance.getDiagnostics(), StableDirs)) - return false; + return {}; - // Create the dependency collector that will collect the produced - // dependencies. - // - // This also moves the existing dependency output options from the + return PrebuiltModulesASTMap; +} + +std::unique_ptr +takeDependencyOutputOptionsFrom(CompilerInstance &ScanInstance, + bool ForceIncludeSystemHeaders) { + // This function moves the existing dependency output options from the // invocation to the collector. The options in the invocation are reset, // which ensures that the compiler won't create new dependency collectors, // and thus won't write out the extra '.d' files to disk. @@ -620,18 +755,24 @@ bool DependencyScanningAction::runInvocation( if (Opts->Targets.empty()) Opts->Targets = {deduceDepTarget(ScanInstance.getFrontendOpts().OutputFile, ScanInstance.getFrontendOpts().Inputs)}; - if (Service.getFormat() == ScanningOutputFormat::Make) { + if (ForceIncludeSystemHeaders) { // Only 'Make' scanning needs to force this because that mode depends on // getting the dependencies directly from \p DependencyFileGenerator. Opts->IncludeSystemHeaders = true; } - auto reportError = [&ScanInstance](Error &&E) -> bool { - ScanInstance.getDiagnostics().Report(diag::err_cas_depscan_failed) - << std::move(E); - return false; - }; + return Opts; +} +std::shared_ptr initializeScanInstanceDependencyCollector( + CompilerInstance &ScanInstance, + std::unique_ptr DepOutputOpts, + StringRef WorkingDirectory, DependencyConsumer &Consumer, + DependencyScanningService &Service, CompilerInvocation &Inv, + DependencyActionController &Controller, + PrebuiltModulesAttrsMap PrebuiltModulesASTMap, + llvm::SmallVector &StableDirs, bool EmitDependencyFile) { + std::shared_ptr MDC; // FIXME: The caller APIs in \p DependencyScanningTool expect a specific // DependencyCollector to get attached to the preprocessor in order to // function properly (e.g. \p FullDependencyConsumer needs \p @@ -645,7 +786,8 @@ bool DependencyScanningAction::runInvocation( case ScanningOutputFormat::Tree: ScanInstance.addDependencyCollector( std::make_shared( - std::move(Opts), WorkingDirectory, Consumer, EmitDependencyFile)); + std::move(DepOutputOpts), WorkingDirectory, Consumer, + EmitDependencyFile)); break; case ScanningOutputFormat::IncludeTree: case ScanningOutputFormat::P1689: @@ -653,15 +795,15 @@ bool DependencyScanningAction::runInvocation( case ScanningOutputFormat::FullTree: case ScanningOutputFormat::FullIncludeTree: if (EmitDependencyFile) { - auto DFG = - std::make_shared(*Opts); + auto DFG = std::make_shared( + *DepOutputOpts); DFG->initialize(ScanInstance.getInvocation()); ScanInstance.addDependencyCollector(std::move(DFG)); } MDC = std::make_shared( - Service, std::move(Opts), ScanInstance, Consumer, Controller, - OriginalInvocation, std::move(PrebuiltModulesASTMap), StableDirs); + Service, std::move(DepOutputOpts), ScanInstance, Consumer, Controller, + Inv, std::move(PrebuiltModulesASTMap), StableDirs); ScanInstance.addDependencyCollector(MDC); ScanInstance.setGenModuleActionWrapper( [&Controller = Controller](const FrontendOptions &Opts, @@ -672,20 +814,75 @@ bool DependencyScanningAction::runInvocation( break; } - // Consider different header search and diagnostic options to create - // different modules. This avoids the unsound aliasing of module PCMs. - // - // TODO: Implement diagnostic bucketing to reduce the impact of strict - // context hashing. - ScanInstance.getHeaderSearchOpts().ModulesStrictContextHash = true; - ScanInstance.getHeaderSearchOpts().ModulesSerializeOnlyPreprocessor = true; - ScanInstance.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true; - ScanInstance.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true; - ScanInstance.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = true; - ScanInstance.getHeaderSearchOpts().ModulesForceValidateUserHeaders = false; + return MDC; +} +} // namespace clang::tooling::dependencies - // Avoid some checks and module map parsing when loading PCM files. - ScanInstance.getPreprocessorOpts().ModulesCheckRelocated = false; +bool DependencyScanningAction::runInvocation( + std::shared_ptr Invocation, + IntrusiveRefCntPtr FS, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagConsumer) { + // Making sure that we canonicalize the defines before we create the deep + // copy to avoid unnecessary variants in the scanner and in the resulting + // explicit command lines. + if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros)) + canonicalizeDefines(Invocation->getPreprocessorOpts()); + + // Make a deep copy of the original Clang invocation. + CompilerInvocation OriginalInvocation(*Invocation); + + if (Scanned) { + CompilerInstance &ScanInstance = *ScanInstanceStorage; + auto reportError = [&ScanInstance](Error &&E) -> bool { + ScanInstance.getDiagnostics().Report(diag::err_cas_depscan_failed) + << std::move(E); + return false; + }; + + // Scanning runs once for the first -cc1 invocation in a chain of driver + // jobs. For any dependent jobs, reuse the scanning result and just + // update the LastCC1Arguments to correspond to the new invocation. + // FIXME: to support multi-arch builds, each arch requires a separate scan + if (MDC) + MDC->applyDiscoveredDependencies(OriginalInvocation); + + if (Error E = Controller.finalize(ScanInstance, OriginalInvocation)) + return reportError(std::move(E)); + + LastCC1Arguments = OriginalInvocation.getCC1CommandLine(); + LastCC1CacheKey = Controller.getCacheKey(OriginalInvocation); + return true; + } + + Scanned = true; + + // Create a compiler instance to handle the actual work. + auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries()); + ScanInstanceStorage.emplace(std::move(Invocation), std::move(PCHContainerOps), + ModCache.get()); + CompilerInstance &ScanInstance = *ScanInstanceStorage; + ScanInstance.getInvocation().getCASOpts() = CASOpts; + + assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); + if (!initializeScanCompilerInstance(ScanInstance, FS, DiagConsumer, Service, + DepFS, DiagGenerationAsCompilation, + VerboseOS, DepCASFS)) + return false; + + llvm::SmallVector StableDirs = getInitialStableDirs(ScanInstance); + auto MaybePrebuiltModulesASTMap = + computePrebuiltModulesASTMap(ScanInstance, StableDirs); + if (!MaybePrebuiltModulesASTMap) + return false; + + auto DepOutputOpts = takeDependencyOutputOptionsFrom( + ScanInstance, Service.getFormat() == ScanningOutputFormat::Make); + + MDC = initializeScanInstanceDependencyCollector( + ScanInstance, std::move(DepOutputOpts), WorkingDirectory, Consumer, + Service, OriginalInvocation, Controller, *MaybePrebuiltModulesASTMap, + StableDirs, EmitDependencyFile); std::unique_ptr Action; @@ -700,6 +897,12 @@ bool DependencyScanningAction::runInvocation( if (ScanInstance.getFrontendOpts().ProgramAction == frontend::GeneratePCH) ScanInstance.getLangOpts().CompilingPCH = true; + auto reportError = [&ScanInstance](Error &&E) -> bool { + ScanInstance.getDiagnostics().Report(diag::err_cas_depscan_failed) + << std::move(E); + return false; + }; + if (Error E = Controller.initialize(ScanInstance, OriginalInvocation)) return reportError(std::move(E)); diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h index 3c131f844e380..0093df7ed6bf1 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h @@ -9,8 +9,10 @@ #ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNER_H #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNER_H +#include "clang/Driver/Compilation.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Serialization/ObjectFilePCHContainerReader.h" #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" @@ -81,9 +83,87 @@ class DependencyScanningAction { raw_ostream *VerboseOS; }; -// Helper functions -void sanitizeDiagOpts(DiagnosticOptions &DiagOpts); +// Helper functions and data types. +std::unique_ptr +createDiagOptions(ArrayRef CommandLine); +struct DignosticsEngineWithDiagOpts { + // We need to bound the lifetime of the DiagOpts used to create the + // DiganosticsEngine with the DiagnosticsEngine itself. + std::unique_ptr DiagOpts; + IntrusiveRefCntPtr DiagEngine; + + DignosticsEngineWithDiagOpts(ArrayRef CommandLine, + IntrusiveRefCntPtr FS, + DiagnosticConsumer &DC); +}; + +struct TextDiagnosticsPrinterWithOutput { + // We need to bound the lifetime of the data that supports the DiagPrinter + // with it together so they have the same lifetime. + std::string DiagnosticOutput; + llvm::raw_string_ostream DiagnosticsOS; + std::unique_ptr DiagOpts; + TextDiagnosticPrinter DiagPrinter; + + TextDiagnosticsPrinterWithOutput(ArrayRef CommandLine) + : DiagnosticsOS(DiagnosticOutput), + DiagOpts(createDiagOptions(CommandLine)), + DiagPrinter(DiagnosticsOS, *DiagOpts) {} +}; + +std::pair, std::unique_ptr> +buildCompilation(ArrayRef ArgStrs, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr FS); + +std::unique_ptr +createCompilerInvocation(ArrayRef CommandLine, + DiagnosticsEngine &Diags); + +std::pair, std::vector> +initVFSForTUBuferScanning( + IntrusiveRefCntPtr BaseFS, + ArrayRef CommandLine, StringRef WorkingDirectory, + llvm::MemoryBufferRef TUBuffer, std::shared_ptr CAS, + IntrusiveRefCntPtr DepCASFS); + +std::pair, std::vector> +initVFSForByNameScanning( + IntrusiveRefCntPtr BaseFS, + ArrayRef CommandLine, StringRef WorkingDirectory, + StringRef ModuleName, std::shared_ptr CAS, + IntrusiveRefCntPtr DepCASFS); + +bool initializeScanCompilerInstance( + CompilerInstance &ScanInstance, + IntrusiveRefCntPtr FS, + DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service, + IntrusiveRefCntPtr DepFS, + bool DiagGenerationAsCompilation, raw_ostream *VerboseOS, + llvm::IntrusiveRefCntPtr DepCASFS); + +SmallVector +getInitialStableDirs(const CompilerInstance &ScanInstance); + +std::optional +computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, + SmallVector &StableDirs); + +std::unique_ptr +takeDependencyOutputOptionsFrom(CompilerInstance &ScanInstance, + bool ForceIncludeSystemHeaders); + +/// Create the dependency collector that will collect the produced +/// dependencies. May return the created ModuleDepCollector depending +/// on the scanning format. +std::shared_ptr initializeScanInstanceDependencyCollector( + CompilerInstance &ScanInstance, + std::unique_ptr DepOutputOpts, + StringRef WorkingDirectory, DependencyConsumer &Consumer, + DependencyScanningService &Service, CompilerInvocation &Inv, + DependencyActionController &Controller, + PrebuiltModulesAttrsMap PrebuiltModulesASTMap, + llvm::SmallVector &StableDirs, bool EmitDependencyFile); } // namespace dependencies } // namespace tooling } // namespace clang diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index eba46e44f20f6..0cc80e01ddd80 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -8,34 +8,9 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" #include "DependencyScannerImpl.h" -#include "clang/Basic/DiagnosticDriver.h" #include "clang/Basic/DiagnosticFrontend.h" -#include "clang/Basic/DiagnosticSerialization.h" -#include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/Job.h" #include "clang/Driver/Tool.h" -#include "clang/Frontend/CompileJobCacheKey.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/CompilerInvocation.h" -#include "clang/Frontend/FrontendActions.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Frontend/Utils.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Serialization/ObjectFilePCHContainerReader.h" -#include "clang/Tooling/DependencyScanning/DependencyScanningService.h" -#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h" -#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/CAS/CASProvidingFileSystem.h" -#include "llvm/CAS/CachingOnDiskFileSystem.h" -#include "llvm/CAS/ObjectStore.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PrefixMapper.h" -#include "llvm/TargetParser/Host.h" -#include using namespace clang; using namespace tooling; @@ -82,32 +57,19 @@ DependencyScanningWorker::getOrCreateFileManager() const { return new FileManager(FileSystemOptions(), BaseFS); } -static std::unique_ptr -createDiagOptions(const std::vector &CommandLine) { - std::vector CLI; - for (const std::string &Arg : CommandLine) - CLI.push_back(Arg.c_str()); - auto DiagOpts = CreateAndPopulateDiagOpts(CLI); - sanitizeDiagOpts(*DiagOpts); - return DiagOpts; -} - llvm::Error DependencyScanningWorker::computeDependencies( StringRef WorkingDirectory, const std::vector &CommandLine, DependencyConsumer &Consumer, DependencyActionController &Controller, std::optional TUBuffer) { // Capture the emitted diagnostics and report them to the client // in the case of a failure. - std::string DiagnosticOutput; - llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput); - auto DiagOpts = createDiagOptions(CommandLine); - TextDiagnosticPrinter DiagPrinter(DiagnosticsOS, *DiagOpts); + TextDiagnosticsPrinterWithOutput DiagPrinterWithOS(CommandLine); if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller, - DiagPrinter, TUBuffer)) + DiagPrinterWithOS.DiagPrinter, TUBuffer)) return llvm::Error::success(); - return llvm::make_error(DiagnosticsOS.str(), - llvm::inconvertibleErrorCode()); + return llvm::make_error( + DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode()); } llvm::Error DependencyScanningWorker::computeDependencies( @@ -116,51 +78,24 @@ llvm::Error DependencyScanningWorker::computeDependencies( StringRef ModuleName) { // Capture the emitted diagnostics and report them to the client // in the case of a failure. - std::string DiagnosticOutput; - llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput); - auto DiagOpts = createDiagOptions(CommandLine); - TextDiagnosticPrinter DiagPrinter(DiagnosticsOS, *DiagOpts); + TextDiagnosticsPrinterWithOutput DiagPrinterWithOS(CommandLine); if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller, - DiagPrinter, ModuleName)) + DiagPrinterWithOS.DiagPrinter, ModuleName)) return llvm::Error::success(); - return llvm::make_error(DiagnosticsOS.str(), - llvm::inconvertibleErrorCode()); + return llvm::make_error( + DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode()); } static bool forEachDriverJob( ArrayRef ArgStrs, DiagnosticsEngine &Diags, IntrusiveRefCntPtr FS, llvm::function_ref Callback) { - SmallVector Argv; - Argv.reserve(ArgStrs.size()); - for (const std::string &Arg : ArgStrs) - Argv.push_back(Arg.c_str()); - - std::unique_ptr Driver = std::make_unique( - Argv[0], llvm::sys::getDefaultTargetTriple(), Diags, - "clang LLVM compiler", FS); - Driver->setTitle("clang_based_tool"); - - llvm::BumpPtrAllocator Alloc; - bool CLMode = driver::IsClangCL( - driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1))); - - if (llvm::Error E = - driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) { - Diags.Report(diag::err_drv_expand_response_file) - << llvm::toString(std::move(E)); - return false; - } - - const std::unique_ptr Compilation( - Driver->BuildCompilation(llvm::ArrayRef(Argv))); + // Compilation holds a non-owning a reference to the Driver, hence we need to + // keep the Driver alive when we use Compilation. + auto [Driver, Compilation] = buildCompilation(ArgStrs, Diags, FS); if (!Compilation) return false; - - if (Compilation->containsError()) - return false; - for (const driver::Command &Job : Compilation->getJobs()) { if (!Callback(Job)) return false; @@ -169,23 +104,14 @@ static bool forEachDriverJob( } static bool createAndRunToolInvocation( - std::vector CommandLine, DependencyScanningAction &Action, + const std::vector &CommandLine, + DependencyScanningAction &Action, IntrusiveRefCntPtr FS, std::shared_ptr &PCHContainerOps, DiagnosticsEngine &Diags, DependencyConsumer &Consumer) { - - // Save executable path before providing CommandLine to ToolInvocation - std::string Executable = CommandLine[0]; - - llvm::opt::ArgStringList Argv; - for (const std::string &Str : ArrayRef(CommandLine).drop_front()) - Argv.push_back(Str.c_str()); - - auto Invocation = std::make_shared(); - if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) { - // FIXME: Should we just go on like cc1_main does? + auto Invocation = createCompilerInvocation(CommandLine, Diags); + if (!Invocation) return false; - } if (!Action.runInvocation(std::move(Invocation), std::move(FS), PCHContainerOps, Diags.getClient())) @@ -194,7 +120,7 @@ static bool createAndRunToolInvocation( std::vector Args = Action.takeLastCC1Arguments(); std::optional CacheKey = Action.takeLastCC1CacheKey(); Consumer.handleBuildCommand( - {std::move(Executable), std::move(Args), std::move(CacheKey)}); + {CommandLine[0], std::move(Args), std::move(CacheKey)}); return true; } @@ -203,25 +129,20 @@ bool DependencyScanningWorker::scanDependencies( DependencyConsumer &Consumer, DependencyActionController &Controller, DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr FS, std::optional ModuleName) { - std::vector CCommandLine(CommandLine.size(), nullptr); - llvm::transform(CommandLine, CCommandLine.begin(), - [](const std::string &Str) { return Str.c_str(); }); - auto DiagOpts = CreateAndPopulateDiagOpts(CCommandLine); - sanitizeDiagOpts(*DiagOpts); - auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC, - /*ShouldOwnClient=*/false); - + DignosticsEngineWithDiagOpts DiagEngineWithCmdAndOpts(CommandLine, FS, DC); DependencyScanningAction Action( Service, WorkingDirectory, Consumer, Controller, DepFS, DepCASFS, CacheFS, /*EmitDependencyFile=*/false, /*DiagGenerationAsCompilation=*/false, getCASOpts(), ModuleName); bool Success = false; if (CommandLine[1] == "-cc1") { - Success = createAndRunToolInvocation(CommandLine, Action, FS, - PCHContainerOps, *Diags, Consumer); + Success = createAndRunToolInvocation( + CommandLine, Action, FS, PCHContainerOps, + *DiagEngineWithCmdAndOpts.DiagEngine, Consumer); } else { Success = forEachDriverJob( - CommandLine, *Diags, FS, [&](const driver::Command &Cmd) { + CommandLine, *DiagEngineWithCmdAndOpts.DiagEngine, FS, + [&](const driver::Command &Cmd) { if (StringRef(Cmd.getCreator().getName()) != "clang") { // Non-clang command. Just pass through to the dependency // consumer. @@ -241,13 +162,15 @@ bool DependencyScanningWorker::scanDependencies( // system to ensure that any file system requests that // are made by the driver do not go through the // dependency scanning filesystem. - return createAndRunToolInvocation(std::move(Argv), Action, FS, - PCHContainerOps, *Diags, Consumer); + return createAndRunToolInvocation( + std::move(Argv), Action, FS, PCHContainerOps, + *DiagEngineWithCmdAndOpts.DiagEngine, Consumer); }); } if (Success && !Action.hasScanned()) - Diags->Report(diag::err_fe_expected_compiler_job) + DiagEngineWithCmdAndOpts.DiagEngine->Report( + diag::err_fe_expected_compiler_job) << llvm::join(CommandLine, " "); // Ensure finish() is called even if we never reached ExecuteAction(). @@ -261,78 +184,25 @@ bool DependencyScanningWorker::computeDependencies( StringRef WorkingDirectory, const std::vector &CommandLine, DependencyConsumer &Consumer, DependencyActionController &Controller, DiagnosticConsumer &DC, std::optional TUBuffer) { - // Reset what might have been modified in the previous worker invocation. - BaseFS->setCurrentWorkingDirectory(WorkingDirectory); - - std::optional> ModifiedCommandLine; - llvm::IntrusiveRefCntPtr ModifiedFS; - - // If we're scanning based on a module name alone, we don't expect the client - // to provide us with an input file. However, the driver really wants to have - // one. Let's just make it up to make the driver happy. if (TUBuffer) { - auto OverlayFS = - llvm::makeIntrusiveRefCnt(BaseFS); - auto InMemoryFS = - llvm::makeIntrusiveRefCnt(); - InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory); - auto InputPath = TUBuffer->getBufferIdentifier(); - InMemoryFS->addFile( - InputPath, 0, - llvm::MemoryBuffer::getMemBufferCopy(TUBuffer->getBuffer())); - llvm::IntrusiveRefCntPtr InMemoryOverlay = - InMemoryFS; - - // If we are using a CAS but not dependency CASFS, we need to provide the - // fake input file in a CASProvidingFS for include-tree. - if (CAS && !DepCASFS) - InMemoryOverlay = - llvm::cas::createCASProvidingFileSystem(CAS, std::move(InMemoryFS)); - - OverlayFS->pushOverlay(InMemoryOverlay); - ModifiedFS = OverlayFS; - ModifiedCommandLine = CommandLine; - ModifiedCommandLine->emplace_back(InputPath); + auto [FinalFS, FinalCommandLine] = initVFSForTUBuferScanning( + BaseFS, CommandLine, WorkingDirectory, *TUBuffer, CAS, DepCASFS); + return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer, + Controller, DC, FinalFS, + /*ModuleName=*/std::nullopt); + } else { + BaseFS->setCurrentWorkingDirectory(WorkingDirectory); + return scanDependencies(WorkingDirectory, CommandLine, Consumer, Controller, + DC, BaseFS, /*ModuleName=*/std::nullopt); } - - const std::vector &FinalCommandLine = - ModifiedCommandLine ? *ModifiedCommandLine : CommandLine; - auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS; - - return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer, - Controller, DC, FinalFS, /*ModuleName=*/std::nullopt); } bool DependencyScanningWorker::computeDependencies( StringRef WorkingDirectory, const std::vector &CommandLine, DependencyConsumer &Consumer, DependencyActionController &Controller, DiagnosticConsumer &DC, StringRef ModuleName) { - // Reset what might have been modified in the previous worker invocation. - BaseFS->setCurrentWorkingDirectory(WorkingDirectory); - - // If we're scanning based on a module name alone, we don't expect the client - // to provide us with an input file. However, the driver really wants to have - // one. Let's just make it up to make the driver happy. - auto OverlayFS = - llvm::makeIntrusiveRefCnt(BaseFS); - auto InMemoryFS = llvm::makeIntrusiveRefCnt(); - InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory); - SmallString<128> FakeInputPath; - // TODO: We should retry the creation if the path already exists. - llvm::sys::fs::createUniquePath(ModuleName + "-%%%%%%%%.input", FakeInputPath, - /*MakeAbsolute=*/false); - InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer("")); - llvm::IntrusiveRefCntPtr InMemoryOverlay = InMemoryFS; - - // If we are using a CAS but not dependency CASFS, we need to provide the - // fake input file in a CASProvidingFS for include-tree. - if (CAS && !DepCASFS) - InMemoryOverlay = - llvm::cas::createCASProvidingFileSystem(CAS, std::move(InMemoryFS)); - - OverlayFS->pushOverlay(InMemoryOverlay); - auto ModifiedCommandLine = CommandLine; - ModifiedCommandLine.emplace_back(FakeInputPath); + auto [OverlayFS, ModifiedCommandLine] = initVFSForByNameScanning( + BaseFS, CommandLine, WorkingDirectory, ModuleName, CAS, DepCASFS); return scanDependencies(WorkingDirectory, ModifiedCommandLine, Consumer, Controller, DC, OverlayFS, ModuleName); From b5fa133f97d6c12378e321e7c29eefd0cf963aaa Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Thu, 18 Sep 2025 11:07:40 -0700 Subject: [PATCH 13/15] [clang] Pass VFS into `ASTUnit::LoadFromASTFile()` (#159166) This PR makes the `VFS` parameter to `ASTUnit::LoadFromASTFile()` required and explicit, rather than silently defaulting to the real file system. This makes it easy to correctly propagate the fully-configured VFS and load any input files like the rest of the compiler does. (cherry picked from commit cda542dd21eb550c58b398f1a47216ed55edf72d) --- clang/include/clang/Frontend/ASTUnit.h | 7 +++---- clang/lib/CrossTU/CrossTranslationUnit.cpp | 4 ++-- clang/lib/Frontend/ASTMerge.cpp | 3 ++- clang/lib/Frontend/ASTUnit.cpp | 5 +++-- clang/lib/Frontend/FrontendAction.cpp | 9 +++++---- clang/tools/c-index-test/core_main.cpp | 7 ++++--- clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp | 4 ++-- clang/tools/libclang/CIndex.cpp | 7 ++++--- clang/unittests/Frontend/ASTUnitTest.cpp | 3 ++- 9 files changed, 27 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 5069c73ad6d99..84eda1184fc43 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -716,16 +716,15 @@ class ASTUnit { /// \returns - The initialized ASTUnit or null if the AST failed to load. static std::unique_ptr LoadFromASTFile( StringRef Filename, const PCHContainerReader &PCHContainerRdr, - WhatToLoad ToLoad, std::shared_ptr DiagOpts, + WhatToLoad ToLoad, IntrusiveRefCntPtr VFS, + std::shared_ptr DiagOpts, IntrusiveRefCntPtr Diags, const FileSystemOptions &FileSystemOpts, const HeaderSearchOptions &HSOpts, const LangOptions *LangOpts = nullptr, bool OnlyLocalDecls = false, CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None, bool AllowASTWithCompilerErrors = false, - bool UserFilesAreVolatile = false, - IntrusiveRefCntPtr VFS = - llvm::vfs::getRealFileSystem()); + bool UserFilesAreVolatile = false); private: /// Helper function for \c LoadFromCompilerInvocation() and diff --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp index fb2a79ab657db..c4d48bad9cee7 100644 --- a/clang/lib/CrossTU/CrossTranslationUnit.cpp +++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp @@ -567,8 +567,8 @@ CrossTranslationUnitContext::ASTLoader::loadFromDump(StringRef ASTDumpPath) { DiagnosticIDs::create(), *DiagOpts, DiagClient); return ASTUnit::LoadFromASTFile( ASTDumpPath, CI.getPCHContainerOperations()->getRawReader(), - ASTUnit::LoadEverything, DiagOpts, Diags, CI.getFileSystemOpts(), - CI.getHeaderSearchOpts()); + ASTUnit::LoadEverything, CI.getVirtualFileSystemPtr(), DiagOpts, Diags, + CI.getFileSystemOpts(), CI.getHeaderSearchOpts()); } /// Load the AST from a source-file, which is supposed to be located inside the diff --git a/clang/lib/Frontend/ASTMerge.cpp b/clang/lib/Frontend/ASTMerge.cpp index 10c10458466bc..0dff69d613bcf 100644 --- a/clang/lib/Frontend/ASTMerge.cpp +++ b/clang/lib/Frontend/ASTMerge.cpp @@ -47,7 +47,8 @@ void ASTMergeAction::ExecuteAction() { /*ShouldOwnClient=*/true); std::unique_ptr Unit = ASTUnit::LoadFromASTFile( ASTFiles[I], CI.getPCHContainerReader(), ASTUnit::LoadEverything, - nullptr, Diags, CI.getFileSystemOpts(), CI.getHeaderSearchOpts()); + CI.getVirtualFileSystemPtr(), nullptr, Diags, CI.getFileSystemOpts(), + CI.getHeaderSearchOpts()); if (!Unit) continue; diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 3ea1a73aeb3e0..376f79275bdba 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -799,12 +799,13 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr Diags, std::unique_ptr ASTUnit::LoadFromASTFile( StringRef Filename, const PCHContainerReader &PCHContainerRdr, - WhatToLoad ToLoad, std::shared_ptr DiagOpts, + WhatToLoad ToLoad, IntrusiveRefCntPtr VFS, + std::shared_ptr DiagOpts, IntrusiveRefCntPtr Diags, const FileSystemOptions &FileSystemOpts, const HeaderSearchOptions &HSOpts, const LangOptions *LangOpts, bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors, - bool UserFilesAreVolatile, IntrusiveRefCntPtr VFS) { + bool UserFilesAreVolatile) { std::unique_ptr AST(new ASTUnit(true)); // Recover resources if we crash before exiting this method. diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index f2a3237f4d632..ba4369d1dfeb0 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -904,7 +904,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, std::unique_ptr AST = ASTUnit::LoadFromASTFile( InputFile, CI.getPCHContainerReader(), ASTUnit::LoadPreprocessorOnly, - nullptr, ASTDiags, CI.getFileSystemOpts(), CI.getHeaderSearchOpts()); + CI.getVirtualFileSystemPtr(), nullptr, ASTDiags, CI.getFileSystemOpts(), + CI.getHeaderSearchOpts()); if (!AST) return false; @@ -971,9 +972,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, StringRef InputFile = Input.getFile(); std::unique_ptr AST = ASTUnit::LoadFromASTFile( - InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything, nullptr, - Diags, CI.getFileSystemOpts(), CI.getHeaderSearchOpts(), - &CI.getLangOpts()); + InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything, + CI.getVirtualFileSystemPtr(), nullptr, Diags, CI.getFileSystemOpts(), + CI.getHeaderSearchOpts(), &CI.getLangOpts()); if (!AST) return false; diff --git a/clang/tools/c-index-test/core_main.cpp b/clang/tools/c-index-test/core_main.cpp index 100e708feb721..c5dc54b98f3bd 100644 --- a/clang/tools/c-index-test/core_main.cpp +++ b/clang/tools/c-index-test/core_main.cpp @@ -369,12 +369,13 @@ static bool printSourceSymbolsFromModule(StringRef modulePath, HeaderSearchOptions HSOpts; + auto VFS = llvm::vfs::getRealFileSystem(); + auto DiagOpts = std::make_shared(); IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), - *DiagOpts); + CompilerInstance::createDiagnostics(*VFS, *DiagOpts); std::unique_ptr AU = ASTUnit::LoadFromASTFile( - modulePath, *pchRdr, ASTUnit::LoadASTOnly, DiagOpts, Diags, + modulePath, *pchRdr, ASTUnit::LoadASTOnly, VFS, DiagOpts, Diags, FileSystemOpts, HSOpts, /*LangOpts=*/nullptr, /*OnlyLocalDecls=*/true, CaptureDiagsKind::None, /*AllowASTWithCompilerErrors=*/true, diff --git a/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp b/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp index ddb2944e3820b..6d8f86b13fa36 100644 --- a/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp +++ b/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp @@ -157,8 +157,8 @@ static bool HandleAST(StringRef AstPath) { std::unique_ptr Unit = ASTUnit::LoadFromASTFile( AstPath, CI->getPCHContainerOperations()->getRawReader(), - ASTUnit::LoadASTOnly, DiagOpts, DiagEngine, CI->getFileSystemOpts(), - CI->getHeaderSearchOpts()); + ASTUnit::LoadASTOnly, CI->getVirtualFileSystemPtr(), DiagOpts, DiagEngine, + CI->getFileSystemOpts(), CI->getHeaderSearchOpts()); if (!Unit) return false; diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index a3d9340a2db73..ee87cd66b308b 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -4243,13 +4243,14 @@ enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx, FileSystemOptions FileSystemOpts; HeaderSearchOptions HSOpts; + auto VFS = llvm::vfs::getRealFileSystem(); + auto DiagOpts = std::make_shared(); IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), - *DiagOpts); + CompilerInstance::createDiagnostics(*VFS, *DiagOpts); std::unique_ptr AU = ASTUnit::LoadFromASTFile( ast_filename, CXXIdx->getPCHContainerOperations()->getRawReader(), - ASTUnit::LoadEverything, DiagOpts, Diags, FileSystemOpts, HSOpts, + ASTUnit::LoadEverything, VFS, DiagOpts, Diags, FileSystemOpts, HSOpts, /*LangOpts=*/nullptr, CXXIdx->getOnlyLocalDecls(), CaptureDiagsKind::All, /*AllowASTWithCompilerErrors=*/true, /*UserFilesAreVolatile=*/true); diff --git a/clang/unittests/Frontend/ASTUnitTest.cpp b/clang/unittests/Frontend/ASTUnitTest.cpp index 35cd3de4d3b48..437b233c40be8 100644 --- a/clang/unittests/Frontend/ASTUnitTest.cpp +++ b/clang/unittests/Frontend/ASTUnitTest.cpp @@ -98,7 +98,8 @@ TEST_F(ASTUnitTest, SaveLoadPreservesLangOptionsInPrintingPolicy) { std::unique_ptr AU = ASTUnit::LoadFromASTFile( ASTFileName, PCHContainerOps->getRawReader(), ASTUnit::LoadEverything, - DiagOpts, Diags, FileSystemOptions(), HSOpts); + llvm::vfs::getRealFileSystem(), DiagOpts, Diags, FileSystemOptions(), + HSOpts); if (!AU) FAIL() << "failed to load ASTUnit"; From a2aeddf3dcd04f360225f5068440fc01abf0e414 Mon Sep 17 00:00:00 2001 From: Qiongsi Wu Date: Thu, 16 Oct 2025 20:12:18 -0700 Subject: [PATCH 14/15] Fix a line missing when merging 30633f30894129919050f24fdd1f8f6bc46beae0 --- clang/lib/Frontend/FrontendAction.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index ba4369d1dfeb0..85f35b4476ee9 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -985,6 +985,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. + CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr()); CI.setFileManager(AST->getFileManagerPtr()); CI.setSourceManager(AST->getSourceManagerPtr()); CI.setPreprocessor(AST->getPreprocessorPtr()); From a5d76b3c98df3e86b8c3409da8f8276fb5476677 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Wed, 22 Oct 2025 12:48:31 -0700 Subject: [PATCH 15/15] [clang][deps] Fix a use-after-free from expanding response files (#164676) In 436861645247 we accidentally moved uses of command-line args saved into a bump pointer allocator during response file expansion out of scope of the allocator. Also, the test that should have caught this (at least with asan) was not working correctly because clang-scan-deps was expanding response files itself during argument adjustment rather than the underlying scanner library. rdar://162720059 (cherry picked from commit 3e6f696af78b509351ce58dda2bcba2f729334cb) --- .../DependencyScannerImpl.cpp | 4 ++-- .../DependencyScannerImpl.h | 3 ++- .../DependencyScanningWorker.cpp | 6 +++-- clang/test/ClangScanDeps/response-file.c | 6 +++-- clang/tools/clang-scan-deps/ClangScanDeps.cpp | 24 ++++++++++++------- clang/tools/clang-scan-deps/Opts.td | 2 ++ 6 files changed, 30 insertions(+), 15 deletions(-) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp index cee4075e98e07..5bd206626fac3 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp @@ -508,7 +508,8 @@ DignosticsEngineWithDiagOpts::DignosticsEngineWithDiagOpts( std::pair, std::unique_ptr> buildCompilation(ArrayRef ArgStrs, DiagnosticsEngine &Diags, - IntrusiveRefCntPtr FS) { + IntrusiveRefCntPtr FS, + llvm::BumpPtrAllocator &Alloc) { SmallVector Argv; Argv.reserve(ArgStrs.size()); for (const std::string &Arg : ArgStrs) @@ -519,7 +520,6 @@ buildCompilation(ArrayRef ArgStrs, DiagnosticsEngine &Diags, "clang LLVM compiler", FS); Driver->setTitle("clang_based_tool"); - llvm::BumpPtrAllocator Alloc; bool CLMode = driver::IsClangCL( driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1))); diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h index 0093df7ed6bf1..8e5df7b92d404 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h +++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h @@ -114,7 +114,8 @@ struct TextDiagnosticsPrinterWithOutput { std::pair, std::unique_ptr> buildCompilation(ArrayRef ArgStrs, DiagnosticsEngine &Diags, - IntrusiveRefCntPtr FS); + IntrusiveRefCntPtr FS, + llvm::BumpPtrAllocator &Alloc); std::unique_ptr createCompilerInvocation(ArrayRef CommandLine, diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 72e2c43d53b93..ac5fff1d8ecb7 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -92,8 +92,10 @@ static bool forEachDriverJob( IntrusiveRefCntPtr FS, llvm::function_ref Callback) { // Compilation holds a non-owning a reference to the Driver, hence we need to - // keep the Driver alive when we use Compilation. - auto [Driver, Compilation] = buildCompilation(ArgStrs, Diags, FS); + // keep the Driver alive when we use Compilation. Arguments to commands may be + // owned by Alloc when expanded from response files. + llvm::BumpPtrAllocator Alloc; + auto [Driver, Compilation] = buildCompilation(ArgStrs, Diags, FS, Alloc); if (!Compilation) return false; for (const driver::Command &Job : Compilation->getJobs()) { diff --git a/clang/test/ClangScanDeps/response-file.c b/clang/test/ClangScanDeps/response-file.c index c08105c127202..f905438e86af6 100644 --- a/clang/test/ClangScanDeps/response-file.c +++ b/clang/test/ClangScanDeps/response-file.c @@ -1,10 +1,12 @@ -// Check that the scanner can handle a response file input. +// Check that the scanner can handle a response file input. Uses -verbatim-args +// to ensure response files are expanded by the scanner library and not the +// argumeent adjuster in clang-scan-deps. // RUN: rm -rf %t // RUN: split-file %s %t // RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json -// RUN: clang-scan-deps -format experimental-full -compilation-database %t/cdb.json > %t/deps.json +// RUN: clang-scan-deps -verbatim-args -format experimental-full -compilation-database %t/cdb.json > %t/deps.json // RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index d2791565775ba..2b32424fe5e89 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -121,6 +121,7 @@ static constexpr bool DoRoundTripDefault = false; #endif static bool RoundTripArgs = DoRoundTripDefault; +static bool VerbatimArgs = false; static void ParseArgs(int argc, char **argv) { ScanDepsOptTable Tbl; @@ -277,6 +278,8 @@ static void ParseArgs(int argc, char **argv) { RoundTripArgs = Args.hasArg(OPT_round_trip_args); + VerbatimArgs = Args.hasArg(OPT_verbatim_args); + if (const llvm::opt::Arg *A = Args.getLastArgNoClaim(OPT_DASH_DASH)) CommandLine.assign(A->getValues().begin(), A->getValues().end()); } @@ -1167,14 +1170,16 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { llvm::cl::PrintOptionValues(); - // Expand response files in advance, so that we can "see" all the arguments - // when adjusting below. - Compilations = expandResponseFiles(std::move(Compilations), - llvm::vfs::getRealFileSystem()); + if (!VerbatimArgs) { + // Expand response files in advance, so that we can "see" all the arguments + // when adjusting below. + Compilations = expandResponseFiles(std::move(Compilations), + llvm::vfs::getRealFileSystem()); - Compilations = inferTargetAndDriverMode(std::move(Compilations)); + Compilations = inferTargetAndDriverMode(std::move(Compilations)); - Compilations = inferToolLocation(std::move(Compilations)); + Compilations = inferToolLocation(std::move(Compilations)); + } // The command options are rewritten to run Clang in preprocessor only mode. auto AdjustingCompilations = @@ -1182,7 +1187,7 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { std::move(Compilations)); ResourceDirectoryCache ResourceDirCache; - AdjustingCompilations->appendArgumentsAdjuster( + auto ArgsAdjuster = [&ResourceDirCache](const tooling::CommandLineArguments &Args, StringRef FileName) { if (EmitCASCompDB) @@ -1255,7 +1260,10 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { AdjustedArgs.push_back("-fdepscan-prefix-map=" + std::string(Map)); } return AdjustedArgs; - }); + }; + + if (!VerbatimArgs) + AdjustingCompilations->appendArgumentsAdjuster(ArgsAdjuster); SharedStream Errs(llvm::errs()); diff --git a/clang/tools/clang-scan-deps/Opts.td b/clang/tools/clang-scan-deps/Opts.td index 4f12a697fc3b9..efcf950780f73 100644 --- a/clang/tools/clang-scan-deps/Opts.td +++ b/clang/tools/clang-scan-deps/Opts.td @@ -59,4 +59,6 @@ def verbose : F<"v", "Use verbose output">; def round_trip_args : F<"round-trip-args", "verify that command-line arguments are canonical by parsing and re-serializing">; +def verbatim_args : F<"verbatim-args", "Pass commands to the scanner verbatim without adjustments">; + def DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>;