xref: /freebsd/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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