Author: Jan Svoboda Date: 2026-02-13T21:40:14Z New Revision: a38584e0afca6c3f3099e7ecc56a454f3a58db89
URL: https://github.com/llvm/llvm-project/commit/a38584e0afca6c3f3099e7ecc56a454f3a58db89 DIFF: https://github.com/llvm/llvm-project/commit/a38584e0afca6c3f3099e7ecc56a454f3a58db89.diff LOG: [clang][deps] Extract service config into a struct (#181405) Adding new configuration knobs in the scanner is fairly painful now, especially with a diverging downstream. This patch extracts what was previously passed into the service constructor into a struct. This encourages one knob customization per line, reduces difficult merge conflicts, `/*ArgName=*/`-style comments with copy-pasted defaults, etc. Added: Modified: clang-tools-extra/clangd/ScanningProjectModules.cpp clang/include/clang/DependencyScanning/DependencyScanningService.h clang/lib/DependencyScanning/DependencyScannerImpl.cpp clang/lib/DependencyScanning/DependencyScanningService.cpp clang/lib/DependencyScanning/DependencyScanningWorker.cpp clang/lib/DependencyScanning/ModuleDepCollector.cpp clang/tools/clang-scan-deps/ClangScanDeps.cpp clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp clang/unittests/Tooling/DependencyScannerTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/ScanningProjectModules.cpp b/clang-tools-extra/clangd/ScanningProjectModules.cpp index 860ce377be532..e2d710e3794d4 100644 --- a/clang-tools-extra/clangd/ScanningProjectModules.cpp +++ b/clang-tools-extra/clangd/ScanningProjectModules.cpp @@ -35,9 +35,12 @@ class ModuleDependencyScanner { ModuleDependencyScanner( std::shared_ptr<const clang::tooling::CompilationDatabase> CDB, const ThreadsafeFS &TFS) - : CDB(CDB), TFS(TFS), - Service(dependencies::ScanningMode::CanonicalPreprocessing, - dependencies::ScanningOutputFormat::P1689) {} + : CDB(CDB), TFS(TFS), Service([] { + dependencies::DependencyScanningServiceOptions Opts; + Opts.Mode = dependencies::ScanningMode::CanonicalPreprocessing; + Opts.Format = dependencies::ScanningOutputFormat::P1689; + return Opts; + }()) {} /// The scanned modules dependency information for a specific source file. struct ModuleDependencyInfo { diff --git a/clang/include/clang/DependencyScanning/DependencyScanningService.h b/clang/include/clang/DependencyScanning/DependencyScanningService.h index 9e8041836bc26..509b6a579ecb4 100644 --- a/clang/include/clang/DependencyScanning/DependencyScanningService.h +++ b/clang/include/clang/DependencyScanning/DependencyScanningService.h @@ -12,7 +12,6 @@ #include "clang/DependencyScanning/DependencyScanningFilesystem.h" #include "clang/DependencyScanning/InProcessModuleCache.h" #include "llvm/ADT/BitmaskEnum.h" -#include "llvm/Support/Chrono.h" namespace clang { namespace dependencies { @@ -77,29 +76,34 @@ enum class ScanningOptimizations { #undef DSS_LAST_BITMASK_ENUM +/// The configuration knobs for the dependency scanning service. +struct DependencyScanningServiceOptions { + DependencyScanningServiceOptions(); + + /// Whether to use optimized dependency directive scan or full preprocessing. + ScanningMode Mode = ScanningMode::DependencyDirectivesScan; + /// What output format are we expected to produce. + ScanningOutputFormat Format = ScanningOutputFormat::Full; + /// How to optimize resulting explicit module command lines. + ScanningOptimizations OptimizeArgs = ScanningOptimizations::Default; + /// Whether the resulting command lines should load explicit PCMs eagerly. + bool EagerLoadModules = false; + /// Whether to trace VFS accesses during the scan. + bool TraceVFS = false; + /// Whether to scan modules asynchronously. + bool AsyncScanModules = false; + /// The build session timestamp for validate-once-per-build-session logic. + std::time_t BuildSessionTimestamp; // = std::chrono::system_clock::now(); +}; + /// The dependency scanning service contains shared configuration and state that /// is used by the individual dependency scanning workers. class DependencyScanningService { public: - DependencyScanningService( - ScanningMode Mode, ScanningOutputFormat Format, - ScanningOptimizations OptimizeArgs = ScanningOptimizations::Default, - bool EagerLoadModules = false, bool TraceVFS = false, - bool AsyncScanModules = false, - std::time_t BuildSessionTimestamp = - llvm::sys::toTimeT(std::chrono::system_clock::now())); - - ScanningMode getMode() const { return Mode; } - - ScanningOutputFormat getFormat() const { return Format; } + explicit DependencyScanningService(DependencyScanningServiceOptions Opts) + : Opts(std::move(Opts)) {} - ScanningOptimizations getOptimizeArgs() const { return OptimizeArgs; } - - bool shouldEagerLoadModules() const { return EagerLoadModules; } - - bool shouldTraceVFS() const { return TraceVFS; } - - bool shouldScanModulesAsynchronously() const { return AsyncScanModules; } + const DependencyScanningServiceOptions &getOpts() const { return Opts; } DependencyScanningFilesystemSharedCache &getSharedCache() { return SharedCache; @@ -107,25 +111,13 @@ class DependencyScanningService { ModuleCacheEntries &getModuleCacheEntries() { return ModCacheEntries; } - std::time_t getBuildSessionTimestamp() const { return BuildSessionTimestamp; } - private: - const ScanningMode Mode; - const ScanningOutputFormat Format; - /// Whether to optimize the modules' command-line arguments. - const ScanningOptimizations OptimizeArgs; - /// Whether to set up command-lines to load PCM files eagerly. - const bool EagerLoadModules; - /// Whether to trace VFS accesses. - const bool TraceVFS; - /// Whether to scan modules asynchronously. - const bool AsyncScanModules; + /// The options customizing dependency scanning behavior. + DependencyScanningServiceOptions Opts; /// The global file system cache. DependencyScanningFilesystemSharedCache SharedCache; /// The global module cache entries. ModuleCacheEntries ModCacheEntries; - /// The build session timestamp. - std::time_t BuildSessionTimestamp; }; } // end namespace dependencies diff --git a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp index cafd3eb976312..28fa2571a24dc 100644 --- a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp @@ -414,7 +414,7 @@ void dependencies::initializeScanCompilerInstance( ScanInstance.createSourceManager(); // Use DepFS for getting the dependency directives if requested to do so. - if (Service.getMode() == ScanningMode::DependencyDirectivesScan) { + if (Service.getOpts().Mode == ScanningMode::DependencyDirectivesScan) { DepFS->resetBypassedPathPrefix(); SmallString<256> ModulesCachePath; normalizeModuleCachePath(ScanInstance.getFileManager(), @@ -442,7 +442,7 @@ createScanCompilerInvocation(const CompilerInvocation &Invocation, if (ScanInvocation->getHeaderSearchOpts().ModulesValidateOncePerBuildSession) ScanInvocation->getHeaderSearchOpts().BuildSessionTimestamp = - Service.getBuildSessionTimestamp(); + Service.getOpts().BuildSessionTimestamp; ScanInvocation->getFrontendOpts().DisableFree = false; ScanInvocation->getFrontendOpts().GenerateGlobalModuleIndex = false; @@ -454,7 +454,7 @@ createScanCompilerInvocation(const CompilerInvocation &Invocation, ScanInvocation->getFrontendOpts().ModulesShareFileManager = true; ScanInvocation->getHeaderSearchOpts().ModuleFormat = "raw"; ScanInvocation->getHeaderSearchOpts().ModulesIncludeVFSUsage = - any(Service.getOptimizeArgs() & ScanningOptimizations::VFS); + any(Service.getOpts().OptimizeArgs & ScanningOptimizations::VFS); // Consider diff erent header search and diagnostic options to create // diff erent modules. This avoids the unsound aliasing of module PCMs. @@ -536,7 +536,7 @@ dependencies::initializeScanInstanceDependencyCollector( PrebuiltModulesAttrsMap PrebuiltModulesASTMap, llvm::SmallVector<StringRef> &StableDirs) { std::shared_ptr<ModuleDepCollector> MDC; - switch (Service.getFormat()) { + switch (Service.getOpts().Format) { case ScanningOutputFormat::Make: ScanInstance.addDependencyCollector( std::make_shared<DependencyConsumerForwarder>( @@ -689,7 +689,7 @@ bool DependencyScanningAction::runInvocation( DiagnosticConsumer *DiagConsumer) { // Making sure that we canonicalize the defines early to avoid unnecessary // variants in both the scanner and in the resulting explicit command lines. - if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros)) + if (any(Service.getOpts().OptimizeArgs & ScanningOptimizations::Macros)) canonicalizeDefines(OriginalInvocation->getPreprocessorOpts()); if (Scanned) { @@ -711,7 +711,7 @@ bool DependencyScanningAction::runInvocation( createScanCompilerInvocation(*OriginalInvocation, Service); // Quickly discovers and compiles modules for the real scan below. - if (Service.shouldScanModulesAsynchronously()) { + if (Service.getOpts().AsyncScanModules) { auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries()); auto ScanInstanceStorage = std::make_unique<CompilerInstance>( std::make_shared<CompilerInvocation>(*ScanInvocation), PCHContainerOps, @@ -761,7 +761,7 @@ bool DependencyScanningAction::runInvocation( std::unique_ptr<FrontendAction> Action; - if (Service.getFormat() == ScanningOutputFormat::P1689) + if (Service.getOpts().Format == ScanningOutputFormat::P1689) Action = std::make_unique<PreprocessOnlyAction>(); else Action = std::make_unique<ReadPCHAndPreprocessAction>(); @@ -809,7 +809,8 @@ bool CompilerInstanceWithContext::initialize( return false; } - if (any(Worker.Service.getOptimizeArgs() & ScanningOptimizations::Macros)) + if (any(Worker.Service.getOpts().OptimizeArgs & + ScanningOptimizations::Macros)) canonicalizeDefines(OriginalInvocation->getPreprocessorOpts()); // Create the CompilerInstance. diff --git a/clang/lib/DependencyScanning/DependencyScanningService.cpp b/clang/lib/DependencyScanning/DependencyScanningService.cpp index 9224de39b40cc..3651b9b20a70f 100644 --- a/clang/lib/DependencyScanning/DependencyScanningService.cpp +++ b/clang/lib/DependencyScanning/DependencyScanningService.cpp @@ -8,14 +8,11 @@ #include "clang/DependencyScanning/DependencyScanningService.h" +#include "llvm/Support/Chrono.h" + using namespace clang; using namespace dependencies; -DependencyScanningService::DependencyScanningService( - ScanningMode Mode, ScanningOutputFormat Format, - ScanningOptimizations OptimizeArgs, bool EagerLoadModules, bool TraceVFS, - bool AsyncScanModules, std::time_t BuildSessionTimestamp) - : Mode(Mode), Format(Format), OptimizeArgs(OptimizeArgs), - EagerLoadModules(EagerLoadModules), TraceVFS(TraceVFS), - AsyncScanModules(AsyncScanModules), - BuildSessionTimestamp(BuildSessionTimestamp) {} +DependencyScanningServiceOptions::DependencyScanningServiceOptions() + : BuildSessionTimestamp( + llvm::sys::toTimeT(std::chrono::system_clock::now())) {} diff --git a/clang/lib/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/DependencyScanning/DependencyScanningWorker.cpp index 25c8a092d38c2..7d0c93138d78c 100644 --- a/clang/lib/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/DependencyScanning/DependencyScanningWorker.cpp @@ -30,7 +30,7 @@ DependencyScanningWorker::DependencyScanningWorker( // The scanner itself writes only raw ast files. PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>()); - if (Service.shouldTraceVFS()) + if (Service.getOpts().TraceVFS) BaseFS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>( std::move(BaseFS)); diff --git a/clang/lib/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/DependencyScanning/ModuleDepCollector.cpp index bbdcd7d8e2b44..46a0f79bfd38e 100644 --- a/clang/lib/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/DependencyScanning/ModuleDepCollector.cpp @@ -334,7 +334,7 @@ ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs( // TODO: Verify this works fine when modulemap for module A is eagerly // loaded from A.pcm, and module map passed on the command line contains // definition of a submodule: "explicit module A.Private { ... }". - if (Service.shouldEagerLoadModules() && + if (Service.getOpts().EagerLoadModules && DepModuleMapFiles.contains(*ModuleMapEntry)) continue; @@ -385,7 +385,7 @@ llvm::DenseSet<const FileEntry *> ModuleDepCollector::collectModuleMapFiles( void ModuleDepCollector::addModuleMapFiles( CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const { - if (Service.shouldEagerLoadModules()) + if (Service.getOpts().EagerLoadModules) return; // Only pcm is needed for eager load. for (const ModuleID &MID : ClangModuleDeps) { @@ -402,7 +402,7 @@ void ModuleDepCollector::addModuleFiles( std::string PCMPath = Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile); - if (Service.shouldEagerLoadModules()) + if (Service.getOpts().EagerLoadModules) CI.getFrontendOpts().ModuleFiles.push_back(std::move(PCMPath)); else CI.getHeaderSearchOpts().PrebuiltModuleFiles.insert( @@ -417,7 +417,7 @@ void ModuleDepCollector::addModuleFiles( std::string PCMPath = Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile); - if (Service.shouldEagerLoadModules()) + if (Service.getOpts().EagerLoadModules) CI.getMutFrontendOpts().ModuleFiles.push_back(std::move(PCMPath)); else CI.getMutHeaderSearchOpts().PrebuiltModuleFiles.insert( @@ -525,7 +525,7 @@ static std::string getModuleContextHash(const ModuleDeps &MD, void ModuleDepCollector::associateWithContextHash( const CowCompilerInvocation &CI, bool IgnoreCWD, ModuleDeps &Deps) { Deps.ID.ContextHash = - getModuleContextHash(Deps, CI, Service.shouldEagerLoadModules(), + getModuleContextHash(Deps, CI, Service.getOpts().EagerLoadModules, IgnoreCWD, ScanInstance.getVirtualFileSystem()); bool Inserted = ModuleDepsByID.insert({Deps.ID, &Deps}).second; (void)Inserted; @@ -752,21 +752,21 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { CowCompilerInvocation CI = MDC.getInvocationAdjustedForModuleBuildWithoutOutputs( MD, [&](CowCompilerInvocation &BuildInvocation) { - if (any(MDC.Service.getOptimizeArgs() & + if (any(MDC.Service.getOpts().OptimizeArgs & (ScanningOptimizations::HeaderSearch | ScanningOptimizations::VFS))) optimizeHeaderSearchOpts(BuildInvocation.getMutHeaderSearchOpts(), *MDC.ScanInstance.getASTReader(), *MF, MDC.PrebuiltModulesASTMap, - MDC.Service.getOptimizeArgs()); + MDC.Service.getOpts().OptimizeArgs); - if (any(MDC.Service.getOptimizeArgs() & + if (any(MDC.Service.getOpts().OptimizeArgs & ScanningOptimizations::SystemWarnings)) optimizeDiagnosticOpts( BuildInvocation.getMutDiagnosticOpts(), BuildInvocation.getFrontendOpts().IsSystemModule); - IgnoreCWD = any(MDC.Service.getOptimizeArgs() & + IgnoreCWD = any(MDC.Service.getOpts().OptimizeArgs & ScanningOptimizations::IgnoreCWD) && isSafeToIgnoreCWD(BuildInvocation); if (IgnoreCWD) { @@ -960,7 +960,7 @@ static StringRef makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path, } void ModuleDepCollector::addFileDep(StringRef Path) { - if (Service.getFormat() == ScanningOutputFormat::P1689) { + if (Service.getOpts().Format == ScanningOutputFormat::P1689) { // Within P1689 format, we don't want all the paths to be absolute path // since it may violate the traditional make style dependencies info. FileDeps.emplace_back(Path); diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index efa9bff019a60..30fb8d47f8d5d 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -1138,9 +1138,14 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { }); }; - DependencyScanningService Service(ScanMode, Format, OptimizeArgs, - EagerLoadModules, /*TraceVFS=*/Verbose, - AsyncScanModules); + DependencyScanningServiceOptions Opts; + Opts.Mode = ScanMode; + Opts.Format = Format; + Opts.OptimizeArgs = OptimizeArgs; + Opts.EagerLoadModules = EagerLoadModules; + Opts.TraceVFS = Verbose; + Opts.AsyncScanModules = AsyncScanModules; + DependencyScanningService Service(std::move(Opts)); llvm::Timer T; T.startTimer(); diff --git a/clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp b/clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp index 872c7effde3d3..ca51fc3f6fbcb 100644 --- a/clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp +++ b/clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp @@ -31,8 +31,9 @@ TEST(DependencyScanner, ScanDepsWithDiagConsumer) { llvm::MemoryBuffer::getMemBuffer("#include \"header.h\"\n")); VFS->addFile(AsmPath, 0, llvm::MemoryBuffer::getMemBuffer("")); - DependencyScanningService Service(ScanningMode::DependencyDirectivesScan, - ScanningOutputFormat::Make); + DependencyScanningServiceOptions Opts; + Opts.Format = ScanningOutputFormat::Make; + DependencyScanningService Service(std::move(Opts)); DependencyScanningWorker Worker(Service, VFS); llvm::DenseSet<ModuleID> AlreadySeen; diff --git a/clang/unittests/Tooling/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScannerTest.cpp index 42d1a7b242aa9..a764a206c4670 100644 --- a/clang/unittests/Tooling/DependencyScannerTest.cpp +++ b/clang/unittests/Tooling/DependencyScannerTest.cpp @@ -228,8 +228,9 @@ TEST(DependencyScanner, ScanDepsWithFS) { VFS->addFile(TestPath, 0, llvm::MemoryBuffer::getMemBuffer("#include \"header.h\"\n")); - DependencyScanningService Service(ScanningMode::DependencyDirectivesScan, - ScanningOutputFormat::Make); + DependencyScanningServiceOptions Opts; + Opts.Format = ScanningOutputFormat::Make; + DependencyScanningService Service(std::move(Opts)); DependencyScanningTool ScanTool(Service, VFS); TextDiagnosticBuffer DiagConsumer; @@ -285,8 +286,9 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) { auto InterceptFS = llvm::makeIntrusiveRefCnt<InterceptorFS>(VFS); - DependencyScanningService Service(ScanningMode::DependencyDirectivesScan, - ScanningOutputFormat::Make); + DependencyScanningServiceOptions Opts; + Opts.Format = ScanningOutputFormat::Make; + DependencyScanningService Service(std::move(Opts)); DependencyScanningTool ScanTool(Service, InterceptFS); // This will fail with "fatal error: module 'Foo' not found" but it doesn't _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
