1 //===- ModuleDepCollector.cpp - Callbacks to collect deps -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" 10 11 #include "clang/Basic/MakeSupport.h" 12 #include "clang/Frontend/CompilerInstance.h" 13 #include "clang/Lex/Preprocessor.h" 14 #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/Support/BLAKE3.h" 17 #include <optional> 18 19 using namespace clang; 20 using namespace tooling; 21 using namespace dependencies; 22 23 void ModuleDeps::forEachFileDep(llvm::function_ref<void(StringRef)> Cb) const { 24 SmallString<0> PathBuf; 25 PathBuf.reserve(256); 26 for (StringRef FileDep : FileDeps) { 27 auto ResolvedFileDep = 28 ASTReader::ResolveImportedPath(PathBuf, FileDep, FileDepsBaseDir); 29 Cb(*ResolvedFileDep); 30 } 31 } 32 33 const std::vector<std::string> &ModuleDeps::getBuildArguments() const { 34 // FIXME: this operation is not thread safe and is expected to be called 35 // on a single thread. Otherwise it should be protected with a lock. 36 assert(!std::holds_alternative<std::monostate>(BuildInfo) && 37 "Using uninitialized ModuleDeps"); 38 if (const auto *CI = std::get_if<CowCompilerInvocation>(&BuildInfo)) 39 BuildInfo = CI->getCC1CommandLine(); 40 return std::get<std::vector<std::string>>(BuildInfo); 41 } 42 43 void PrebuiltModuleASTAttrs::updateDependentsNotInStableDirs( 44 PrebuiltModulesAttrsMap &PrebuiltModulesMap) { 45 setInStableDir(); 46 for (const auto Dep : ModuleFileDependents) { 47 if (!PrebuiltModulesMap[Dep].isInStableDir()) 48 return; 49 PrebuiltModulesMap[Dep].updateDependentsNotInStableDirs(PrebuiltModulesMap); 50 } 51 } 52 53 static void 54 optimizeHeaderSearchOpts(HeaderSearchOptions &Opts, ASTReader &Reader, 55 const serialization::ModuleFile &MF, 56 const PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, 57 ScanningOptimizations OptimizeArgs) { 58 if (any(OptimizeArgs & ScanningOptimizations::HeaderSearch)) { 59 // Only preserve search paths that were used during the dependency scan. 60 std::vector<HeaderSearchOptions::Entry> Entries; 61 std::swap(Opts.UserEntries, Entries); 62 63 llvm::BitVector SearchPathUsage(Entries.size()); 64 llvm::DenseSet<const serialization::ModuleFile *> Visited; 65 std::function<void(const serialization::ModuleFile *)> VisitMF = 66 [&](const serialization::ModuleFile *MF) { 67 SearchPathUsage |= MF->SearchPathUsage; 68 Visited.insert(MF); 69 for (const serialization::ModuleFile *Import : MF->Imports) 70 if (!Visited.contains(Import)) 71 VisitMF(Import); 72 }; 73 VisitMF(&MF); 74 75 if (SearchPathUsage.size() != Entries.size()) 76 llvm::report_fatal_error( 77 "Inconsistent search path options between modules detected"); 78 79 for (auto Idx : SearchPathUsage.set_bits()) 80 Opts.UserEntries.push_back(std::move(Entries[Idx])); 81 } 82 if (any(OptimizeArgs & ScanningOptimizations::VFS)) { 83 std::vector<std::string> VFSOverlayFiles; 84 std::swap(Opts.VFSOverlayFiles, VFSOverlayFiles); 85 86 llvm::BitVector VFSUsage(VFSOverlayFiles.size()); 87 llvm::DenseSet<const serialization::ModuleFile *> Visited; 88 std::function<void(const serialization::ModuleFile *)> VisitMF = 89 [&](const serialization::ModuleFile *MF) { 90 Visited.insert(MF); 91 if (MF->Kind == serialization::MK_ImplicitModule) { 92 VFSUsage |= MF->VFSUsage; 93 // We only need to recurse into implicit modules. Other module types 94 // will have the correct set of VFSs for anything they depend on. 95 for (const serialization::ModuleFile *Import : MF->Imports) 96 if (!Visited.contains(Import)) 97 VisitMF(Import); 98 } else { 99 // This is not an implicitly built module, so it may have different 100 // VFS options. Fall back to a string comparison instead. 101 auto PrebuiltModulePropIt = 102 PrebuiltModulesASTMap.find(MF->FileName); 103 if (PrebuiltModulePropIt == PrebuiltModulesASTMap.end()) 104 return; 105 for (std::size_t I = 0, E = VFSOverlayFiles.size(); I != E; ++I) { 106 if (PrebuiltModulePropIt->second.getVFS().contains( 107 VFSOverlayFiles[I])) 108 VFSUsage[I] = true; 109 } 110 } 111 }; 112 VisitMF(&MF); 113 114 if (VFSUsage.size() != VFSOverlayFiles.size()) 115 llvm::report_fatal_error( 116 "Inconsistent -ivfsoverlay options between modules detected"); 117 118 for (auto Idx : VFSUsage.set_bits()) 119 Opts.VFSOverlayFiles.push_back(std::move(VFSOverlayFiles[Idx])); 120 } 121 } 122 123 static void optimizeDiagnosticOpts(DiagnosticOptions &Opts, 124 bool IsSystemModule) { 125 // If this is not a system module or -Wsystem-headers was passed, don't 126 // optimize. 127 if (!IsSystemModule) 128 return; 129 bool Wsystem_headers = false; 130 for (StringRef Opt : Opts.Warnings) { 131 bool isPositive = !Opt.consume_front("no-"); 132 if (Opt == "system-headers") 133 Wsystem_headers = isPositive; 134 } 135 if (Wsystem_headers) 136 return; 137 138 // Remove all warning flags. System modules suppress most, but not all, 139 // warnings. 140 Opts.Warnings.clear(); 141 Opts.UndefPrefixes.clear(); 142 Opts.Remarks.clear(); 143 } 144 145 static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) { 146 BuildInvocation.getMutFileSystemOpts().WorkingDir.clear(); 147 if (BuildInvocation.getCodeGenOpts().DwarfVersion) { 148 // It is necessary to explicitly set the DebugCompilationDir 149 // to a common directory (e.g. root) if IgnoreCWD is true. 150 // When IgnoreCWD is true, the module's content should not 151 // depend on the current working directory. However, if dwarf 152 // information is needed (when CGOpts.DwarfVersion is 153 // non-zero), then CGOpts.DebugCompilationDir must be 154 // populated, because otherwise the current working directory 155 // will be automatically embedded in the dwarf information in 156 // the pcm, contradicting the assumption that it is safe to 157 // ignore the CWD. Thus in such cases, 158 // CGOpts.DebugCompilationDir is explicitly set to a common 159 // directory. 160 // FIXME: It is still excessive to create a copy of 161 // CodeGenOpts for each module. Since we do not modify the 162 // CodeGenOpts otherwise per module, the following code 163 // ends up generating identical CodeGenOpts for each module 164 // with DebugCompilationDir pointing to the root directory. 165 // We can optimize this away by creating a _single_ copy of 166 // CodeGenOpts whose DebugCompilationDir points to the root 167 // directory and reuse it across modules. 168 BuildInvocation.getMutCodeGenOpts().DebugCompilationDir = 169 llvm::sys::path::root_path(CWD); 170 } 171 } 172 173 static std::vector<std::string> splitString(std::string S, char Separator) { 174 SmallVector<StringRef> Segments; 175 StringRef(S).split(Segments, Separator, /*MaxSplit=*/-1, /*KeepEmpty=*/false); 176 std::vector<std::string> Result; 177 Result.reserve(Segments.size()); 178 for (StringRef Segment : Segments) 179 Result.push_back(Segment.str()); 180 return Result; 181 } 182 183 void ModuleDepCollector::addOutputPaths(CowCompilerInvocation &CI, 184 ModuleDeps &Deps) { 185 CI.getMutFrontendOpts().OutputFile = 186 Controller.lookupModuleOutput(Deps, ModuleOutputKind::ModuleFile); 187 if (!CI.getDiagnosticOpts().DiagnosticSerializationFile.empty()) 188 CI.getMutDiagnosticOpts().DiagnosticSerializationFile = 189 Controller.lookupModuleOutput( 190 Deps, ModuleOutputKind::DiagnosticSerializationFile); 191 if (!CI.getDependencyOutputOpts().OutputFile.empty()) { 192 CI.getMutDependencyOutputOpts().OutputFile = 193 Controller.lookupModuleOutput(Deps, ModuleOutputKind::DependencyFile); 194 CI.getMutDependencyOutputOpts().Targets = 195 splitString(Controller.lookupModuleOutput( 196 Deps, ModuleOutputKind::DependencyTargets), 197 '\0'); 198 if (!CI.getDependencyOutputOpts().OutputFile.empty() && 199 CI.getDependencyOutputOpts().Targets.empty()) { 200 // Fallback to -o as dependency target, as in the driver. 201 SmallString<128> Target; 202 quoteMakeTarget(CI.getFrontendOpts().OutputFile, Target); 203 CI.getMutDependencyOutputOpts().Targets.push_back(std::string(Target)); 204 } 205 } 206 } 207 208 void dependencies::resetBenignCodeGenOptions(frontend::ActionKind ProgramAction, 209 const LangOptions &LangOpts, 210 CodeGenOptions &CGOpts) { 211 // TODO: Figure out better way to set options to their default value. 212 if (ProgramAction == frontend::GenerateModule) { 213 CGOpts.MainFileName.clear(); 214 CGOpts.DwarfDebugFlags.clear(); 215 } 216 if (ProgramAction == frontend::GeneratePCH || 217 (ProgramAction == frontend::GenerateModule && !LangOpts.ModulesCodegen)) { 218 CGOpts.DebugCompilationDir.clear(); 219 CGOpts.CoverageCompilationDir.clear(); 220 CGOpts.CoverageDataFile.clear(); 221 CGOpts.CoverageNotesFile.clear(); 222 CGOpts.ProfileInstrumentUsePath.clear(); 223 CGOpts.SampleProfileFile.clear(); 224 CGOpts.ProfileRemappingFile.clear(); 225 } 226 } 227 228 bool dependencies::isPathInStableDir(const ArrayRef<StringRef> Directories, 229 const StringRef Input) { 230 using namespace llvm::sys; 231 232 if (!path::is_absolute(Input)) 233 return false; 234 235 auto PathStartsWith = [](StringRef Prefix, StringRef Path) { 236 auto PrefixIt = path::begin(Prefix), PrefixEnd = path::end(Prefix); 237 for (auto PathIt = path::begin(Path), PathEnd = path::end(Path); 238 PrefixIt != PrefixEnd && PathIt != PathEnd; ++PrefixIt, ++PathIt) { 239 if (*PrefixIt != *PathIt) 240 return false; 241 } 242 return PrefixIt == PrefixEnd; 243 }; 244 245 return any_of(Directories, [&](StringRef Dir) { 246 return !Dir.empty() && PathStartsWith(Dir, Input); 247 }); 248 } 249 250 bool dependencies::areOptionsInStableDir(const ArrayRef<StringRef> Directories, 251 const HeaderSearchOptions &HSOpts) { 252 assert(isPathInStableDir(Directories, HSOpts.Sysroot) && 253 "Sysroots differ between module dependencies and current TU"); 254 255 assert(isPathInStableDir(Directories, HSOpts.ResourceDir) && 256 "ResourceDirs differ between module dependencies and current TU"); 257 258 for (const auto &Entry : HSOpts.UserEntries) { 259 if (!Entry.IgnoreSysRoot) 260 continue; 261 if (!isPathInStableDir(Directories, Entry.Path)) 262 return false; 263 } 264 265 for (const auto &SysPrefix : HSOpts.SystemHeaderPrefixes) { 266 if (!isPathInStableDir(Directories, SysPrefix.Prefix)) 267 return false; 268 } 269 270 return true; 271 } 272 273 static CowCompilerInvocation 274 makeCommonInvocationForModuleBuild(CompilerInvocation CI) { 275 CI.resetNonModularOptions(); 276 CI.clearImplicitModuleBuildOptions(); 277 278 // The scanner takes care to avoid passing non-affecting module maps to the 279 // explicit compiles. No need to do extra work just to find out there are no 280 // module map files to prune. 281 CI.getHeaderSearchOpts().ModulesPruneNonAffectingModuleMaps = false; 282 283 // Remove options incompatible with explicit module build or are likely to 284 // differ between identical modules discovered from different translation 285 // units. 286 CI.getFrontendOpts().Inputs.clear(); 287 CI.getFrontendOpts().OutputFile.clear(); 288 // LLVM options are not going to affect the AST 289 CI.getFrontendOpts().LLVMArgs.clear(); 290 291 resetBenignCodeGenOptions(frontend::GenerateModule, CI.getLangOpts(), 292 CI.getCodeGenOpts()); 293 294 // Map output paths that affect behaviour to "-" so their existence is in the 295 // context hash. The final path will be computed in addOutputPaths. 296 if (!CI.getDiagnosticOpts().DiagnosticSerializationFile.empty()) 297 CI.getDiagnosticOpts().DiagnosticSerializationFile = "-"; 298 if (!CI.getDependencyOutputOpts().OutputFile.empty()) 299 CI.getDependencyOutputOpts().OutputFile = "-"; 300 CI.getDependencyOutputOpts().Targets.clear(); 301 302 CI.getFrontendOpts().ProgramAction = frontend::GenerateModule; 303 CI.getLangOpts().ModuleName.clear(); 304 305 // Remove any macro definitions that are explicitly ignored. 306 if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) { 307 llvm::erase_if( 308 CI.getPreprocessorOpts().Macros, 309 [&CI](const std::pair<std::string, bool> &Def) { 310 StringRef MacroDef = Def.first; 311 return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains( 312 llvm::CachedHashString(MacroDef.split('=').first)); 313 }); 314 // Remove the now unused option. 315 CI.getHeaderSearchOpts().ModulesIgnoreMacros.clear(); 316 } 317 318 return CI; 319 } 320 321 CowCompilerInvocation 322 ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs( 323 const ModuleDeps &Deps, 324 llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const { 325 CowCompilerInvocation CI = CommonInvocation; 326 327 CI.getMutLangOpts().ModuleName = Deps.ID.ModuleName; 328 CI.getMutFrontendOpts().IsSystemModule = Deps.IsSystem; 329 330 // Inputs 331 InputKind ModuleMapInputKind(CI.getFrontendOpts().DashX.getLanguage(), 332 InputKind::Format::ModuleMap); 333 CI.getMutFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile, 334 ModuleMapInputKind); 335 336 auto CurrentModuleMapEntry = 337 ScanInstance.getFileManager().getOptionalFileRef(Deps.ClangModuleMapFile); 338 assert(CurrentModuleMapEntry && "module map file entry not found"); 339 340 // Remove directly passed modulemap files. They will get added back if they 341 // were actually used. 342 CI.getMutFrontendOpts().ModuleMapFiles.clear(); 343 344 auto DepModuleMapFiles = collectModuleMapFiles(Deps.ClangModuleDeps); 345 for (StringRef ModuleMapFile : Deps.ModuleMapFileDeps) { 346 // TODO: Track these as `FileEntryRef` to simplify the equality check below. 347 auto ModuleMapEntry = 348 ScanInstance.getFileManager().getOptionalFileRef(ModuleMapFile); 349 assert(ModuleMapEntry && "module map file entry not found"); 350 351 // Don't report module maps describing eagerly-loaded dependency. This 352 // information will be deserialized from the PCM. 353 // TODO: Verify this works fine when modulemap for module A is eagerly 354 // loaded from A.pcm, and module map passed on the command line contains 355 // definition of a submodule: "explicit module A.Private { ... }". 356 if (Service.shouldEagerLoadModules() && 357 DepModuleMapFiles.contains(*ModuleMapEntry)) 358 continue; 359 360 // Don't report module map file of the current module unless it also 361 // describes a dependency (for symmetry). 362 if (*ModuleMapEntry == *CurrentModuleMapEntry && 363 !DepModuleMapFiles.contains(*ModuleMapEntry)) 364 continue; 365 366 CI.getMutFrontendOpts().ModuleMapFiles.emplace_back(ModuleMapFile); 367 } 368 369 // Report the prebuilt modules this module uses. 370 for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps) 371 CI.getMutFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile); 372 373 // Add module file inputs from dependencies. 374 addModuleFiles(CI, Deps.ClangModuleDeps); 375 376 if (!CI.getDiagnosticOpts().SystemHeaderWarningsModules.empty()) { 377 // Apply -Wsystem-headers-in-module for the current module. 378 if (llvm::is_contained(CI.getDiagnosticOpts().SystemHeaderWarningsModules, 379 Deps.ID.ModuleName)) 380 CI.getMutDiagnosticOpts().Warnings.push_back("system-headers"); 381 // Remove the now unused option(s). 382 CI.getMutDiagnosticOpts().SystemHeaderWarningsModules.clear(); 383 } 384 385 Optimize(CI); 386 387 return CI; 388 } 389 390 llvm::DenseSet<const FileEntry *> ModuleDepCollector::collectModuleMapFiles( 391 ArrayRef<ModuleID> ClangModuleDeps) const { 392 llvm::DenseSet<const FileEntry *> ModuleMapFiles; 393 for (const ModuleID &MID : ClangModuleDeps) { 394 ModuleDeps *MD = ModuleDepsByID.lookup(MID); 395 assert(MD && "Inconsistent dependency info"); 396 // TODO: Track ClangModuleMapFile as `FileEntryRef`. 397 auto FE = ScanInstance.getFileManager().getOptionalFileRef( 398 MD->ClangModuleMapFile); 399 assert(FE && "Missing module map file that was previously found"); 400 ModuleMapFiles.insert(*FE); 401 } 402 return ModuleMapFiles; 403 } 404 405 void ModuleDepCollector::addModuleMapFiles( 406 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const { 407 if (Service.shouldEagerLoadModules()) 408 return; // Only pcm is needed for eager load. 409 410 for (const ModuleID &MID : ClangModuleDeps) { 411 ModuleDeps *MD = ModuleDepsByID.lookup(MID); 412 assert(MD && "Inconsistent dependency info"); 413 CI.getFrontendOpts().ModuleMapFiles.push_back(MD->ClangModuleMapFile); 414 } 415 } 416 417 void ModuleDepCollector::addModuleFiles( 418 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const { 419 for (const ModuleID &MID : ClangModuleDeps) { 420 ModuleDeps *MD = ModuleDepsByID.lookup(MID); 421 std::string PCMPath = 422 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile); 423 424 if (Service.shouldEagerLoadModules()) 425 CI.getFrontendOpts().ModuleFiles.push_back(std::move(PCMPath)); 426 else 427 CI.getHeaderSearchOpts().PrebuiltModuleFiles.insert( 428 {MID.ModuleName, std::move(PCMPath)}); 429 } 430 } 431 432 void ModuleDepCollector::addModuleFiles( 433 CowCompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const { 434 for (const ModuleID &MID : ClangModuleDeps) { 435 ModuleDeps *MD = ModuleDepsByID.lookup(MID); 436 std::string PCMPath = 437 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile); 438 439 if (Service.shouldEagerLoadModules()) 440 CI.getMutFrontendOpts().ModuleFiles.push_back(std::move(PCMPath)); 441 else 442 CI.getMutHeaderSearchOpts().PrebuiltModuleFiles.insert( 443 {MID.ModuleName, std::move(PCMPath)}); 444 } 445 } 446 447 static bool needsModules(FrontendInputFile FIF) { 448 switch (FIF.getKind().getLanguage()) { 449 case Language::Unknown: 450 case Language::Asm: 451 case Language::LLVM_IR: 452 return false; 453 default: 454 return true; 455 } 456 } 457 458 void ModuleDepCollector::applyDiscoveredDependencies(CompilerInvocation &CI) { 459 CI.clearImplicitModuleBuildOptions(); 460 resetBenignCodeGenOptions(CI.getFrontendOpts().ProgramAction, 461 CI.getLangOpts(), CI.getCodeGenOpts()); 462 463 if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) { 464 Preprocessor &PP = ScanInstance.getPreprocessor(); 465 if (Module *CurrentModule = PP.getCurrentModuleImplementation()) 466 if (OptionalFileEntryRef CurrentModuleMap = 467 PP.getHeaderSearchInfo() 468 .getModuleMap() 469 .getModuleMapFileForUniquing(CurrentModule)) 470 CI.getFrontendOpts().ModuleMapFiles.emplace_back( 471 CurrentModuleMap->getNameAsRequested()); 472 473 SmallVector<ModuleID> DirectDeps; 474 for (const auto &KV : ModularDeps) 475 if (DirectModularDeps.contains(KV.first)) 476 DirectDeps.push_back(KV.second->ID); 477 478 // TODO: Report module maps the same way it's done for modular dependencies. 479 addModuleMapFiles(CI, DirectDeps); 480 481 addModuleFiles(CI, DirectDeps); 482 483 for (const auto &KV : DirectPrebuiltModularDeps) 484 CI.getFrontendOpts().ModuleFiles.push_back(KV.second.PCMFile); 485 } 486 } 487 488 static bool isSafeToIgnoreCWD(const CowCompilerInvocation &CI) { 489 // Check if the command line input uses relative paths. 490 // It is not safe to ignore the current working directory if any of the 491 // command line inputs use relative paths. 492 #define IF_RELATIVE_RETURN_FALSE(PATH) \ 493 do { \ 494 if (!PATH.empty() && !llvm::sys::path::is_absolute(PATH)) \ 495 return false; \ 496 } while (0) 497 498 #define IF_ANY_RELATIVE_RETURN_FALSE(PATHS) \ 499 do { \ 500 if (llvm::any_of(PATHS, [](const auto &P) { \ 501 return !P.empty() && !llvm::sys::path::is_absolute(P); \ 502 })) \ 503 return false; \ 504 } while (0) 505 506 // Header search paths. 507 const auto &HeaderSearchOpts = CI.getHeaderSearchOpts(); 508 IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.Sysroot); 509 for (auto &Entry : HeaderSearchOpts.UserEntries) 510 if (Entry.IgnoreSysRoot) 511 IF_RELATIVE_RETURN_FALSE(Entry.Path); 512 IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ResourceDir); 513 IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ModuleCachePath); 514 IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ModuleUserBuildPath); 515 for (auto I = HeaderSearchOpts.PrebuiltModuleFiles.begin(), 516 E = HeaderSearchOpts.PrebuiltModuleFiles.end(); 517 I != E;) { 518 auto Current = I++; 519 IF_RELATIVE_RETURN_FALSE(Current->second); 520 } 521 IF_ANY_RELATIVE_RETURN_FALSE(HeaderSearchOpts.PrebuiltModulePaths); 522 IF_ANY_RELATIVE_RETURN_FALSE(HeaderSearchOpts.VFSOverlayFiles); 523 524 // Preprocessor options. 525 const auto &PPOpts = CI.getPreprocessorOpts(); 526 IF_ANY_RELATIVE_RETURN_FALSE(PPOpts.MacroIncludes); 527 IF_ANY_RELATIVE_RETURN_FALSE(PPOpts.Includes); 528 IF_RELATIVE_RETURN_FALSE(PPOpts.ImplicitPCHInclude); 529 530 // Frontend options. 531 const auto &FrontendOpts = CI.getFrontendOpts(); 532 for (const FrontendInputFile &Input : FrontendOpts.Inputs) { 533 if (Input.isBuffer()) 534 continue; // FIXME: Can this happen when parsing command-line? 535 536 IF_RELATIVE_RETURN_FALSE(Input.getFile()); 537 } 538 IF_RELATIVE_RETURN_FALSE(FrontendOpts.CodeCompletionAt.FileName); 539 IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModuleMapFiles); 540 IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModuleFiles); 541 IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModulesEmbedFiles); 542 IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ASTMergeFiles); 543 IF_RELATIVE_RETURN_FALSE(FrontendOpts.OverrideRecordLayoutsFile); 544 IF_RELATIVE_RETURN_FALSE(FrontendOpts.StatsFile); 545 546 // Filesystem options. 547 const auto &FileSystemOpts = CI.getFileSystemOpts(); 548 IF_RELATIVE_RETURN_FALSE(FileSystemOpts.WorkingDir); 549 550 // Codegen options. 551 const auto &CodeGenOpts = CI.getCodeGenOpts(); 552 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.DebugCompilationDir); 553 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.CoverageCompilationDir); 554 555 // Sanitizer options. 556 IF_ANY_RELATIVE_RETURN_FALSE(CI.getLangOpts().NoSanitizeFiles); 557 558 // Coverage mappings. 559 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.ProfileInstrumentUsePath); 560 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.SampleProfileFile); 561 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.ProfileRemappingFile); 562 563 // Dependency output options. 564 for (auto &ExtraDep : CI.getDependencyOutputOpts().ExtraDeps) 565 IF_RELATIVE_RETURN_FALSE(ExtraDep.first); 566 567 return true; 568 } 569 570 static std::string getModuleContextHash(const ModuleDeps &MD, 571 const CowCompilerInvocation &CI, 572 bool EagerLoadModules, bool IgnoreCWD, 573 llvm::vfs::FileSystem &VFS) { 574 llvm::HashBuilder<llvm::TruncatedBLAKE3<16>, llvm::endianness::native> 575 HashBuilder; 576 577 // Hash the compiler version and serialization version to ensure the module 578 // will be readable. 579 HashBuilder.add(getClangFullRepositoryVersion()); 580 HashBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR); 581 llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory(); 582 if (CWD && !IgnoreCWD) 583 HashBuilder.add(*CWD); 584 585 // Hash the BuildInvocation without any input files. 586 SmallString<0> ArgVec; 587 ArgVec.reserve(4096); 588 CI.generateCC1CommandLine([&](const Twine &Arg) { 589 Arg.toVector(ArgVec); 590 ArgVec.push_back('\0'); 591 }); 592 HashBuilder.add(ArgVec); 593 594 // Hash the module dependencies. These paths may differ even if the invocation 595 // is identical if they depend on the contents of the files in the TU -- for 596 // example, case-insensitive paths to modulemap files. Usually such a case 597 // would indicate a missed optimization to canonicalize, but it may be 598 // difficult to canonicalize all cases when there is a VFS. 599 for (const auto &ID : MD.ClangModuleDeps) { 600 HashBuilder.add(ID.ModuleName); 601 HashBuilder.add(ID.ContextHash); 602 } 603 604 HashBuilder.add(EagerLoadModules); 605 606 llvm::BLAKE3Result<16> Hash = HashBuilder.final(); 607 std::array<uint64_t, 2> Words; 608 static_assert(sizeof(Hash) == sizeof(Words), "Hash must match Words"); 609 std::memcpy(Words.data(), Hash.data(), sizeof(Hash)); 610 return toString(llvm::APInt(sizeof(Words) * 8, Words), 36, /*Signed=*/false); 611 } 612 613 void ModuleDepCollector::associateWithContextHash( 614 const CowCompilerInvocation &CI, bool IgnoreCWD, ModuleDeps &Deps) { 615 Deps.ID.ContextHash = 616 getModuleContextHash(Deps, CI, Service.shouldEagerLoadModules(), 617 IgnoreCWD, ScanInstance.getVirtualFileSystem()); 618 bool Inserted = ModuleDepsByID.insert({Deps.ID, &Deps}).second; 619 (void)Inserted; 620 assert(Inserted && "duplicate module mapping"); 621 } 622 623 void ModuleDepCollectorPP::LexedFileChanged(FileID FID, 624 LexedFileChangeReason Reason, 625 SrcMgr::CharacteristicKind FileType, 626 FileID PrevFID, 627 SourceLocation Loc) { 628 if (Reason != LexedFileChangeReason::EnterFile) 629 return; 630 631 SourceManager &SM = MDC.ScanInstance.getSourceManager(); 632 633 // Dependency generation really does want to go all the way to the 634 // file entry for a source location to find out what is depended on. 635 // We do not want #line markers to affect dependency generation! 636 if (std::optional<StringRef> Filename = SM.getNonBuiltinFilenameForID(FID)) 637 MDC.addFileDep(llvm::sys::path::remove_leading_dotslash(*Filename)); 638 } 639 640 void ModuleDepCollectorPP::InclusionDirective( 641 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, 642 bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, 643 StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, 644 bool ModuleImported, SrcMgr::CharacteristicKind FileType) { 645 if (!File && !ModuleImported) { 646 // This is a non-modular include that HeaderSearch failed to find. Add it 647 // here as `FileChanged` will never see it. 648 MDC.addFileDep(FileName); 649 } 650 handleImport(SuggestedModule); 651 } 652 653 void ModuleDepCollectorPP::moduleImport(SourceLocation ImportLoc, 654 ModuleIdPath Path, 655 const Module *Imported) { 656 if (MDC.ScanInstance.getPreprocessor().isInImportingCXXNamedModules()) { 657 P1689ModuleInfo RequiredModule; 658 RequiredModule.ModuleName = Path[0].getIdentifierInfo()->getName().str(); 659 RequiredModule.Type = P1689ModuleInfo::ModuleType::NamedCXXModule; 660 MDC.RequiredStdCXXModules.push_back(std::move(RequiredModule)); 661 return; 662 } 663 664 handleImport(Imported); 665 } 666 667 void ModuleDepCollectorPP::handleImport(const Module *Imported) { 668 if (!Imported) 669 return; 670 671 const Module *TopLevelModule = Imported->getTopLevelModule(); 672 673 if (MDC.isPrebuiltModule(TopLevelModule)) 674 MDC.DirectPrebuiltModularDeps.insert( 675 {TopLevelModule, PrebuiltModuleDep{TopLevelModule}}); 676 else { 677 MDC.DirectModularDeps.insert(TopLevelModule); 678 MDC.DirectImports.insert(Imported); 679 } 680 } 681 682 void ModuleDepCollectorPP::EndOfMainFile() { 683 FileID MainFileID = MDC.ScanInstance.getSourceManager().getMainFileID(); 684 MDC.MainFile = std::string(MDC.ScanInstance.getSourceManager() 685 .getFileEntryRefForID(MainFileID) 686 ->getName()); 687 688 auto &PP = MDC.ScanInstance.getPreprocessor(); 689 if (PP.isInNamedModule()) { 690 P1689ModuleInfo ProvidedModule; 691 ProvidedModule.ModuleName = PP.getNamedModuleName(); 692 ProvidedModule.Type = P1689ModuleInfo::ModuleType::NamedCXXModule; 693 ProvidedModule.IsStdCXXModuleInterface = PP.isInNamedInterfaceUnit(); 694 // Don't put implementation (non partition) unit as Provide. 695 // Put the module as required instead. Since the implementation 696 // unit will import the primary module implicitly. 697 if (PP.isInImplementationUnit()) 698 MDC.RequiredStdCXXModules.push_back(ProvidedModule); 699 else 700 MDC.ProvidedStdCXXModule = ProvidedModule; 701 } 702 703 if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty()) 704 MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude); 705 706 for (const Module *M : 707 MDC.ScanInstance.getPreprocessor().getAffectingClangModules()) 708 if (!MDC.isPrebuiltModule(M)) 709 MDC.DirectModularDeps.insert(M); 710 711 MDC.addVisibleModules(); 712 713 for (const Module *M : MDC.DirectModularDeps) 714 handleTopLevelModule(M); 715 716 MDC.Consumer.handleContextHash( 717 MDC.ScanInstance.getInvocation().getModuleHash()); 718 719 MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts); 720 721 MDC.Consumer.handleProvidedAndRequiredStdCXXModules( 722 MDC.ProvidedStdCXXModule, MDC.RequiredStdCXXModules); 723 724 for (auto &&I : MDC.ModularDeps) 725 MDC.Consumer.handleModuleDependency(*I.second); 726 727 for (const Module *M : MDC.DirectModularDeps) { 728 auto It = MDC.ModularDeps.find(M); 729 // Only report direct dependencies that were successfully handled. 730 if (It != MDC.ModularDeps.end()) 731 MDC.Consumer.handleDirectModuleDependency(It->second->ID); 732 } 733 734 for (auto &&I : MDC.VisibleModules) 735 MDC.Consumer.handleVisibleModule(std::string(I.getKey())); 736 737 for (auto &&I : MDC.FileDeps) 738 MDC.Consumer.handleFileDependency(I); 739 740 for (auto &&I : MDC.DirectPrebuiltModularDeps) 741 MDC.Consumer.handlePrebuiltModuleDependency(I.second); 742 } 743 744 std::optional<ModuleID> 745 ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { 746 assert(M == M->getTopLevelModule() && "Expected top level module!"); 747 748 // A top-level module might not be actually imported as a module when 749 // -fmodule-name is used to compile a translation unit that imports this 750 // module. In that case it can be skipped. The appropriate header 751 // dependencies will still be reported as expected. 752 if (!M->getASTFile()) 753 return {}; 754 755 // If this module has been handled already, just return its ID. 756 if (auto ModI = MDC.ModularDeps.find(M); ModI != MDC.ModularDeps.end()) 757 return ModI->second->ID; 758 759 auto OwnedMD = std::make_unique<ModuleDeps>(); 760 ModuleDeps &MD = *OwnedMD; 761 762 MD.ID.ModuleName = M->getFullModuleName(); 763 MD.IsSystem = M->IsSystem; 764 765 // Start off with the assumption that this module is shareable when there 766 // are stable directories. As more dependencies are discovered, check if those 767 // come from the provided directories. 768 MD.IsInStableDirectories = !MDC.StableDirs.empty(); 769 770 // For modules which use export_as link name, the linked product that of the 771 // corresponding export_as-named module. 772 if (!M->UseExportAsModuleLinkName) 773 MD.LinkLibraries = M->LinkLibraries; 774 775 ModuleMap &ModMapInfo = 776 MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); 777 778 if (auto ModuleMap = ModMapInfo.getModuleMapFileForUniquing(M)) { 779 SmallString<128> Path = ModuleMap->getNameAsRequested(); 780 ModMapInfo.canonicalizeModuleMapPath(Path); 781 MD.ClangModuleMapFile = std::string(Path); 782 } 783 784 serialization::ModuleFile *MF = 785 MDC.ScanInstance.getASTReader()->getModuleManager().lookup( 786 *M->getASTFile()); 787 MD.FileDepsBaseDir = MF->BaseDirectory; 788 MDC.ScanInstance.getASTReader()->visitInputFileInfos( 789 *MF, /*IncludeSystem=*/true, 790 [&](const serialization::InputFileInfo &IFI, bool IsSystem) { 791 // The __inferred_module.map file is an insignificant implementation 792 // detail of implicitly-built modules. The PCM will also report the 793 // actual on-disk module map file that allowed inferring the module, 794 // which is what we need for building the module explicitly 795 // Let's ignore this file. 796 if (IFI.UnresolvedImportedFilename.ends_with("__inferred_module.map")) 797 return; 798 MDC.addFileDep(MD, IFI.UnresolvedImportedFilename); 799 }); 800 801 llvm::DenseSet<const Module *> SeenDeps; 802 addAllSubmodulePrebuiltDeps(M, MD, SeenDeps); 803 addAllSubmoduleDeps(M, MD, SeenDeps); 804 addAllAffectingClangModules(M, MD, SeenDeps); 805 806 SmallString<0> PathBuf; 807 PathBuf.reserve(256); 808 MDC.ScanInstance.getASTReader()->visitInputFileInfos( 809 *MF, /*IncludeSystem=*/true, 810 [&](const serialization::InputFileInfo &IFI, bool IsSystem) { 811 if (MD.IsInStableDirectories) { 812 auto FullFilePath = ASTReader::ResolveImportedPath( 813 PathBuf, IFI.UnresolvedImportedFilename, MF->BaseDirectory); 814 MD.IsInStableDirectories = 815 isPathInStableDir(MDC.StableDirs, *FullFilePath); 816 } 817 if (!(IFI.TopLevel && IFI.ModuleMap)) 818 return; 819 if (IFI.UnresolvedImportedFilenameAsRequested.ends_with( 820 "__inferred_module.map")) 821 return; 822 auto ResolvedFilenameAsRequested = ASTReader::ResolveImportedPath( 823 PathBuf, IFI.UnresolvedImportedFilenameAsRequested, 824 MF->BaseDirectory); 825 MD.ModuleMapFileDeps.emplace_back(*ResolvedFilenameAsRequested); 826 }); 827 828 bool IgnoreCWD = false; 829 CowCompilerInvocation CI = 830 MDC.getInvocationAdjustedForModuleBuildWithoutOutputs( 831 MD, [&](CowCompilerInvocation &BuildInvocation) { 832 if (any(MDC.Service.getOptimizeArgs() & 833 (ScanningOptimizations::HeaderSearch | 834 ScanningOptimizations::VFS))) 835 optimizeHeaderSearchOpts(BuildInvocation.getMutHeaderSearchOpts(), 836 *MDC.ScanInstance.getASTReader(), *MF, 837 MDC.PrebuiltModulesASTMap, 838 MDC.Service.getOptimizeArgs()); 839 840 if (any(MDC.Service.getOptimizeArgs() & 841 ScanningOptimizations::SystemWarnings)) 842 optimizeDiagnosticOpts( 843 BuildInvocation.getMutDiagnosticOpts(), 844 BuildInvocation.getFrontendOpts().IsSystemModule); 845 846 IgnoreCWD = any(MDC.Service.getOptimizeArgs() & 847 ScanningOptimizations::IgnoreCWD) && 848 isSafeToIgnoreCWD(BuildInvocation); 849 if (IgnoreCWD) { 850 llvm::ErrorOr<std::string> CWD = 851 MDC.ScanInstance.getVirtualFileSystem() 852 .getCurrentWorkingDirectory(); 853 if (CWD) 854 optimizeCWD(BuildInvocation, *CWD); 855 } 856 }); 857 858 // Check provided input paths from the invocation for determining 859 // IsInStableDirectories. 860 if (MD.IsInStableDirectories) 861 MD.IsInStableDirectories = 862 areOptionsInStableDir(MDC.StableDirs, CI.getHeaderSearchOpts()); 863 864 MDC.associateWithContextHash(CI, IgnoreCWD, MD); 865 866 // Finish the compiler invocation. Requires dependencies and the context hash. 867 MDC.addOutputPaths(CI, MD); 868 869 MD.BuildInfo = std::move(CI); 870 871 MDC.ModularDeps.insert({M, std::move(OwnedMD)}); 872 873 return MD.ID; 874 } 875 876 static void forEachSubmoduleSorted(const Module *M, 877 llvm::function_ref<void(const Module *)> F) { 878 // Submodule order depends on order of header includes for inferred submodules 879 // we don't care about the exact order, so sort so that it's consistent across 880 // TUs to improve sharing. 881 SmallVector<const Module *> Submodules(M->submodules()); 882 llvm::stable_sort(Submodules, [](const Module *A, const Module *B) { 883 return A->Name < B->Name; 884 }); 885 for (const Module *SubM : Submodules) 886 F(SubM); 887 } 888 889 void ModuleDepCollectorPP::addAllSubmodulePrebuiltDeps( 890 const Module *M, ModuleDeps &MD, 891 llvm::DenseSet<const Module *> &SeenSubmodules) { 892 addModulePrebuiltDeps(M, MD, SeenSubmodules); 893 894 forEachSubmoduleSorted(M, [&](const Module *SubM) { 895 addAllSubmodulePrebuiltDeps(SubM, MD, SeenSubmodules); 896 }); 897 } 898 899 void ModuleDepCollectorPP::addModulePrebuiltDeps( 900 const Module *M, ModuleDeps &MD, 901 llvm::DenseSet<const Module *> &SeenSubmodules) { 902 for (const Module *Import : M->Imports) 903 if (Import->getTopLevelModule() != M->getTopLevelModule()) 904 if (MDC.isPrebuiltModule(Import->getTopLevelModule())) 905 if (SeenSubmodules.insert(Import->getTopLevelModule()).second) { 906 MD.PrebuiltModuleDeps.emplace_back(Import->getTopLevelModule()); 907 if (MD.IsInStableDirectories) { 908 auto PrebuiltModulePropIt = MDC.PrebuiltModulesASTMap.find( 909 MD.PrebuiltModuleDeps.back().PCMFile); 910 MD.IsInStableDirectories = 911 (PrebuiltModulePropIt != MDC.PrebuiltModulesASTMap.end()) && 912 PrebuiltModulePropIt->second.isInStableDir(); 913 } 914 } 915 } 916 917 void ModuleDepCollectorPP::addAllSubmoduleDeps( 918 const Module *M, ModuleDeps &MD, 919 llvm::DenseSet<const Module *> &AddedModules) { 920 addModuleDep(M, MD, AddedModules); 921 922 forEachSubmoduleSorted(M, [&](const Module *SubM) { 923 addAllSubmoduleDeps(SubM, MD, AddedModules); 924 }); 925 } 926 927 void ModuleDepCollectorPP::addOneModuleDep(const Module *M, const ModuleID ID, 928 ModuleDeps &MD) { 929 MD.ClangModuleDeps.push_back(std::move(ID)); 930 if (MD.IsInStableDirectories) 931 MD.IsInStableDirectories = MDC.ModularDeps[M]->IsInStableDirectories; 932 } 933 934 void ModuleDepCollectorPP::addModuleDep( 935 const Module *M, ModuleDeps &MD, 936 llvm::DenseSet<const Module *> &AddedModules) { 937 for (const Module *Import : M->Imports) { 938 if (Import->getTopLevelModule() != M->getTopLevelModule() && 939 !MDC.isPrebuiltModule(Import)) { 940 if (auto ImportID = handleTopLevelModule(Import->getTopLevelModule())) 941 if (AddedModules.insert(Import->getTopLevelModule()).second) 942 addOneModuleDep(Import->getTopLevelModule(), *ImportID, MD); 943 } 944 } 945 } 946 947 void ModuleDepCollectorPP::addAllAffectingClangModules( 948 const Module *M, ModuleDeps &MD, 949 llvm::DenseSet<const Module *> &AddedModules) { 950 addAffectingClangModule(M, MD, AddedModules); 951 952 for (const Module *SubM : M->submodules()) 953 addAllAffectingClangModules(SubM, MD, AddedModules); 954 } 955 956 void ModuleDepCollectorPP::addAffectingClangModule( 957 const Module *M, ModuleDeps &MD, 958 llvm::DenseSet<const Module *> &AddedModules) { 959 for (const Module *Affecting : M->AffectingClangModules) { 960 assert(Affecting == Affecting->getTopLevelModule() && 961 "Not quite import not top-level module"); 962 if (Affecting != M->getTopLevelModule() && 963 !MDC.isPrebuiltModule(Affecting)) { 964 if (auto ImportID = handleTopLevelModule(Affecting)) 965 if (AddedModules.insert(Affecting).second) 966 addOneModuleDep(Affecting, *ImportID, MD); 967 } 968 } 969 } 970 971 ModuleDepCollector::ModuleDepCollector( 972 DependencyScanningService &Service, 973 std::unique_ptr<DependencyOutputOptions> Opts, 974 CompilerInstance &ScanInstance, DependencyConsumer &C, 975 DependencyActionController &Controller, CompilerInvocation OriginalCI, 976 const PrebuiltModulesAttrsMap PrebuiltModulesASTMap, 977 const ArrayRef<StringRef> StableDirs) 978 : Service(Service), ScanInstance(ScanInstance), Consumer(C), 979 Controller(Controller), 980 PrebuiltModulesASTMap(std::move(PrebuiltModulesASTMap)), 981 StableDirs(StableDirs), Opts(std::move(Opts)), 982 CommonInvocation( 983 makeCommonInvocationForModuleBuild(std::move(OriginalCI))) {} 984 985 void ModuleDepCollector::attachToPreprocessor(Preprocessor &PP) { 986 PP.addPPCallbacks(std::make_unique<ModuleDepCollectorPP>(*this)); 987 } 988 989 void ModuleDepCollector::attachToASTReader(ASTReader &R) {} 990 991 bool ModuleDepCollector::isPrebuiltModule(const Module *M) { 992 std::string Name(M->getTopLevelModuleName()); 993 const auto &PrebuiltModuleFiles = 994 ScanInstance.getHeaderSearchOpts().PrebuiltModuleFiles; 995 auto PrebuiltModuleFileIt = PrebuiltModuleFiles.find(Name); 996 if (PrebuiltModuleFileIt == PrebuiltModuleFiles.end()) 997 return false; 998 assert("Prebuilt module came from the expected AST file" && 999 PrebuiltModuleFileIt->second == M->getASTFile()->getName()); 1000 return true; 1001 } 1002 1003 void ModuleDepCollector::addVisibleModules() { 1004 llvm::DenseSet<const Module *> ImportedModules; 1005 auto InsertVisibleModules = [&](const Module *M) { 1006 if (ImportedModules.contains(M)) 1007 return; 1008 1009 VisibleModules.insert(M->getTopLevelModuleName()); 1010 SmallVector<Module *> Stack; 1011 M->getExportedModules(Stack); 1012 while (!Stack.empty()) { 1013 const Module *CurrModule = Stack.pop_back_val(); 1014 if (ImportedModules.contains(CurrModule)) 1015 continue; 1016 ImportedModules.insert(CurrModule); 1017 VisibleModules.insert(CurrModule->getTopLevelModuleName()); 1018 CurrModule->getExportedModules(Stack); 1019 } 1020 }; 1021 1022 for (const Module *Import : DirectImports) 1023 InsertVisibleModules(Import); 1024 } 1025 1026 static StringRef makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path, 1027 SmallVectorImpl<char> &Storage) { 1028 if (llvm::sys::path::is_absolute(Path) && 1029 !llvm::sys::path::is_style_windows(llvm::sys::path::Style::native)) 1030 return Path; 1031 Storage.assign(Path.begin(), Path.end()); 1032 CI.getFileManager().makeAbsolutePath(Storage); 1033 llvm::sys::path::make_preferred(Storage); 1034 return StringRef(Storage.data(), Storage.size()); 1035 } 1036 1037 void ModuleDepCollector::addFileDep(StringRef Path) { 1038 if (Service.getFormat() == ScanningOutputFormat::P1689) { 1039 // Within P1689 format, we don't want all the paths to be absolute path 1040 // since it may violate the traditional make style dependencies info. 1041 FileDeps.emplace_back(Path); 1042 return; 1043 } 1044 1045 llvm::SmallString<256> Storage; 1046 Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage); 1047 FileDeps.emplace_back(Path); 1048 } 1049 1050 void ModuleDepCollector::addFileDep(ModuleDeps &MD, StringRef Path) { 1051 MD.FileDeps.emplace_back(Path); 1052 } 1053