diff options
author | Cyndy Ishida <cyndy_ishida@apple.com> | 2025-04-08 15:48:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-08 15:48:25 -0700 |
commit | 1365b5b1ad5d09a738dbe97b5a72902186e24d80 (patch) | |
tree | 741897b9e1bc5669b1a2c585e756030d5a597e61 /clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp | |
parent | b712068af26643d5fcbfd148b2084554b4e61650 (diff) | |
download | llvm-1365b5b1ad5d09a738dbe97b5a72902186e24d80.zip llvm-1365b5b1ad5d09a738dbe97b5a72902186e24d80.tar.gz llvm-1365b5b1ad5d09a738dbe97b5a72902186e24d80.tar.bz2 |
[clang][DependencyScanning] Track dependencies from prebuilt modules to determine IsInStableDir (#132237)
When a module is being scanned, it can depend on modules that have
already been built from a pch dependency. When this happens, the pcm
files are reused for the module dependencies. When this is the case,
check if input files recorded from the PCMs come from the provided
stable directories transitively since the scanner will not have access
to the full set of file dependencies from prebuilt modules.
Diffstat (limited to 'clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp')
-rw-r--r-- | clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp | 100 |
1 files changed, 58 insertions, 42 deletions
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index 364f1565..ebd392f 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -41,10 +41,20 @@ const std::vector<std::string> &ModuleDeps::getBuildArguments() const { return std::get<std::vector<std::string>>(BuildInfo); } +void PrebuiltModuleASTAttrs::updateDependentsNotInStableDirs( + PrebuiltModulesAttrsMap &PrebuiltModulesMap) { + setInStableDir(); + for (const auto Dep : ModuleFileDependents) { + if (!PrebuiltModulesMap[Dep].isInStableDir()) + return; + PrebuiltModulesMap[Dep].updateDependentsNotInStableDirs(PrebuiltModulesMap); + } +} + static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts, ASTReader &Reader, const serialization::ModuleFile &MF, - const PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap, + const PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, ScanningOptimizations OptimizeArgs) { if (any(OptimizeArgs & ScanningOptimizations::HeaderSearch)) { // Only preserve search paths that were used during the dependency scan. @@ -89,11 +99,13 @@ optimizeHeaderSearchOpts(HeaderSearchOptions &Opts, ASTReader &Reader, } else { // This is not an implicitly built module, so it may have different // VFS options. Fall back to a string comparison instead. - auto VFSMap = PrebuiltModuleVFSMap.find(MF->FileName); - if (VFSMap == PrebuiltModuleVFSMap.end()) + auto PrebuiltModulePropIt = + PrebuiltModulesASTMap.find(MF->FileName); + if (PrebuiltModulePropIt == PrebuiltModulesASTMap.end()) return; for (std::size_t I = 0, E = VFSOverlayFiles.size(); I != E; ++I) { - if (VFSMap->second.contains(VFSOverlayFiles[I])) + if (PrebuiltModulePropIt->second.getVFS().contains( + VFSOverlayFiles[I])) VFSUsage[I] = true; } } @@ -159,32 +171,6 @@ static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) { } } -/// Check a subset of invocation options to determine whether the current -/// context can safely be considered as stable. -static bool areOptionsInStableDir(CowCompilerInvocation &BuildInvocation, - const ArrayRef<StringRef> StableDirs) { - const auto &HSOpts = BuildInvocation.getHeaderSearchOpts(); - assert(isPathInStableDir(StableDirs, HSOpts.Sysroot) && - "Sysroots differ between module dependencies and current TU"); - - assert(isPathInStableDir(StableDirs, HSOpts.ResourceDir) && - "ResourceDirs differ between module dependencies and current TU"); - - for (const auto &Entry : HSOpts.UserEntries) { - if (!Entry.IgnoreSysRoot) - continue; - if (!isPathInStableDir(StableDirs, Entry.Path)) - return false; - } - - for (const auto &SysPrefix : HSOpts.SystemHeaderPrefixes) { - if (!isPathInStableDir(StableDirs, SysPrefix.Prefix)) - return false; - } - - return true; -} - static std::vector<std::string> splitString(std::string S, char Separator) { SmallVector<StringRef> Segments; StringRef(S).split(Segments, Separator, /*MaxSplit=*/-1, /*KeepEmpty=*/false); @@ -242,11 +228,14 @@ void dependencies::resetBenignCodeGenOptions(frontend::ActionKind ProgramAction, bool dependencies::isPathInStableDir(const ArrayRef<StringRef> Directories, const StringRef Input) { + using namespace llvm::sys; + + if (!path::is_absolute(Input)) + return false; + auto PathStartsWith = [](StringRef Prefix, StringRef Path) { - auto PrefixIt = llvm::sys::path::begin(Prefix), - PrefixEnd = llvm::sys::path::end(Prefix); - for (auto PathIt = llvm::sys::path::begin(Path), - PathEnd = llvm::sys::path::end(Path); + auto PrefixIt = path::begin(Prefix), PrefixEnd = path::end(Prefix); + for (auto PathIt = path::begin(Path), PathEnd = path::end(Path); PrefixIt != PrefixEnd && PathIt != PathEnd; ++PrefixIt, ++PathIt) { if (*PrefixIt != *PathIt) return false; @@ -259,6 +248,29 @@ bool dependencies::isPathInStableDir(const ArrayRef<StringRef> Directories, }); } +bool dependencies::areOptionsInStableDir(const ArrayRef<StringRef> Directories, + const HeaderSearchOptions &HSOpts) { + assert(isPathInStableDir(Directories, HSOpts.Sysroot) && + "Sysroots differ between module dependencies and current TU"); + + assert(isPathInStableDir(Directories, HSOpts.ResourceDir) && + "ResourceDirs differ between module dependencies and current TU"); + + for (const auto &Entry : HSOpts.UserEntries) { + if (!Entry.IgnoreSysRoot) + continue; + if (!isPathInStableDir(Directories, Entry.Path)) + return false; + } + + for (const auto &SysPrefix : HSOpts.SystemHeaderPrefixes) { + if (!isPathInStableDir(Directories, SysPrefix.Prefix)) + return false; + } + + return true; +} + static CowCompilerInvocation makeCommonInvocationForModuleBuild(CompilerInvocation CI) { CI.resetNonModularOptions(); @@ -827,7 +839,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { ScanningOptimizations::VFS))) optimizeHeaderSearchOpts(BuildInvocation.getMutHeaderSearchOpts(), *MDC.ScanInstance.getASTReader(), *MF, - MDC.PrebuiltModuleVFSMap, + MDC.PrebuiltModulesASTMap, MDC.Service.getOptimizeArgs()); if (any(MDC.Service.getOptimizeArgs() & @@ -851,7 +863,8 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { // Check provided input paths from the invocation for determining // IsInStableDirectories. if (MD.IsInStableDirectories) - MD.IsInStableDirectories = areOptionsInStableDir(CI, StableDirs); + MD.IsInStableDirectories = + areOptionsInStableDir(StableDirs, CI.getHeaderSearchOpts()); MDC.associateWithContextHash(CI, IgnoreCWD, MD); @@ -896,10 +909,13 @@ void ModuleDepCollectorPP::addModulePrebuiltDeps( if (MDC.isPrebuiltModule(Import->getTopLevelModule())) if (SeenSubmodules.insert(Import->getTopLevelModule()).second) { MD.PrebuiltModuleDeps.emplace_back(Import->getTopLevelModule()); - // Conservatively consider the module as not coming from stable - // directories, as transitive dependencies from the prebuilt module - // have not been determined. - MD.IsInStableDirectories = false; + if (MD.IsInStableDirectories) { + auto PrebuiltModulePropIt = MDC.PrebuiltModulesASTMap.find( + MD.PrebuiltModuleDeps.back().PCMFile); + MD.IsInStableDirectories = + (PrebuiltModulePropIt != MDC.PrebuiltModulesASTMap.end()) && + PrebuiltModulePropIt->second.isInStableDir(); + } } } @@ -962,10 +978,10 @@ ModuleDepCollector::ModuleDepCollector( std::unique_ptr<DependencyOutputOptions> Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, DependencyActionController &Controller, CompilerInvocation OriginalCI, - PrebuiltModuleVFSMapT PrebuiltModuleVFSMap) + const PrebuiltModulesAttrsMap PrebuiltModulesASTMap) : Service(Service), ScanInstance(ScanInstance), Consumer(C), Controller(Controller), - PrebuiltModuleVFSMap(std::move(PrebuiltModuleVFSMap)), + PrebuiltModulesASTMap(std::move(PrebuiltModulesASTMap)), Opts(std::move(Opts)), CommonInvocation( makeCommonInvocationForModuleBuild(std::move(OriginalCI))) {} |