clang 22.0.0git
ModuleDepCollector.cpp
Go to the documentation of this file.
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
10
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/Support/BLAKE3.h"
17#include <optional>
18
19using namespace clang;
20using namespace dependencies;
21
22void ModuleDeps::forEachFileDep(llvm::function_ref<void(StringRef)> Cb) const {
23 SmallString<0> PathBuf;
24 PathBuf.reserve(256);
25 for (StringRef FileDep : FileDeps) {
26 auto ResolvedFileDep =
27 ASTReader::ResolveImportedPath(PathBuf, FileDep, FileDepsBaseDir);
28 Cb(*ResolvedFileDep);
29 }
30}
31
32const std::vector<std::string> &ModuleDeps::getBuildArguments() const {
33 // FIXME: this operation is not thread safe and is expected to be called
34 // on a single thread. Otherwise it should be protected with a lock.
35 assert(!std::holds_alternative<std::monostate>(BuildInfo) &&
36 "Using uninitialized ModuleDeps");
37 if (const auto *CI = std::get_if<CowCompilerInvocation>(&BuildInfo))
38 BuildInfo = CI->getCC1CommandLine();
39 return std::get<std::vector<std::string>>(BuildInfo);
40}
41
43 PrebuiltModulesAttrsMap &PrebuiltModulesMap) {
45 for (const auto Dep : ModuleFileDependents) {
46 if (!PrebuiltModulesMap[Dep].isInStableDir())
47 return;
48 PrebuiltModulesMap[Dep].updateDependentsNotInStableDirs(PrebuiltModulesMap);
49 }
50}
51
52static void
55 const PrebuiltModulesAttrsMap &PrebuiltModulesASTMap,
56 ScanningOptimizations OptimizeArgs) {
57 if (any(OptimizeArgs & ScanningOptimizations::HeaderSearch)) {
58 // Only preserve search paths that were used during the dependency scan.
59 std::vector<HeaderSearchOptions::Entry> Entries;
60 std::swap(Opts.UserEntries, Entries);
61
62 llvm::BitVector SearchPathUsage(Entries.size());
63 llvm::DenseSet<const serialization::ModuleFile *> Visited;
64 std::function<void(const serialization::ModuleFile *)> VisitMF =
65 [&](const serialization::ModuleFile *MF) {
66 SearchPathUsage |= MF->SearchPathUsage;
67 Visited.insert(MF);
68 for (const serialization::ModuleFile *Import : MF->Imports)
69 if (!Visited.contains(Import))
70 VisitMF(Import);
71 };
72 VisitMF(&MF);
73
74 if (SearchPathUsage.size() != Entries.size())
75 llvm::report_fatal_error(
76 "Inconsistent search path options between modules detected");
77
78 for (auto Idx : SearchPathUsage.set_bits())
79 Opts.UserEntries.push_back(std::move(Entries[Idx]));
80 }
81 if (any(OptimizeArgs & ScanningOptimizations::VFS)) {
82 std::vector<std::string> VFSOverlayFiles;
83 std::swap(Opts.VFSOverlayFiles, VFSOverlayFiles);
84
85 llvm::BitVector VFSUsage(VFSOverlayFiles.size());
86 llvm::DenseSet<const serialization::ModuleFile *> Visited;
87 std::function<void(const serialization::ModuleFile *)> VisitMF =
88 [&](const serialization::ModuleFile *MF) {
89 Visited.insert(MF);
91 VFSUsage |= MF->VFSUsage;
92 // We only need to recurse into implicit modules. Other module types
93 // will have the correct set of VFSs for anything they depend on.
94 for (const serialization::ModuleFile *Import : MF->Imports)
95 if (!Visited.contains(Import))
96 VisitMF(Import);
97 } else {
98 // This is not an implicitly built module, so it may have different
99 // VFS options. Fall back to a string comparison instead.
100 auto PrebuiltModulePropIt =
101 PrebuiltModulesASTMap.find(MF->FileName);
102 if (PrebuiltModulePropIt == PrebuiltModulesASTMap.end())
103 return;
104 for (std::size_t I = 0, E = VFSOverlayFiles.size(); I != E; ++I) {
105 if (PrebuiltModulePropIt->second.getVFS().contains(
106 VFSOverlayFiles[I]))
107 VFSUsage[I] = true;
108 }
109 }
110 };
111 VisitMF(&MF);
112
113 if (VFSUsage.size() != VFSOverlayFiles.size())
114 llvm::report_fatal_error(
115 "Inconsistent -ivfsoverlay options between modules detected");
116
117 for (auto Idx : VFSUsage.set_bits())
118 Opts.VFSOverlayFiles.push_back(std::move(VFSOverlayFiles[Idx]));
119 }
120}
121
123 bool IsSystemModule) {
124 // If this is not a system module or -Wsystem-headers was passed, don't
125 // optimize.
126 if (!IsSystemModule)
127 return;
128 bool Wsystem_headers = false;
129 for (StringRef Opt : Opts.Warnings) {
130 bool isPositive = !Opt.consume_front("no-");
131 if (Opt == "system-headers")
132 Wsystem_headers = isPositive;
133 }
134 if (Wsystem_headers)
135 return;
136
137 // Remove all warning flags. System modules suppress most, but not all,
138 // warnings.
139 Opts.Warnings.clear();
140 Opts.UndefPrefixes.clear();
141 Opts.Remarks.clear();
142}
143
144static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) {
145 BuildInvocation.getMutFileSystemOpts().WorkingDir.clear();
146 BuildInvocation.getMutCodeGenOpts().DebugCompilationDir.clear();
147 BuildInvocation.getMutCodeGenOpts().CoverageCompilationDir.clear();
148}
149
150static std::vector<std::string> splitString(std::string S, char Separator) {
151 SmallVector<StringRef> Segments;
152 StringRef(S).split(Segments, Separator, /*MaxSplit=*/-1, /*KeepEmpty=*/false);
153 std::vector<std::string> Result;
154 Result.reserve(Segments.size());
155 for (StringRef Segment : Segments)
156 Result.push_back(Segment.str());
157 return Result;
158}
159
160void ModuleDepCollector::addOutputPaths(CowCompilerInvocation &CI,
161 ModuleDeps &Deps) {
163 Controller.lookupModuleOutput(Deps, ModuleOutputKind::ModuleFile);
166 Controller.lookupModuleOutput(
168 if (!CI.getDependencyOutputOpts().OutputFile.empty()) {
170 Controller.lookupModuleOutput(Deps, ModuleOutputKind::DependencyFile);
172 splitString(Controller.lookupModuleOutput(
174 '\0');
175 if (!CI.getDependencyOutputOpts().OutputFile.empty() &&
176 CI.getDependencyOutputOpts().Targets.empty()) {
177 // Fallback to -o as dependency target, as in the driver.
178 SmallString<128> Target;
180 CI.getMutDependencyOutputOpts().Targets.push_back(std::string(Target));
181 }
182 }
183}
184
186 const LangOptions &LangOpts,
187 CodeGenOptions &CGOpts) {
188 // TODO: Figure out better way to set options to their default value.
189 if (ProgramAction == frontend::GenerateModule) {
190 CGOpts.MainFileName.clear();
191 CGOpts.DwarfDebugFlags.clear();
192 }
193 if (ProgramAction == frontend::GeneratePCH ||
194 (ProgramAction == frontend::GenerateModule && !LangOpts.ModulesCodegen)) {
195 CGOpts.DebugCompilationDir.clear();
196 CGOpts.CoverageCompilationDir.clear();
197 CGOpts.CoverageDataFile.clear();
198 CGOpts.CoverageNotesFile.clear();
199 CGOpts.ProfileInstrumentUsePath.clear();
200 CGOpts.SampleProfileFile.clear();
201 CGOpts.ProfileRemappingFile.clear();
202 }
203}
204
206 const StringRef Input) {
207 using namespace llvm::sys;
208
209 if (!path::is_absolute(Input))
210 return false;
211
212 auto PathStartsWith = [](StringRef Prefix, StringRef Path) {
213 auto PrefixIt = path::begin(Prefix), PrefixEnd = path::end(Prefix);
214 for (auto PathIt = path::begin(Path), PathEnd = path::end(Path);
215 PrefixIt != PrefixEnd && PathIt != PathEnd; ++PrefixIt, ++PathIt) {
216 if (*PrefixIt != *PathIt)
217 return false;
218 }
219 return PrefixIt == PrefixEnd;
220 };
221
222 return any_of(Directories, [&](StringRef Dir) {
223 return !Dir.empty() && PathStartsWith(Dir, Input);
224 });
225}
226
228 const HeaderSearchOptions &HSOpts) {
229 assert(isPathInStableDir(Directories, HSOpts.Sysroot) &&
230 "Sysroots differ between module dependencies and current TU");
231
232 assert(isPathInStableDir(Directories, HSOpts.ResourceDir) &&
233 "ResourceDirs differ between module dependencies and current TU");
234
235 for (const auto &Entry : HSOpts.UserEntries) {
236 if (!Entry.IgnoreSysRoot)
237 continue;
238 if (!isPathInStableDir(Directories, Entry.Path))
239 return false;
240 }
241
242 for (const auto &SysPrefix : HSOpts.SystemHeaderPrefixes) {
243 if (!isPathInStableDir(Directories, SysPrefix.Prefix))
244 return false;
245 }
246
247 return true;
248}
249
254
255 // The scanner takes care to avoid passing non-affecting module maps to the
256 // explicit compiles. No need to do extra work just to find out there are no
257 // module map files to prune.
259
260 // Remove options incompatible with explicit module build or are likely to
261 // differ between identical modules discovered from different translation
262 // units.
263 CI.getFrontendOpts().Inputs.clear();
264 CI.getFrontendOpts().OutputFile.clear();
265 CI.getFrontendOpts().GenReducedBMI = false;
269 // LLVM options are not going to affect the AST
270 CI.getFrontendOpts().LLVMArgs.clear();
271
273 CI.getCodeGenOpts());
274
275 // Map output paths that affect behaviour to "-" so their existence is in the
276 // context hash. The final path will be computed in addOutputPaths.
279 if (!CI.getDependencyOutputOpts().OutputFile.empty())
281 CI.getDependencyOutputOpts().Targets.clear();
282
284 CI.getLangOpts().ModuleName.clear();
285
286 // Remove any macro definitions that are explicitly ignored.
287 if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) {
288 llvm::erase_if(
290 [&CI](const std::pair<std::string, bool> &Def) {
291 StringRef MacroDef = Def.first;
292 return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
293 llvm::CachedHashString(MacroDef.split('=').first));
294 });
295 // Remove the now unused option.
297 }
298
299 return CI;
300}
301
302CowCompilerInvocation
303ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs(
304 const ModuleDeps &Deps,
305 llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const {
306 CowCompilerInvocation CI = CommonInvocation;
307
310
311 // Inputs
312 InputKind ModuleMapInputKind(CI.getFrontendOpts().DashX.getLanguage(),
314 CI.getMutFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile,
315 ModuleMapInputKind);
316
317 auto CurrentModuleMapEntry =
318 ScanInstance.getFileManager().getOptionalFileRef(Deps.ClangModuleMapFile);
319 assert(CurrentModuleMapEntry && "module map file entry not found");
320
321 // Remove directly passed modulemap files. They will get added back if they
322 // were actually used.
324
325 auto DepModuleMapFiles = collectModuleMapFiles(Deps.ClangModuleDeps);
326 for (StringRef ModuleMapFile : Deps.ModuleMapFileDeps) {
327 // TODO: Track these as `FileEntryRef` to simplify the equality check below.
328 auto ModuleMapEntry =
329 ScanInstance.getFileManager().getOptionalFileRef(ModuleMapFile);
330 assert(ModuleMapEntry && "module map file entry not found");
331
332 // Don't report module maps describing eagerly-loaded dependency. This
333 // information will be deserialized from the PCM.
334 // TODO: Verify this works fine when modulemap for module A is eagerly
335 // loaded from A.pcm, and module map passed on the command line contains
336 // definition of a submodule: "explicit module A.Private { ... }".
337 if (Service.shouldEagerLoadModules() &&
338 DepModuleMapFiles.contains(*ModuleMapEntry))
339 continue;
340
341 // Don't report module map file of the current module unless it also
342 // describes a dependency (for symmetry).
343 if (*ModuleMapEntry == *CurrentModuleMapEntry &&
344 !DepModuleMapFiles.contains(*ModuleMapEntry))
345 continue;
346
347 CI.getMutFrontendOpts().ModuleMapFiles.emplace_back(ModuleMapFile);
348 }
349
350 // Report the prebuilt modules this module uses.
351 for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps)
352 CI.getMutFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
353
354 // Add module file inputs from dependencies.
355 addModuleFiles(CI, Deps.ClangModuleDeps);
356
358 // Apply -Wsystem-headers-in-module for the current module.
359 if (llvm::is_contained(CI.getDiagnosticOpts().SystemHeaderWarningsModules,
360 Deps.ID.ModuleName))
361 CI.getMutDiagnosticOpts().Warnings.push_back("system-headers");
362 // Remove the now unused option(s).
364 }
365
366 Optimize(CI);
367
368 return CI;
369}
370
371llvm::DenseSet<const FileEntry *> ModuleDepCollector::collectModuleMapFiles(
372 ArrayRef<ModuleID> ClangModuleDeps) const {
373 llvm::DenseSet<const FileEntry *> ModuleMapFiles;
374 for (const ModuleID &MID : ClangModuleDeps) {
375 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
376 assert(MD && "Inconsistent dependency info");
377 // TODO: Track ClangModuleMapFile as `FileEntryRef`.
378 auto FE = ScanInstance.getFileManager().getOptionalFileRef(
380 assert(FE && "Missing module map file that was previously found");
381 ModuleMapFiles.insert(*FE);
382 }
383 return ModuleMapFiles;
384}
385
386void ModuleDepCollector::addModuleMapFiles(
387 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
388 if (Service.shouldEagerLoadModules())
389 return; // Only pcm is needed for eager load.
390
391 for (const ModuleID &MID : ClangModuleDeps) {
392 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
393 assert(MD && "Inconsistent dependency info");
395 }
396}
397
398void ModuleDepCollector::addModuleFiles(
399 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
400 for (const ModuleID &MID : ClangModuleDeps) {
401 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
402 std::string PCMPath =
403 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile);
404
405 if (Service.shouldEagerLoadModules())
406 CI.getFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
407 else
409 {MID.ModuleName, std::move(PCMPath)});
410 }
411}
412
413void ModuleDepCollector::addModuleFiles(
414 CowCompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
415 for (const ModuleID &MID : ClangModuleDeps) {
416 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
417 std::string PCMPath =
418 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile);
419
420 if (Service.shouldEagerLoadModules())
421 CI.getMutFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
422 else
424 {MID.ModuleName, std::move(PCMPath)});
425 }
426}
427
429 switch (FIF.getKind().getLanguage()) {
431 case Language::Asm:
433 return false;
434 default:
435 return true;
436 }
437}
438
442 CI.getLangOpts(), CI.getCodeGenOpts());
443
444 if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) {
445 Preprocessor &PP = ScanInstance.getPreprocessor();
446 if (Module *CurrentModule = PP.getCurrentModuleImplementation())
447 if (OptionalFileEntryRef CurrentModuleMap =
449 .getModuleMap()
450 .getModuleMapFileForUniquing(CurrentModule))
451 CI.getFrontendOpts().ModuleMapFiles.emplace_back(
452 CurrentModuleMap->getNameAsRequested());
453
454 SmallVector<ModuleID> DirectDeps;
455 for (const auto &KV : ModularDeps)
456 if (DirectModularDeps.contains(KV.first))
457 DirectDeps.push_back(KV.second->ID);
458
459 // TODO: Report module maps the same way it's done for modular dependencies.
460 addModuleMapFiles(CI, DirectDeps);
461
462 addModuleFiles(CI, DirectDeps);
463
464 for (const auto &KV : DirectPrebuiltModularDeps)
465 CI.getFrontendOpts().ModuleFiles.push_back(KV.second.PCMFile);
466 }
467}
468
470 // Check if the command line input uses relative paths.
471 // It is not safe to ignore the current working directory if any of the
472 // command line inputs use relative paths.
473 bool AnyRelative = false;
474 CI.visitPaths([&](StringRef Path) {
475 assert(!AnyRelative && "Continuing path visitation despite returning true");
476 AnyRelative |= !Path.empty() && !llvm::sys::path::is_absolute(Path);
477 return AnyRelative;
478 });
479 return !AnyRelative;
480}
481
482static std::string getModuleContextHash(const ModuleDeps &MD,
483 const CowCompilerInvocation &CI,
484 bool EagerLoadModules, bool IgnoreCWD,
485 llvm::vfs::FileSystem &VFS) {
486 llvm::HashBuilder<llvm::TruncatedBLAKE3<16>, llvm::endianness::native>
487 HashBuilder;
488
489 // Hash the compiler version and serialization version to ensure the module
490 // will be readable.
491 HashBuilder.add(getClangFullRepositoryVersion());
493 llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory();
494 if (CWD && !IgnoreCWD)
495 HashBuilder.add(*CWD);
496
497 // Hash the BuildInvocation without any input files.
498 SmallString<0> ArgVec;
499 ArgVec.reserve(4096);
500 CI.generateCC1CommandLine([&](const Twine &Arg) {
501 Arg.toVector(ArgVec);
502 ArgVec.push_back('\0');
503 });
504 HashBuilder.add(ArgVec);
505
506 // Hash the module dependencies. These paths may differ even if the invocation
507 // is identical if they depend on the contents of the files in the TU -- for
508 // example, case-insensitive paths to modulemap files. Usually such a case
509 // would indicate a missed optimization to canonicalize, but it may be
510 // difficult to canonicalize all cases when there is a VFS.
511 for (const auto &ID : MD.ClangModuleDeps) {
512 HashBuilder.add(ID.ModuleName);
513 HashBuilder.add(ID.ContextHash);
514 }
515
516 HashBuilder.add(EagerLoadModules);
517
518 llvm::BLAKE3Result<16> Hash = HashBuilder.final();
519 std::array<uint64_t, 2> Words;
520 static_assert(sizeof(Hash) == sizeof(Words), "Hash must match Words");
521 std::memcpy(Words.data(), Hash.data(), sizeof(Hash));
522 return toString(llvm::APInt(sizeof(Words) * 8, Words), 36, /*Signed=*/false);
523}
524
525void ModuleDepCollector::associateWithContextHash(
526 const CowCompilerInvocation &CI, bool IgnoreCWD, ModuleDeps &Deps) {
527 Deps.ID.ContextHash =
528 getModuleContextHash(Deps, CI, Service.shouldEagerLoadModules(),
529 IgnoreCWD, ScanInstance.getVirtualFileSystem());
530 bool Inserted = ModuleDepsByID.insert({Deps.ID, &Deps}).second;
531 (void)Inserted;
532 assert(Inserted && "duplicate module mapping");
533}
534
538 FileID PrevFID,
539 SourceLocation Loc) {
541 return;
542
543 SourceManager &SM = MDC.ScanInstance.getSourceManager();
544
545 // Dependency generation really does want to go all the way to the
546 // file entry for a source location to find out what is depended on.
547 // We do not want #line markers to affect dependency generation!
548 if (std::optional<StringRef> Filename = SM.getNonBuiltinFilenameForID(FID))
549 MDC.addFileDep(llvm::sys::path::remove_leading_dotslash(*Filename));
550}
551
553 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
554 bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
555 StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule,
556 bool ModuleImported, SrcMgr::CharacteristicKind FileType) {
557 if (!File && !ModuleImported) {
558 // This is a non-modular include that HeaderSearch failed to find. Add it
559 // here as `FileChanged` will never see it.
560 MDC.addFileDep(FileName);
561 }
562 handleImport(SuggestedModule);
563}
564
566 ModuleIdPath Path,
567 const Module *Imported) {
568 if (MDC.ScanInstance.getPreprocessor().isInImportingCXXNamedModules()) {
569 P1689ModuleInfo RequiredModule;
570 RequiredModule.ModuleName = Path[0].getIdentifierInfo()->getName().str();
572 MDC.RequiredStdCXXModules.push_back(std::move(RequiredModule));
573 return;
574 }
575
576 handleImport(Imported);
577}
578
579void ModuleDepCollectorPP::handleImport(const Module *Imported) {
580 if (!Imported)
581 return;
582
583 const Module *TopLevelModule = Imported->getTopLevelModule();
584
585 if (MDC.isPrebuiltModule(TopLevelModule))
586 MDC.DirectPrebuiltModularDeps.insert(
587 {TopLevelModule, PrebuiltModuleDep{TopLevelModule}});
588 else {
589 MDC.DirectModularDeps.insert(TopLevelModule);
590 MDC.DirectImports.insert(Imported);
591 }
592}
593
595 FileID MainFileID = MDC.ScanInstance.getSourceManager().getMainFileID();
596 MDC.MainFile = std::string(MDC.ScanInstance.getSourceManager()
597 .getFileEntryRefForID(MainFileID)
598 ->getName());
599
600 auto &PP = MDC.ScanInstance.getPreprocessor();
601 if (PP.isInNamedModule()) {
602 P1689ModuleInfo ProvidedModule;
603 ProvidedModule.ModuleName = PP.getNamedModuleName();
605 ProvidedModule.IsStdCXXModuleInterface = PP.isInNamedInterfaceUnit();
606 // Don't put implementation (non partition) unit as Provide.
607 // Put the module as required instead. Since the implementation
608 // unit will import the primary module implicitly.
609 if (PP.isInImplementationUnit())
610 MDC.RequiredStdCXXModules.push_back(ProvidedModule);
611 else
612 MDC.ProvidedStdCXXModule = ProvidedModule;
613 }
614
615 if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
616 MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude);
617
618 for (StringRef VFS : MDC.ScanInstance.getHeaderSearchOpts().VFSOverlayFiles)
619 MDC.addFileDep(VFS);
620
621 if (Module *CurrentModule = PP.getCurrentModuleImplementation()) {
622 if (OptionalFileEntryRef CurrentModuleMap =
623 PP.getHeaderSearchInfo().getModuleMap().getModuleMapFileForUniquing(
624 CurrentModule))
625 MDC.addFileDep(CurrentModuleMap->getName());
626 }
627
628 for (const Module *M :
629 MDC.ScanInstance.getPreprocessor().getAffectingClangModules())
630 if (!MDC.isPrebuiltModule(M))
631 MDC.DirectModularDeps.insert(M);
632
633 MDC.addVisibleModules();
634
635 for (const Module *M : MDC.DirectModularDeps)
636 handleTopLevelModule(M);
637
638 MDC.Consumer.handleContextHash(
639 MDC.ScanInstance.getInvocation().getModuleHash());
640
641 MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts);
642
643 MDC.Consumer.handleProvidedAndRequiredStdCXXModules(
644 MDC.ProvidedStdCXXModule, MDC.RequiredStdCXXModules);
645
646 for (auto &&I : MDC.ModularDeps)
647 MDC.Consumer.handleModuleDependency(*I.second);
648
649 for (const Module *M : MDC.DirectModularDeps) {
650 auto It = MDC.ModularDeps.find(M);
651 // Only report direct dependencies that were successfully handled.
652 if (It != MDC.ModularDeps.end())
653 MDC.Consumer.handleDirectModuleDependency(It->second->ID);
654 }
655
656 for (auto &&I : MDC.VisibleModules)
657 MDC.Consumer.handleVisibleModule(std::string(I.getKey()));
658
659 for (auto &&I : MDC.FileDeps)
660 MDC.Consumer.handleFileDependency(I);
661
662 for (auto &&I : MDC.DirectPrebuiltModularDeps)
663 MDC.Consumer.handlePrebuiltModuleDependency(I.second);
664}
665
666std::optional<ModuleID>
667ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
668 assert(M == M->getTopLevelModule() && "Expected top level module!");
669
670 // A top-level module might not be actually imported as a module when
671 // -fmodule-name is used to compile a translation unit that imports this
672 // module. In that case it can be skipped. The appropriate header
673 // dependencies will still be reported as expected.
674 if (!M->getASTFile())
675 return {};
676
677 // If this module has been handled already, just return its ID.
678 if (auto ModI = MDC.ModularDeps.find(M); ModI != MDC.ModularDeps.end())
679 return ModI->second->ID;
680
681 auto OwnedMD = std::make_unique<ModuleDeps>();
682 ModuleDeps &MD = *OwnedMD;
683
685 MD.IsSystem = M->IsSystem;
686
687 // Start off with the assumption that this module is shareable when there
688 // are stable directories. As more dependencies are discovered, check if those
689 // come from the provided directories.
690 MD.IsInStableDirectories = !MDC.StableDirs.empty();
691
692 // For modules which use export_as link name, the linked product that of the
693 // corresponding export_as-named module.
696
697 ModuleMap &ModMapInfo =
698 MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
699
700 if (auto ModuleMap = ModMapInfo.getModuleMapFileForUniquing(M)) {
701 SmallString<128> Path = ModuleMap->getNameAsRequested();
702 ModMapInfo.canonicalizeModuleMapPath(Path);
703 MD.ClangModuleMapFile = std::string(Path);
704 }
705
707 MDC.ScanInstance.getASTReader()->getModuleManager().lookup(
708 *M->getASTFile());
709 MD.FileDepsBaseDir = MF->BaseDirectory;
710 MDC.ScanInstance.getASTReader()->visitInputFileInfos(
711 *MF, /*IncludeSystem=*/true,
712 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
713 // The __inferred_module.map file is an insignificant implementation
714 // detail of implicitly-built modules. The PCM will also report the
715 // actual on-disk module map file that allowed inferring the module,
716 // which is what we need for building the module explicitly
717 // Let's ignore this file.
718 if (IFI.UnresolvedImportedFilename.ends_with("__inferred_module.map"))
719 return;
720 MDC.addFileDep(MD, IFI.UnresolvedImportedFilename);
721 });
722
723 llvm::DenseSet<const Module *> SeenDeps;
724 addAllSubmodulePrebuiltDeps(M, MD, SeenDeps);
725 addAllSubmoduleDeps(M, MD, SeenDeps);
726 addAllAffectingClangModules(M, MD, SeenDeps);
727
728 SmallString<0> PathBuf;
729 PathBuf.reserve(256);
730 MDC.ScanInstance.getASTReader()->visitInputFileInfos(
731 *MF, /*IncludeSystem=*/true,
732 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
733 if (MD.IsInStableDirectories) {
734 auto FullFilePath = ASTReader::ResolveImportedPath(
735 PathBuf, IFI.UnresolvedImportedFilename, MF->BaseDirectory);
737 isPathInStableDir(MDC.StableDirs, *FullFilePath);
738 }
739 if (!(IFI.TopLevel && IFI.ModuleMap))
740 return;
742 "__inferred_module.map"))
743 return;
744 auto ResolvedFilenameAsRequested = ASTReader::ResolveImportedPath(
746 MF->BaseDirectory);
747 MD.ModuleMapFileDeps.emplace_back(*ResolvedFilenameAsRequested);
748 });
749
750 bool IgnoreCWD = false;
751 CowCompilerInvocation CI =
752 MDC.getInvocationAdjustedForModuleBuildWithoutOutputs(
753 MD, [&](CowCompilerInvocation &BuildInvocation) {
754 if (any(MDC.Service.getOptimizeArgs() &
758 *MDC.ScanInstance.getASTReader(), *MF,
759 MDC.PrebuiltModulesASTMap,
760 MDC.Service.getOptimizeArgs());
761
762 if (any(MDC.Service.getOptimizeArgs() &
765 BuildInvocation.getMutDiagnosticOpts(),
766 BuildInvocation.getFrontendOpts().IsSystemModule);
767
768 IgnoreCWD = any(MDC.Service.getOptimizeArgs() &
770 isSafeToIgnoreCWD(BuildInvocation);
771 if (IgnoreCWD) {
772 llvm::ErrorOr<std::string> CWD =
773 MDC.ScanInstance.getVirtualFileSystem()
774 .getCurrentWorkingDirectory();
775 if (CWD)
776 optimizeCWD(BuildInvocation, *CWD);
777 }
778 });
779
780 // Check provided input paths from the invocation for determining
781 // IsInStableDirectories.
784 areOptionsInStableDir(MDC.StableDirs, CI.getHeaderSearchOpts());
785
786 MDC.associateWithContextHash(CI, IgnoreCWD, MD);
787
788 // Finish the compiler invocation. Requires dependencies and the context hash.
789 MDC.addOutputPaths(CI, MD);
790
791 MD.BuildInfo = std::move(CI);
792
793 MDC.ModularDeps.insert({M, std::move(OwnedMD)});
794
795 return MD.ID;
796}
797
798static void forEachSubmoduleSorted(const Module *M,
799 llvm::function_ref<void(const Module *)> F) {
800 // Submodule order depends on order of header includes for inferred submodules
801 // we don't care about the exact order, so sort so that it's consistent across
802 // TUs to improve sharing.
804 llvm::stable_sort(Submodules, [](const Module *A, const Module *B) {
805 return A->Name < B->Name;
806 });
807 for (const Module *SubM : Submodules)
808 F(SubM);
809}
810
811void ModuleDepCollectorPP::addAllSubmodulePrebuiltDeps(
812 const Module *M, ModuleDeps &MD,
813 llvm::DenseSet<const Module *> &SeenSubmodules) {
814 addModulePrebuiltDeps(M, MD, SeenSubmodules);
815
816 forEachSubmoduleSorted(M, [&](const Module *SubM) {
817 addAllSubmodulePrebuiltDeps(SubM, MD, SeenSubmodules);
818 });
819}
820
821void ModuleDepCollectorPP::addModulePrebuiltDeps(
822 const Module *M, ModuleDeps &MD,
823 llvm::DenseSet<const Module *> &SeenSubmodules) {
824 for (const Module *Import : M->Imports)
825 if (Import->getTopLevelModule() != M->getTopLevelModule())
826 if (MDC.isPrebuiltModule(Import->getTopLevelModule()))
827 if (SeenSubmodules.insert(Import->getTopLevelModule()).second) {
828 MD.PrebuiltModuleDeps.emplace_back(Import->getTopLevelModule());
829 if (MD.IsInStableDirectories) {
830 auto PrebuiltModulePropIt = MDC.PrebuiltModulesASTMap.find(
831 MD.PrebuiltModuleDeps.back().PCMFile);
833 (PrebuiltModulePropIt != MDC.PrebuiltModulesASTMap.end()) &&
834 PrebuiltModulePropIt->second.isInStableDir();
835 }
836 }
837}
838
839void ModuleDepCollectorPP::addAllSubmoduleDeps(
840 const Module *M, ModuleDeps &MD,
841 llvm::DenseSet<const Module *> &AddedModules) {
842 addModuleDep(M, MD, AddedModules);
843
844 forEachSubmoduleSorted(M, [&](const Module *SubM) {
845 addAllSubmoduleDeps(SubM, MD, AddedModules);
846 });
847}
848
849void ModuleDepCollectorPP::addOneModuleDep(const Module *M, const ModuleID ID,
850 ModuleDeps &MD) {
851 MD.ClangModuleDeps.push_back(std::move(ID));
853 MD.IsInStableDirectories = MDC.ModularDeps[M]->IsInStableDirectories;
854}
855
856void ModuleDepCollectorPP::addModuleDep(
857 const Module *M, ModuleDeps &MD,
858 llvm::DenseSet<const Module *> &AddedModules) {
859 for (const Module *Import : M->Imports) {
860 if (Import->getTopLevelModule() != M->getTopLevelModule() &&
861 !MDC.isPrebuiltModule(Import)) {
862 if (auto ImportID = handleTopLevelModule(Import->getTopLevelModule()))
863 if (AddedModules.insert(Import->getTopLevelModule()).second)
864 addOneModuleDep(Import->getTopLevelModule(), *ImportID, MD);
865 }
866 }
867}
868
869void ModuleDepCollectorPP::addAllAffectingClangModules(
870 const Module *M, ModuleDeps &MD,
871 llvm::DenseSet<const Module *> &AddedModules) {
872 addAffectingClangModule(M, MD, AddedModules);
873
874 for (const Module *SubM : M->submodules())
875 addAllAffectingClangModules(SubM, MD, AddedModules);
876}
877
878void ModuleDepCollectorPP::addAffectingClangModule(
879 const Module *M, ModuleDeps &MD,
880 llvm::DenseSet<const Module *> &AddedModules) {
881 for (const Module *Affecting : M->AffectingClangModules) {
882 assert(Affecting == Affecting->getTopLevelModule() &&
883 "Not quite import not top-level module");
884 if (Affecting != M->getTopLevelModule() &&
885 !MDC.isPrebuiltModule(Affecting)) {
886 if (auto ImportID = handleTopLevelModule(Affecting))
887 if (AddedModules.insert(Affecting).second)
888 addOneModuleDep(Affecting, *ImportID, MD);
889 }
890 }
891}
892
895 std::unique_ptr<DependencyOutputOptions> Opts,
896 CompilerInstance &ScanInstance, DependencyConsumer &C,
897 DependencyActionController &Controller, CompilerInvocation OriginalCI,
898 const PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
899 const ArrayRef<StringRef> StableDirs)
900 : Service(Service), ScanInstance(ScanInstance), Consumer(C),
901 Controller(Controller),
902 PrebuiltModulesASTMap(std::move(PrebuiltModulesASTMap)),
903 StableDirs(StableDirs), Opts(std::move(Opts)),
904 CommonInvocation(
905 makeCommonInvocationForModuleBuild(std::move(OriginalCI))) {}
906
908 auto CollectorPP = std::make_unique<ModuleDepCollectorPP>(*this);
909 CollectorPPPtr = CollectorPP.get();
910 PP.addPPCallbacks(std::move(CollectorPP));
911}
912
914
915bool ModuleDepCollector::isPrebuiltModule(const Module *M) {
916 std::string Name(M->getTopLevelModuleName());
917 const auto &PrebuiltModuleFiles =
919 auto PrebuiltModuleFileIt = PrebuiltModuleFiles.find(Name);
920 if (PrebuiltModuleFileIt == PrebuiltModuleFiles.end())
921 return false;
922 assert("Prebuilt module came from the expected AST file" &&
923 PrebuiltModuleFileIt->second == M->getASTFile()->getName());
924 return true;
925}
926
927void ModuleDepCollector::addVisibleModules() {
928 llvm::DenseSet<const Module *> ImportedModules;
929 auto InsertVisibleModules = [&](const Module *M) {
930 if (ImportedModules.contains(M))
931 return;
932
933 VisibleModules.insert(M->getTopLevelModuleName());
935 M->getExportedModules(Stack);
936 while (!Stack.empty()) {
937 const Module *CurrModule = Stack.pop_back_val();
938 if (ImportedModules.contains(CurrModule))
939 continue;
940 ImportedModules.insert(CurrModule);
941 VisibleModules.insert(CurrModule->getTopLevelModuleName());
942 CurrModule->getExportedModules(Stack);
943 }
944 };
945
946 for (const Module *Import : DirectImports)
947 InsertVisibleModules(Import);
948}
949
950static StringRef makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path,
951 SmallVectorImpl<char> &Storage) {
952 if (llvm::sys::path::is_absolute(Path) &&
953 !llvm::sys::path::is_style_windows(llvm::sys::path::Style::native))
954 return Path;
955 Storage.assign(Path.begin(), Path.end());
956 CI.getFileManager().makeAbsolutePath(Storage);
957 llvm::sys::path::make_preferred(Storage);
958 return StringRef(Storage.data(), Storage.size());
959}
960
961void ModuleDepCollector::addFileDep(StringRef Path) {
962 if (Service.getFormat() == ScanningOutputFormat::P1689) {
963 // Within P1689 format, we don't want all the paths to be absolute path
964 // since it may violate the traditional make style dependencies info.
965 FileDeps.emplace_back(Path);
966 return;
967 }
968
969 llvm::SmallString<256> Storage;
970 Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage);
971 FileDeps.emplace_back(Path);
972}
973
974void ModuleDepCollector::addFileDep(ModuleDeps &MD, StringRef Path) {
975 MD.FileDeps.emplace_back(Path);
976}
static std::vector< std::string > splitString(std::string S, char Separator)
static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts, ASTReader &Reader, const serialization::ModuleFile &MF, const PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, ScanningOptimizations OptimizeArgs)
static void optimizeDiagnosticOpts(DiagnosticOptions &Opts, bool IsSystemModule)
static StringRef makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path, SmallVectorImpl< char > &Storage)
static CowCompilerInvocation makeCommonInvocationForModuleBuild(CompilerInvocation CI)
static void forEachSubmoduleSorted(const Module *M, llvm::function_ref< void(const Module *)> F)
static bool needsModules(FrontendInputFile FIF)
static bool isSafeToIgnoreCWD(const CowCompilerInvocation &CI)
static std::string getModuleContextHash(const ModuleDeps &MD, const CowCompilerInvocation &CI, bool EagerLoadModules, bool IgnoreCWD, llvm::vfs::FileSystem &VFS)
static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD)
#define SM(sm)
Defines the clang::Preprocessor interface.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Reads an AST files chain containing the contents of a translation unit.
Definition ASTReader.h:430
static TemporarilyOwnedStringRef ResolveImportedPath(SmallString< 0 > &Buf, StringRef Path, ModuleFile &ModF)
Resolve Path in the context of module file M.
Represents a character-granular source range.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
std::string CoverageNotesFile
The filename with path we use for coverage notes files.
std::string ProfileInstrumentUsePath
Name of the profile file to use as input for -fprofile-instr-use.
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
std::string CoverageDataFile
The filename with path we use for coverage data files.
std::string DebugCompilationDir
The string to embed in debug information as the current working directory.
std::string MainFileName
The user provided name for the "main file", if non-empty.
std::string CoverageCompilationDir
The string to embed in coverage mapping as the current working directory.
std::string ProfileRemappingFile
Name of the profile remapping file to apply to the profile data supplied by -fprofile-sample-use or -...
std::string DwarfDebugFlags
The string to embed in the debug information for the compile unit, if non-empty.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
FileManager & getFileManager() const
Return the current file manager to the caller.
IntrusiveRefCntPtr< ASTReader > getASTReader() const
Preprocessor & getPreprocessor() const
Return the current preprocessor.
HeaderSearchOptions & getHeaderSearchOpts()
const FrontendOptions & getFrontendOpts() const
void visitPaths(llvm::function_ref< bool(StringRef)> Callback) const
Visitation.
void generateCC1CommandLine(llvm::SmallVectorImpl< const char * > &Args, StringAllocator SA) const
Generate cc1-compatible command line arguments from this instance.
const DependencyOutputOptions & getDependencyOutputOpts() const
const HeaderSearchOptions & getHeaderSearchOpts() const
const DiagnosticOptions & getDiagnosticOpts() const
Helper class for holding the data necessary to invoke the compiler.
PreprocessorOptions & getPreprocessorOpts()
void clearImplicitModuleBuildOptions()
Disable implicit modules and canonicalize options that are only used by implicit modules.
LangOptions & getLangOpts()
Mutable getters.
DependencyOutputOptions & getDependencyOutputOpts()
void resetNonModularOptions()
Reset all of the options that are not considered when building a module.
FrontendOptions & getFrontendOpts()
CodeGenOptions & getCodeGenOpts()
HeaderSearchOptions & getHeaderSearchOpts()
DiagnosticOptions & getDiagnosticOpts()
Same as CompilerInvocation, but with copy-on-write optimization.
LangOptions & getMutLangOpts()
Mutable getters.
HeaderSearchOptions & getMutHeaderSearchOpts()
FileSystemOptions & getMutFileSystemOpts()
DiagnosticOptions & getMutDiagnosticOpts()
DependencyOutputOptions & getMutDependencyOutputOpts()
std::string OutputFile
The file to write dependency output to.
std::vector< std::string > Targets
A list of names to use as the targets in the dependency file; this list must contain at least one ent...
Options for controlling the compiler diagnostics engine.
std::vector< std::string > Remarks
The list of -R... options used to alter the diagnostic mappings, with the prefixes removed.
std::vector< std::string > Warnings
The list of -W... options used to alter the diagnostic mappings, with the prefixes removed.
std::vector< std::string > UndefPrefixes
The list of prefixes from -Wundef-prefix=... used to generate warnings for undefined macros.
std::vector< std::string > SystemHeaderWarningsModules
The list of -Wsystem-headers-in-module=... options used to override whether -Wsystem-headers is enabl...
std::string DiagnosticSerializationFile
The file to serialize diagnostics to (non-appending).
StringRef getName() const
The name of this FileEntry.
Definition FileEntry.h:61
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool makeAbsolutePath(SmallVectorImpl< char > &Path) const
Makes Path absolute taking into account FileSystemOptions and the working directory option.
std::string WorkingDir
If set, paths are resolved as if the working directory was set to the value of WorkingDir.
An input file for the front end.
InputKind getKind() const
InputKind DashX
The input kind, either specified via -x argument or deduced from the input file name.
std::vector< std::string > ModuleFiles
The list of additional prebuilt module files to load before processing the input.
unsigned IsSystemModule
When using -emit-module, treat the modulemap as a system module.
std::vector< std::string > LLVMArgs
A list of arguments to forward to LLVM's option processing; this should only be used for debugging an...
std::string OutputFile
The output file, if any.
unsigned GenReducedBMI
Whether to generate reduced BMI for C++20 named modules.
std::string ModuleOutputPath
Output Path for module output file.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
frontend::ActionKind ProgramAction
The frontend action to perform.
std::vector< std::string > ModuleMapFiles
The list of module map files to load before processing the input.
HeaderSearchOptions - Helper class for storing options related to the initialization of the HeaderSea...
unsigned ModulesPruneNonAffectingModuleMaps
Whether to prune non-affecting module map files from PCM files.
std::map< std::string, std::string, std::less<> > PrebuiltModuleFiles
The mapping of module names to prebuilt module files.
unsigned ModulesSkipHeaderSearchPaths
Whether to entirely skip writing header search paths.
std::vector< SystemHeaderPrefix > SystemHeaderPrefixes
User-specified system header prefixes.
std::string Sysroot
If non-empty, the directory to use as a "virtual system root" for include paths.
unsigned ModulesSkipDiagnosticOptions
Whether to entirely skip writing diagnostic options.
llvm::SmallSetVector< llvm::CachedHashString, 16 > ModulesIgnoreMacros
The set of macro names that should be ignored for the purposes of computing the module hash.
std::vector< std::string > VFSOverlayFiles
The set of user-provided virtual filesystem overlay files.
std::vector< Entry > UserEntries
User specified include entries.
std::string ResourceDir
The directory which holds the compiler resource files (builtin includes, etc.).
ModuleMap & getModuleMap()
Retrieve the module map.
Language getLanguage() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
std::string ModuleName
The module currently being compiled as specified by -fmodule-name.
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
std::error_code canonicalizeModuleMapPath(SmallVectorImpl< char > &Path)
Canonicalize Path in a manner suitable for a module map file.
Describes a module or submodule.
Definition Module.h:144
StringRef getTopLevelModuleName() const
Retrieve the name of the top-level module.
Definition Module.h:732
llvm::SmallSetVector< Module *, 2 > Imports
The set of modules imported by this module, and on which this module depends.
Definition Module.h:458
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
Definition Module.h:389
std::string Name
The name of this module.
Definition Module.h:147
llvm::iterator_range< submodule_iterator > submodules()
Definition Module.h:838
llvm::SmallVector< LinkLibrary, 2 > LinkLibraries
The set of libraries or frameworks to link against when an entity from this module is used.
Definition Module.h:520
llvm::SmallSetVector< Module *, 2 > AffectingClangModules
The set of top-level modules that affected the compilation of this module, but were not imported.
Definition Module.h:462
void getExportedModules(SmallVectorImpl< Module * > &Exported) const
Appends this module's list of exported modules to Exported.
Definition Module.cpp:383
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
Definition Module.cpp:239
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
Definition Module.h:722
OptionalFileEntryRef getASTFile() const
The serialized AST file for this module, if one was created.
Definition Module.h:737
bool UseExportAsModuleLinkName
Autolinking uses the framework name for linking purposes when this is false and the export_as name ot...
Definition Module.h:524
std::vector< std::pair< std::string, bool > > Macros
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Module * getCurrentModuleImplementation()
Retrieves the module whose implementation we're current compiling, if any.
HeaderSearch & getHeaderSearchInfo() const
Encodes a location in the source.
This class handles loading and caching of source files into memory.
Token - This structure provides full information about a lexed token.
Definition Token.h:36
Dependency scanner callbacks that are used during scanning to influence the behaviour of the scan - f...
The dependency scanning service contains shared configuration and state that is used by the individua...
void EndOfMainFile() override
Callback invoked when the end of the main file is reached.
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) override
Callback invoked whenever an inclusion directive of any kind (#include, #import, etc....
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) override
Callback invoked whenever the Lexer moves to a different file for lexing.
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported) override
Callback invoked whenever there was an explicit module-import syntax.
ModuleDepCollector(DependencyScanningService &Service, std::unique_ptr< DependencyOutputOptions > Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, DependencyActionController &Controller, CompilerInvocation OriginalCI, const PrebuiltModulesAttrsMap PrebuiltModulesASTMap, const ArrayRef< StringRef > StableDirs)
void applyDiscoveredDependencies(CompilerInvocation &CI)
Apply any changes implied by the discovered dependencies to the given invocation, (e....
void attachToPreprocessor(Preprocessor &PP) override
void attachToASTReader(ASTReader &R) override
void updateDependentsNotInStableDirs(PrebuiltModulesAttrsMap &PrebuiltModulesMap)
When a module is discovered to not be in stable directories, traverse & update all modules that depen...
bool isInStableDir() const
Read-only access to whether the module is made up of dependencies in stable directories.
void setInStableDir(bool V=false)
Update whether the prebuilt module resolves entirely in a stable directories.
Information about a module that has been loaded by the ASTReader.
Definition ModuleFile.h:130
std::string FileName
The file name of the module file.
Definition ModuleFile.h:145
llvm::SetVector< ModuleFile * > Imports
List of modules which this module directly imported.
Definition ModuleFile.h:494
llvm::BitVector SearchPathUsage
The bit vector denoting usage of each header search entry (true = used).
Definition ModuleFile.h:196
llvm::BitVector VFSUsage
The bit vector denoting usage of each VFS entry (true = used).
Definition ModuleFile.h:199
ModuleKind Kind
The type of this module.
Definition ModuleFile.h:142
std::string BaseDirectory
The base directory of the module.
Definition ModuleFile.h:151
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool areOptionsInStableDir(const ArrayRef< StringRef > Directories, const HeaderSearchOptions &HSOpts)
Determine if options collected from a module's compilation can safely be considered as stable.
@ VFS
Remove unused -ivfsoverlay arguments.
@ IgnoreCWD
Ignore the compiler's working directory if it is safe.
@ SystemWarnings
Remove warnings from system modules.
@ HeaderSearch
Remove unused header search paths including header maps.
@ DiagnosticSerializationFile
The path of the serialized diagnostic file (.dia), if any.
@ DependencyFile
The path of the dependency file (.d), if any.
@ DependencyTargets
The null-separated list of names to use as the targets in the dependency file, if any.
@ ModuleFile
The module file (.pcm). Required.
llvm::StringMap< PrebuiltModuleASTAttrs > PrebuiltModulesAttrsMap
Attributes loaded from AST files of prebuilt modules collected prior to ModuleDepCollector creation.
bool isPathInStableDir(const ArrayRef< StringRef > Directories, const StringRef Input)
Determine if Input can be resolved within a stable directory.
@ P1689
This outputs the dependency graph for standard c++ modules in P1689R5 format.
void resetBenignCodeGenOptions(frontend::ActionKind ProgramAction, const LangOptions &LangOpts, CodeGenOptions &CGOpts)
Resets codegen options that don't affect modules/PCH.
@ GeneratePCH
Generate pre-compiled header.
@ GenerateModule
Generate pre-compiled module from a module map.
const unsigned VERSION_MINOR
AST file minor version number supported by this version of Clang.
Definition ASTBitCodes.h:57
const unsigned VERSION_MAJOR
AST file major version number supported by this version of Clang.
Definition ASTBitCodes.h:47
@ MK_ImplicitModule
File is an implicitly-loaded module.
Definition ModuleFile.h:45
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:208
void quoteMakeTarget(StringRef Target, SmallVectorImpl< char > &Res)
Quote target names for inclusion in GNU Make dependency files.
ArrayRef< IdentifierLoc > ModuleIdPath
A sequence of identifier/location pairs used to describe a particular module or submodule,...
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
Definition Linkage.h:54
@ Asm
Assembly: we accept this only so that we can preprocess it.
std::string getClangFullRepositoryVersion()
Retrieves the full repository version that is an amalgamation of the information in getClangRepositor...
Definition Version.cpp:68
int const char * function
Definition c++config.h:31
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
std::vector< std::string > ModuleMapFileDeps
A collection of absolute paths to module map files that this module needs to know about.
bool IsInStableDirectories
Whether this module is fully composed of file & module inputs from locations likely to stay the same ...
ModuleID ID
The identifier of the module.
void forEachFileDep(llvm::function_ref< void(StringRef)> Cb) const
Invokes Cb for all file dependencies of this module.
std::vector< PrebuiltModuleDep > PrebuiltModuleDeps
A collection of prebuilt modular dependencies this module directly depends on, not including transiti...
llvm::SmallVector< Module::LinkLibrary, 2 > LinkLibraries
The set of libraries or frameworks to link against when an entity from this module is used.
std::vector< ModuleID > ClangModuleDeps
A list of module identifiers this module directly depends on, not including transitive dependencies.
const std::vector< std::string > & getBuildArguments() const
Get (or compute) the compiler invocation that can be used to build this module.
std::string ClangModuleMapFile
The path to the modulemap file which defines this module.
bool IsSystem
Whether this is a "system" module.
This is used to identify a specific module.
std::string ModuleName
The name of the module.
std::string ContextHash
The context hash of a module represents the compiler options that affect the resulting command-line i...
P1689ModuleInfo - Represents the needed information of standard C++20 modules for P1689 format.
bool IsStdCXXModuleInterface
If this module is a standard c++ interface unit.
std::string ModuleName
The name of the module. This may include : for partitions.
Modular dependency that has already been built prior to the dependency scan.
The input file info that has been loaded from an AST file.
Definition ModuleFile.h:64