clang 24.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
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/Support/BLAKE3.h"
19#include <optional>
20
21using namespace clang;
22using namespace dependencies;
23
27 Dep.ModuleName = MF->ModuleName;
28 Dep.PCMFile = MF->FileName.str();
30 return Dep;
31}
32
34 PrebuiltModulesAttrsMap &PrebuiltModulesMap) {
36 for (const auto Dep : ModuleFileDependents) {
37 if (!PrebuiltModulesMap[Dep].isInStableDir())
38 return;
39 PrebuiltModulesMap[Dep].updateDependentsNotInStableDirs(PrebuiltModulesMap);
40 }
41}
42
43static void
46 const PrebuiltModulesAttrsMap &PrebuiltModulesASTMap,
47 ScanningOptimizations OptimizeArgs) {
48 if (any(OptimizeArgs & ScanningOptimizations::HeaderSearch)) {
49 // Only preserve search paths that were used during the dependency scan.
50 std::vector<HeaderSearchOptions::Entry> Entries;
51 std::swap(Opts.UserEntries, Entries);
52
53 llvm::BitVector SearchPathUsage(Entries.size());
54 llvm::DenseSet<const serialization::ModuleFile *> Visited;
55 std::function<void(const serialization::ModuleFile *)> VisitMF =
56 [&](const serialization::ModuleFile *MF) {
57 SearchPathUsage |= MF->SearchPathUsage;
58 Visited.insert(MF);
59 for (const serialization::ModuleFile *Import : MF->Imports)
60 if (!Visited.contains(Import))
61 VisitMF(Import);
62 };
63 VisitMF(&MF);
64
65 if (SearchPathUsage.size() != Entries.size())
66 llvm::report_fatal_error(
67 "Inconsistent search path options between modules detected");
68
69 for (auto Idx : SearchPathUsage.set_bits())
70 Opts.UserEntries.push_back(std::move(Entries[Idx]));
71 }
72 if (any(OptimizeArgs & ScanningOptimizations::VFS)) {
73 std::vector<std::string> VFSOverlayFiles;
74 std::swap(Opts.VFSOverlayFiles, VFSOverlayFiles);
75
76 llvm::BitVector VFSUsage(VFSOverlayFiles.size());
77 llvm::DenseSet<const serialization::ModuleFile *> Visited;
78 std::function<void(const serialization::ModuleFile *)> VisitMF =
79 [&](const serialization::ModuleFile *MF) {
80 Visited.insert(MF);
82 VFSUsage |= MF->VFSUsage;
83 // We only need to recurse into implicit modules. Other module types
84 // will have the correct set of VFSs for anything they depend on.
85 for (const serialization::ModuleFile *Import : MF->Imports)
86 if (!Visited.contains(Import))
87 VisitMF(Import);
88 } else {
89 // This is not an implicitly built module, so it may have different
90 // VFS options. Fall back to a string comparison instead.
91 auto PrebuiltModulePropIt =
92 PrebuiltModulesASTMap.find(MF->FileName);
93 if (PrebuiltModulePropIt == PrebuiltModulesASTMap.end())
94 return;
95 for (std::size_t I = 0, E = VFSOverlayFiles.size(); I != E; ++I) {
96 if (PrebuiltModulePropIt->second.getVFS().contains(
97 VFSOverlayFiles[I]))
98 VFSUsage[I] = true;
99 }
100 }
101 };
102 VisitMF(&MF);
103
104 if (VFSUsage.size() != VFSOverlayFiles.size())
105 llvm::report_fatal_error(
106 "Inconsistent -ivfsoverlay options between modules detected");
107
108 for (auto Idx : VFSUsage.set_bits())
109 Opts.VFSOverlayFiles.push_back(std::move(VFSOverlayFiles[Idx]));
110 }
111}
112
114 bool IsSystemModule) {
115 // If this is not a system module or -Wsystem-headers was passed, don't
116 // optimize.
117 if (!IsSystemModule)
118 return;
119 bool Wsystem_headers = false;
120 for (StringRef Opt : Opts.Warnings) {
121 bool isPositive = !Opt.consume_front("no-");
122 if (Opt == "system-headers")
123 Wsystem_headers = isPositive;
124 }
125 if (Wsystem_headers)
126 return;
127
128 // Remove all warning flags. System modules suppress most, but not all,
129 // warnings.
130 Opts.Warnings.clear();
131 Opts.UndefPrefixes.clear();
132 Opts.Remarks.clear();
133}
134
135static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) {
136 BuildInvocation.getMutFileSystemOpts().WorkingDir.clear();
137 BuildInvocation.getMutCodeGenOpts().DebugCompilationDir.clear();
138 BuildInvocation.getMutCodeGenOpts().CoverageCompilationDir.clear();
139}
140
141static std::vector<std::string> splitString(std::string S, char Separator) {
142 SmallVector<StringRef> Segments;
143 StringRef(S).split(Segments, Separator, /*MaxSplit=*/-1, /*KeepEmpty=*/false);
144 std::vector<std::string> Result;
145 Result.reserve(Segments.size());
146 for (StringRef Segment : Segments)
147 Result.push_back(Segment.str());
148 return Result;
149}
150
151void ModuleDepCollector::addOutputPaths(CowCompilerInvocation &CI,
152 ModuleDeps &Deps) {
154 Controller.lookupModuleOutput(Deps, ModuleOutputKind::ModuleFile);
157 Controller.lookupModuleOutput(
159 if (!CI.getDependencyOutputOpts().OutputFile.empty()) {
161 Controller.lookupModuleOutput(Deps, ModuleOutputKind::DependencyFile);
163 splitString(Controller.lookupModuleOutput(
165 '\0');
166 if (!CI.getDependencyOutputOpts().OutputFile.empty() &&
167 CI.getDependencyOutputOpts().Targets.empty()) {
168 // Fallback to -o as dependency target, as in the driver.
169 SmallString<128> Target;
171 CI.getMutDependencyOutputOpts().Targets.push_back(std::string(Target));
172 }
173 }
174}
175
177 const LangOptions &LangOpts,
178 CodeGenOptions &CGOpts) {
179 // TODO: Figure out better way to set options to their default value.
180 if (ProgramAction == frontend::GenerateModule) {
181 CGOpts.MainFileName.clear();
182 CGOpts.DwarfDebugFlags.clear();
183 }
184 if (ProgramAction == frontend::GeneratePCH ||
185 (ProgramAction == frontend::GenerateModule && !LangOpts.ModulesCodegen)) {
186 CGOpts.DebugCompilationDir.clear();
187 CGOpts.CoverageCompilationDir.clear();
188 CGOpts.CoverageDataFile.clear();
189 CGOpts.CoverageNotesFile.clear();
190 CGOpts.ProfileInstrumentUsePath.clear();
191 CGOpts.SampleProfileFile.clear();
192 CGOpts.ProfileRemappingFile.clear();
193 }
194}
195
197 const StringRef Input) {
198 using namespace llvm::sys;
199
200 if (!path::is_absolute(Input))
201 return false;
202
203 auto PathStartsWith = [](StringRef Prefix, StringRef Path) {
204 auto PrefixIt = path::begin(Prefix), PrefixEnd = path::end(Prefix);
205 for (auto PathIt = path::begin(Path), PathEnd = path::end(Path);
206 PrefixIt != PrefixEnd && PathIt != PathEnd; ++PrefixIt, ++PathIt) {
207 if (*PrefixIt != *PathIt)
208 return false;
209 }
210 return PrefixIt == PrefixEnd;
211 };
212
213 return any_of(Directories, [&](StringRef Dir) {
214 return !Dir.empty() && PathStartsWith(Dir, Input);
215 });
216}
217
219 const HeaderSearchOptions &HSOpts) {
220 assert(isPathInStableDir(Directories, HSOpts.Sysroot) &&
221 "Sysroots differ between module dependencies and current TU");
222
223 assert(isPathInStableDir(Directories, HSOpts.ResourceDir) &&
224 "ResourceDirs differ between module dependencies and current TU");
225
226 for (const auto &Entry : HSOpts.UserEntries) {
227 if (!Entry.IgnoreSysRoot)
228 continue;
229 if (!isPathInStableDir(Directories, Entry.Path))
230 return false;
231 }
232
233 for (const auto &SysPrefix : HSOpts.SystemHeaderPrefixes) {
234 if (!isPathInStableDir(Directories, SysPrefix.Prefix))
235 return false;
236 }
237
238 return true;
239}
240
245
246 // The scanner takes care to avoid passing non-affecting module maps to the
247 // explicit compiles. No need to do extra work just to find out there are no
248 // module map files to prune.
250
251 // Remove options incompatible with explicit module build or are likely to
252 // differ between identical modules discovered from different translation
253 // units.
254 CI.getFrontendOpts().Inputs.clear();
255 CI.getFrontendOpts().OutputFile.clear();
256 CI.getFrontendOpts().GenReducedBMI = false;
260 // LLVM options are not going to affect the AST
261 CI.getFrontendOpts().LLVMArgs.clear();
262
264 CI.getCodeGenOpts());
265
266 // Erase the command-line arguments. These don't make it into the final set of
267 // compilation arguments and will be re-populated during compilation itself.
268 // Keeping them around would make copies of the invocation expensive.
269 CI.getCodeGenOpts().Argv0 = nullptr;
270 CI.getCodeGenOpts().CommandLineArgs.clear();
271
272 // Map output paths that affect behaviour to "-" so their existence is in the
273 // context hash. The final path will be computed in addOutputPaths.
276 if (!CI.getDependencyOutputOpts().OutputFile.empty())
278 CI.getDependencyOutputOpts().Targets.clear();
280
282 CI.getLangOpts().ModuleName.clear();
283
284 // Remove any macro definitions that are explicitly ignored.
285 if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) {
286 llvm::erase_if(
288 [&CI](const std::pair<std::string, bool> &Def) {
289 StringRef MacroDef = Def.first;
290 return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
291 llvm::CachedHashString(MacroDef.split('=').first));
292 });
293 // Remove the now unused option.
295 }
296
297 // Remove any header search paths that are explicitly ignored.
299 llvm::erase_if(
301 [&CI](const HeaderSearchOptions::Entry &E) {
302 return CI.getHeaderSearchOpts().ModulesIgnoreSearchPaths.contains(
303 llvm::CachedHashString(E.Path));
304 });
305 // Remove the now unused option.
307 }
308
309 return CI;
310}
311
312CowCompilerInvocation
313ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs(
314 const ModuleDeps &Deps,
315 llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const {
316 CowCompilerInvocation CI = CommonInvocation;
317
320
321 // Inputs
322 InputKind ModuleMapInputKind(CI.getFrontendOpts().DashX.getLanguage(),
324 CI.getMutFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile,
325 ModuleMapInputKind);
326
327 // Remove directly passed modulemap files. They will get added back if they
328 // were actually used.
330
331 llvm::append_range(CI.getMutFrontendOpts().ModuleMapFiles,
332 Deps.ModuleMapFileDeps);
333
334 // Report the prebuilt modules this module uses.
335 for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps)
336 CI.getMutFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
337
338 // Add module file inputs from dependencies.
339 addModuleFiles(CI, Deps.ClangModuleDeps);
340
342 // Apply -Wsystem-headers-in-module for the current module.
343 if (llvm::is_contained(CI.getDiagnosticOpts().SystemHeaderWarningsModules,
344 Deps.ID.ModuleName))
345 CI.getMutDiagnosticOpts().Warnings.push_back("system-headers");
346 // Remove the now unused option(s).
348 }
349
350 Optimize(CI);
351
352 return CI;
353}
354
355static void
356collectModuleMap(std::vector<std::string> &ModuleMapFiles,
357 llvm::SmallDenseSet<const FileEntry *, 16> &SeenModuleMapFiles,
358 FileEntryRef ModuleMapFile, StringRef Path,
359 const bool Report) {
360 if (!SeenModuleMapFiles.insert(ModuleMapFile).second)
361 return;
362 // Conditionalize reporting for modes like eager module loading.
363 // That mode will have this information deserialized from the PCM instead.
364 // TODO: Verify this works fine when modulemap for module A is eagerly
365 // loaded from A.pcm, and module map passed on the command line contains
366 // definition of a submodule: "explicit module A.Private { ... }".
367 if (Report)
368 ModuleMapFiles.emplace_back(Path);
369}
370
371void ModuleDepCollector::collectModuleMapFiles(
372 std::vector<std::string> &ModuleMapFiles,
373 llvm::SmallDenseSet<const FileEntry *, 16> &SeenModuleMapFiles,
374 ArrayRef<ModuleID> ClangModuleDeps) const {
375 // Add each dependency's module map, in the order the PCM recorded its
376 // imports. This is expected to be a stable order across runs and workers.
377 for (const ModuleID &MID : ClangModuleDeps) {
378 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
379 assert(MD && "Inconsistent dependency info");
380 // TODO: Track ClangModuleMapFile as `FileEntryRef`.
381 auto FE = ScanInstance.getFileManager().getOptionalFileRef(
383 assert(FE && "Missing module map file that was previously found");
384 if (!FE)
385 continue;
386
387 collectModuleMap(ModuleMapFiles, SeenModuleMapFiles, *FE,
389 /*Report=*/!Service.getOpts().EagerLoadModules);
390 }
391}
392
393void ModuleDepCollector::addModuleFiles(
394 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
395 for (const ModuleID &MID : ClangModuleDeps) {
396 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
397 std::string PCMPath =
398 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile);
399
400 if (Service.getOpts().EagerLoadModules)
401 CI.getFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
402 else
404 {MID.ModuleName, std::move(PCMPath)});
405 }
406}
407
408void ModuleDepCollector::addModuleFiles(
409 CowCompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
410 for (const ModuleID &MID : ClangModuleDeps) {
411 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
412 std::string PCMPath =
413 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile);
414
415 if (Service.getOpts().EagerLoadModules)
416 CI.getMutFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
417 else
419 {MID.ModuleName, std::move(PCMPath)});
420 }
421}
422
424 switch (FIF.getKind().getLanguage()) {
426 case Language::Asm:
428 return false;
429 default:
430 return true;
431 }
432}
433
437 CI.getLangOpts(), CI.getCodeGenOpts());
439
440 if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) {
441 Preprocessor &PP = ScanInstance.getPreprocessor();
442
443 SmallVector<ModuleID> DirectDeps;
444 for (const auto &KV : ModularDeps)
445 if (DirectModularDeps.contains(KV.first))
446 DirectDeps.push_back(KV.second->ID);
447
448 addModuleFiles(CI, DirectDeps);
449
450 for (const auto &KV : DirectPrebuiltModularDeps)
451 CI.getFrontendOpts().ModuleFiles.push_back(KV.second.PCMFile);
452
453 llvm::SmallDenseSet<const FileEntry *, 16> SeenModuleMapFiles;
454 const ModuleMap &ModMapInfo = PP.getHeaderSearchInfo().getModuleMap();
455 if (Module *CurrentModule = PP.getCurrentModuleImplementation())
456 if (OptionalFileEntryRef CurrentModuleMap =
457 ModMapInfo.getModuleMapFileForUniquing(CurrentModule))
459 SeenModuleMapFiles, *CurrentModuleMap,
460 CurrentModuleMap->getNameAsRequested(),
461 /*Report=*/true);
462
463 collectModuleMapFiles(CI.getFrontendOpts().ModuleMapFiles,
464 SeenModuleMapFiles, DirectDeps);
465 }
466}
467
469 // Check if the command line input uses relative paths.
470 // It is not safe to ignore the current working directory if any of the
471 // command line inputs use relative paths.
472 bool AnyRelative = false;
473 CI.visitPaths([&](StringRef Path) {
474 assert(!AnyRelative && "Continuing path visitation despite relative path");
475 AnyRelative |= !Path.empty() && !llvm::sys::path::is_absolute(Path);
476 return CowCompilerInvocation::VisitConstResult{/*Terminate=*/AnyRelative};
477 });
478 return !AnyRelative;
479}
480
481static std::string getModuleContextHash(const ModuleDeps &MD,
482 const CowCompilerInvocation &CI,
483 bool EagerLoadModules,
484 llvm::vfs::FileSystem &VFS) {
485 llvm::HashBuilder<llvm::TruncatedBLAKE3<16>, llvm::endianness::native>
486 HashBuilder;
487
488 // Hash the compiler version and serialization version to ensure the module
489 // will be readable.
490 HashBuilder.add(getClangFullRepositoryVersion());
492 llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory();
493 if (CWD && !MD.IgnoreCWD)
494 HashBuilder.add(*CWD);
495
496 // Hash the BuildInvocation without any input files.
497 SmallString<0> ArgVec;
498 ArgVec.reserve(4096);
499 CI.generateCC1CommandLine([&](const Twine &Arg) {
500 Arg.toVector(ArgVec);
501 ArgVec.push_back('\0');
502 });
503 HashBuilder.add(ArgVec);
504
505 // Hash the module dependencies. These paths may differ even if the invocation
506 // is identical if they depend on the contents of the files in the TU -- for
507 // example, case-insensitive paths to modulemap files. Usually such a case
508 // would indicate a missed optimization to canonicalize, but it may be
509 // difficult to canonicalize all cases when there is a VFS.
510 for (const auto &ID : MD.ClangModuleDeps) {
511 HashBuilder.add(ID.ModuleName);
512 HashBuilder.add(ID.ContextHash);
513 }
514
515 HashBuilder.add(EagerLoadModules);
516
517 llvm::BLAKE3Result<16> Hash = HashBuilder.final();
518 std::array<uint64_t, 2> Words;
519 static_assert(sizeof(Hash) == sizeof(Words), "Hash must match Words");
520 std::memcpy(Words.data(), Hash.data(), sizeof(Hash));
521 return toString(llvm::APInt(sizeof(Words) * 8, Words), 36, /*Signed=*/false);
522}
523
524void ModuleDepCollector::associateWithContextHash(
525 const CowCompilerInvocation &CI, ModuleDeps &Deps) {
526 Deps.ID.ContextHash =
527 getModuleContextHash(Deps, CI, Service.getOpts().EagerLoadModules,
528 ScanInstance.getVirtualFileSystem());
529 bool Inserted = ModuleDepsByID.insert({Deps.ID, &Deps}).second;
530 (void)Inserted;
531 assert(Inserted && "duplicate module mapping");
532}
533
534/// Callback that records textual includes and direct modular includes/imports
535/// during preprocessing.
537 /// The parent dependency collector.
539
540public:
542
544 SrcMgr::CharacteristicKind FileType, FileID PrevFID,
545 SourceLocation Loc) override {
547 return;
548
549 SourceManager &SM = MDC.ScanInstance.getSourceManager();
550
551 // Dependency generation really does want to go all the way to the
552 // file entry for a source location to find out what is depended on.
553 // We do not want #line markers to affect dependency generation!
554 if (std::optional<StringRef> Filename = SM.getNonBuiltinFilenameForID(FID))
555 MDC.addFileDep(llvm::sys::path::remove_leading_dotslash(*Filename));
556 }
557
558 void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
560 SrcMgr::CharacteristicKind FileType) override {
561 if (File)
562 MDC.addFileDep(File->getName());
563 }
564
565 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
566 StringRef FileName, bool IsAngled,
567 CharSourceRange FilenameRange,
568 OptionalFileEntryRef File, StringRef SearchPath,
569 StringRef RelativePath, const Module *SuggestedModule,
570 bool ModuleImported,
571 SrcMgr::CharacteristicKind FileType) override {
572 if (!File && !ModuleImported) {
573 // This is a non-modular include that HeaderSearch failed to find. Add it
574 // here as `FileChanged` will never see it.
575 MDC.addFileDep(FileName);
576 }
577 if (ModuleImported && SuggestedModule &&
578 MDC.ScanInstance.getPreprocessorOpts()
579 .DependencyScanningModuleMapImports)
580 MDC.addRequiredStdCXXModule(SuggestedModule->getFullModuleName());
581 MDC.handleImport(SuggestedModule);
582 }
583
585 const Module *Imported) override {
586 auto &PP = MDC.ScanInstance.getPreprocessor();
587 if (PP.getLangOpts().CPlusPlusModules && PP.isImportingCXXNamedModules()) {
588 MDC.addRequiredStdCXXModule(Path[0].getIdentifierInfo()->getName());
589 return;
590 }
591
592 MDC.handleImport(Imported);
593 }
594};
595
596void ModuleDepCollector::addRequiredStdCXXModule(StringRef ModuleName) {
597 if (llvm::any_of(RequiredStdCXXModules,
598 [ModuleName](const P1689ModuleInfo &RequiredModule) {
599 return RequiredModule.ModuleName == ModuleName;
600 }))
601 return;
602
603 P1689ModuleInfo RequiredModule;
604 RequiredModule.ModuleName = ModuleName.str();
606 RequiredStdCXXModules.push_back(std::move(RequiredModule));
607}
608
609void ModuleDepCollector::handleImport(const Module *Imported) {
610 auto &MDC = *this;
611
612 if (!Imported)
613 return;
614
615 const Module *TopLevelModule = Imported->getTopLevelModule();
616 const ModuleFileKey *MFKey = TopLevelModule->getASTFileKey();
617 if (!MFKey)
618 return;
620 MDC.ScanInstance.getASTReader()->getModuleManager().lookup(*MFKey);
621
622 if (MDC.isPrebuiltModule(MF))
623 MDC.DirectPrebuiltModularDeps.insert({MF, createPrebuiltModuleDep(MF)});
624 else {
625 MDC.DirectModularDeps.insert(MF);
626 MDC.DirectImports.insert(Imported);
627 }
628}
629
631 auto &MDC = *this;
632
633 FileID MainFileID = MDC.ScanInstance.getSourceManager().getMainFileID();
634 MDC.MainFile = std::string(MDC.ScanInstance.getSourceManager()
635 .getFileEntryRefForID(MainFileID)
636 ->getName());
637
638 auto &PP = MDC.ScanInstance.getPreprocessor();
639 if (PP.isInNamedModule()) {
640 P1689ModuleInfo ProvidedModule;
641 ProvidedModule.ModuleName = PP.getNamedModuleName();
643 ProvidedModule.IsStdCXXModuleInterface = PP.isInNamedInterfaceUnit();
644 // Don't put implementation (non partition) unit as Provide.
645 // Put the module as required instead. Since the implementation
646 // unit will import the primary module implicitly.
647 if (PP.isInImplementationUnit())
648 MDC.addRequiredStdCXXModule(ProvidedModule.ModuleName);
649 else
650 MDC.ProvidedStdCXXModule = ProvidedModule;
651 }
652
653 if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
654 MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude);
655
656 for (StringRef VFS : MDC.ScanInstance.getHeaderSearchOpts().VFSOverlayFiles)
657 MDC.addFileDep(VFS);
658
659 if (Module *CurrentModule = PP.getCurrentModuleImplementation()) {
660 if (OptionalFileEntryRef CurrentModuleMap =
661 PP.getHeaderSearchInfo().getModuleMap().getModuleMapFileForUniquing(
662 CurrentModule))
663 MDC.addFileDep(CurrentModuleMap->getName());
664 }
665
666 for (const Module *M :
667 MDC.ScanInstance.getPreprocessor().getAffectingClangModules()) {
669 MDC.ScanInstance.getASTReader()->getModuleManager().lookup(
670 *M->getASTFileKey());
671 if (!MDC.isPrebuiltModule(MF))
672 MDC.DirectModularDeps.insert(MF);
673 }
674
675 if (MDC.Service.getOpts().ReportVisibleModules)
676 MDC.addVisibleModules();
677
678 for (serialization::ModuleFile *MF : MDC.DirectModularDeps)
679 handleTopLevelModule(MF);
680
681 Consumer.handleContextHash(
682 MDC.ScanInstance.getInvocation().computeContextHash());
683
684 Consumer.handleDependencyOutputOpts(*MDC.Opts);
685
686 Consumer.handleProvidedAndRequiredStdCXXModules(MDC.ProvidedStdCXXModule,
687 MDC.RequiredStdCXXModules);
688
689 for (auto &&I : MDC.ModularDeps)
690 Consumer.handleModuleDependency(*I.second);
691
692 for (serialization::ModuleFile *MF : MDC.DirectModularDeps) {
693 auto It = MDC.ModularDeps.find(MF);
694 // Only report direct dependencies that were successfully handled.
695 if (It != MDC.ModularDeps.end())
696 Consumer.handleDirectModuleDependency(It->second->ID);
697 }
698
699 for (auto &&I : MDC.VisibleModules)
700 Consumer.handleVisibleModule(std::string(I.getKey()));
701
702 for (auto &&I : MDC.FileDeps)
703 Consumer.handleFileDependency(I);
704
705 for (auto &&I : MDC.DirectPrebuiltModularDeps)
706 Consumer.handlePrebuiltModuleDependency(I.second);
707}
708
710 StringRef Path,
711 SmallVectorImpl<char> &Storage) {
712 // FIXME: Consider skipping if path is already absolute & canonicalized.
713
714 Storage.assign(Path.begin(), Path.end());
715 CI.getFileManager().makeAbsolutePath(Storage, /*Canonicalize=*/true);
716 return StringRef(Storage.data(), Storage.size());
717}
718
719std::optional<ModuleID>
720ModuleDepCollector::handleTopLevelModule(serialization::ModuleFile *MF) {
721 auto &MDC = *this;
722
723 // If this module has been handled already, just return its ID.
724 if (auto ModI = MDC.ModularDeps.find(MF); ModI != MDC.ModularDeps.end())
725 return ModI->second->ID;
726
727 Module *M = MDC.ScanInstance.getPreprocessor()
728 .getHeaderSearchInfo()
729 .getModuleMap()
730 .findModule(MF->ModuleName);
731 assert(M && M == M->getTopLevelModule() &&
732 "ModuleFile without top-level Module");
733
734 auto OwnedMD = std::make_unique<ModuleDeps>();
735 ModuleDeps &MD = *OwnedMD;
736
737 MD.ID.ModuleName = MF->ModuleName;
738 MD.IsSystem = M->IsSystem;
739
740 // Start off with the assumption that this module is shareable when there
741 // are stable directories. As more dependencies are discovered, check if those
742 // come from the provided directories.
743 MD.IsInStableDirectories = !MDC.StableDirs.empty();
744
745 // For modules which use export_as link name, the linked product that of the
746 // corresponding export_as-named module.
749
750 ModuleMap &ModMapInfo =
751 MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
752
753 OptionalFileEntryRef CurrentModuleMapEntry =
754 ModMapInfo.getModuleMapFileForUniquing(M);
755 if (CurrentModuleMapEntry) {
756 SmallString<128> Path = CurrentModuleMapEntry->getNameAsRequested();
757 ModMapInfo.canonicalizeModuleMapPath(Path);
758 MD.ClangModuleMapFile = std::string(Path);
759 }
760
761 llvm::SmallString<256> Storage;
762 MD.FileDepsBaseDir =
763 makeAbsoluteAndCanonicalize(MDC.ScanInstance, MF->BaseDirectory, Storage);
764 MDC.ScanInstance.getASTReader()->visitInputFileInfos(
765 *MF, /*IncludeSystem=*/true,
766 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
767 // The __inferred_module.map file is an insignificant implementation
768 // detail of implicitly-built modules. The PCM will also report the
769 // actual on-disk module map file that allowed inferring the module,
770 // which is what we need for building the module explicitly
771 // Let's ignore this file.
772 if (IFI.UnresolvedImportedFilename.ends_with("__inferred_module.map"))
773 return;
774 MDC.addFileDep(MD, IFI.UnresolvedImportedFilename);
775 });
776
777 addAllModuleDeps(*MF, MD);
778
779 // Capture module map file dependencies.
780 llvm::SmallDenseSet<const FileEntry *, 16> SeenModuleMapFiles;
781 MDC.collectModuleMapFiles(MD.ModuleMapFileDeps, SeenModuleMapFiles,
782 MD.ClangModuleDeps);
783
784 SmallString<0> PathBuf;
785 PathBuf.reserve(256);
786 MDC.ScanInstance.getASTReader()->visitInputFileInfos(
787 *MF, /*IncludeSystem=*/true,
788 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
789 if (MD.IsInStableDirectories) {
790 auto FullFilePath = ASTReader::ResolveImportedPath(
791 PathBuf, IFI.UnresolvedImportedFilename, MF->BaseDirectory);
793 isPathInStableDir(MDC.StableDirs, *FullFilePath);
794 }
795 if (!(IFI.TopLevel && IFI.ModuleMap))
796 return;
798 "__inferred_module.map"))
799 return;
800 auto ResolvedFilenameAsRequested = ASTReader::ResolveImportedPath(
802 MF->BaseDirectory);
803
804 auto ModuleMapEntry =
805 MDC.ScanInstance.getFileManager().getOptionalFileRef(
806 *ResolvedFilenameAsRequested);
807 assert(ModuleMapEntry && "module map file entry not found");
808 if (!ModuleMapEntry)
809 return;
810
811 // Don't report module map file of the current module unless it also
812 // describes a dependency in ModuleMapFileDeps (for symmetry).
813 if (CurrentModuleMapEntry && *ModuleMapEntry == *CurrentModuleMapEntry)
814 return;
815
816 // Add additional modulemaps for input files the module
817 // dependencies did not already cover. e.g. A modulemap that only
818 // declares a submodule is recorded only as an input file.
819 // FIXME: It is not guaranteed to be in a stable order across runs or
820 // workers.
821 collectModuleMap(MD.ModuleMapFileDeps, SeenModuleMapFiles,
822 *ModuleMapEntry, *ResolvedFilenameAsRequested,
823 /*Report=*/true);
824 });
825
827
828 bool IgnoreCWD = false;
829 CowCompilerInvocation CI =
830 MDC.getInvocationAdjustedForModuleBuildWithoutOutputs(
831 MD, [&](CowCompilerInvocation &BuildInvocation) {
832 if (any(MDC.Service.getOpts().OptimizeArgs &
836 *MDC.ScanInstance.getASTReader(), *MF,
837 MDC.PrebuiltModulesASTMap,
838 MDC.Service.getOpts().OptimizeArgs);
839
840 if (any(MDC.Service.getOpts().OptimizeArgs &
843 BuildInvocation.getMutDiagnosticOpts(),
844 BuildInvocation.getFrontendOpts().IsSystemModule);
845
846 IgnoreCWD = any(MDC.Service.getOpts().OptimizeArgs &
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 // FIXME: Propagate errors up.
859 (void)MDC.Controller.finalizeModuleInvocation(MDC.ScanInstance, CI, MD);
860
861 // Check provided input paths from the invocation for determining
862 // IsInStableDirectories.
865 areOptionsInStableDir(MDC.StableDirs, CI.getHeaderSearchOpts());
866
867 MD.IgnoreCWD = IgnoreCWD;
868 MDC.associateWithContextHash(CI, MD);
869
870 // Finish the compiler invocation. Requires dependencies and the context hash.
871 MDC.addOutputPaths(CI, MD);
872
873 MD.BuildInfo = std::move(CI);
874
875 MDC.ModularDeps.insert({MF, std::move(OwnedMD)});
876
877 return MD.ID;
878}
879
880void ModuleDepCollector::addAllModuleDeps(serialization::ModuleFile &MF,
881 ModuleDeps &MD) {
882 auto &MDC = *this;
883
884 llvm::DenseSet<const Module *> Seen;
885 for (serialization::ModuleFile *Import : MF.Imports) {
886 if (MDC.isPrebuiltModule(Import)) {
887 MD.PrebuiltModuleDeps.push_back(createPrebuiltModuleDep(Import));
888 if (MD.IsInStableDirectories) {
889 auto It = MDC.PrebuiltModulesASTMap.find(
890 MD.PrebuiltModuleDeps.back().PCMFile);
892 It != MDC.PrebuiltModulesASTMap.end() && It->second.isInStableDir();
893 }
894 } else {
895 if (auto ID = handleTopLevelModule(Import)) {
896 MD.ClangModuleDeps.push_back(std::move(*ID));
899 MDC.ModularDeps[Import]->IsInStableDirectories;
900 }
901 }
902 }
903}
904
907 std::unique_ptr<DependencyOutputOptions> Opts,
908 CompilerInstance &ScanInstance, DependencyActionController &Controller,
909 CompilerInvocation OriginalCI,
910 const PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
911 const ArrayRef<StringRef> StableDirs)
912 : Service(Service), ScanInstance(ScanInstance), Controller(Controller),
913 PrebuiltModulesASTMap(std::move(PrebuiltModulesASTMap)),
914 StableDirs(StableDirs), Opts(std::move(Opts)),
915 CommonInvocation(
916 makeCommonInvocationForModuleBuild(std::move(OriginalCI))) {}
917
919 auto CollectorPP = std::make_unique<ModuleDepCollectorPP>(*this);
920 CollectorPPPtr = CollectorPP.get();
921 PP.addPPCallbacks(std::move(CollectorPP));
922}
923
925
926bool ModuleDepCollector::isPrebuiltModule(const serialization::ModuleFile *MF) {
927 const auto &PrebuiltModuleFiles =
929 auto PrebuiltModuleFileIt = PrebuiltModuleFiles.find(MF->ModuleName);
930 if (PrebuiltModuleFileIt == PrebuiltModuleFiles.end())
931 return false;
932 assert("Prebuilt module came from the expected AST file" &&
933 PrebuiltModuleFileIt->second == MF->FileName.str());
934 return true;
935}
936
937void ModuleDepCollector::addVisibleModules() {
938 llvm::DenseSet<const Module *> ImportedModules;
939 auto InsertVisibleModules = [&](const Module *M) {
940 if (ImportedModules.contains(M))
941 return;
942
943 VisibleModules.insert(M->getTopLevelModuleName());
945 M->getExportedModules(Stack);
946 while (!Stack.empty()) {
947 const Module *CurrModule = Stack.pop_back_val();
948 if (ImportedModules.contains(CurrModule))
949 continue;
950 ImportedModules.insert(CurrModule);
951 VisibleModules.insert(CurrModule->getTopLevelModuleName());
952 CurrModule->getExportedModules(Stack);
953 }
954 };
955
956 for (const Module *Import : DirectImports)
957 InsertVisibleModules(Import);
958}
959
960void ModuleDepCollector::addFileDep(StringRef Path) {
961 if (!Service.getOpts().ReportAbsolutePaths) {
962 FileDeps.emplace_back(Path);
963 return;
964 }
965
966 llvm::SmallString<256> Storage;
967 Path = makeAbsoluteAndCanonicalize(ScanInstance, Path, Storage);
968 FileDeps.emplace_back(Path);
969}
970
971void ModuleDepCollector::addFileDep(ModuleDeps &MD, StringRef Path) {
972 MD.FileDeps.emplace_back(Path);
973}
Result
Implement __builtin_bit_cast and related operations.
static std::vector< std::string > splitString(std::string S, char Separator)
static std::string getModuleContextHash(const ModuleDeps &MD, const CowCompilerInvocation &CI, bool EagerLoadModules, llvm::vfs::FileSystem &VFS)
static PrebuiltModuleDep createPrebuiltModuleDep(const serialization::ModuleFile *MF)
static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts, ASTReader &Reader, const serialization::ModuleFile &MF, const PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, ScanningOptimizations OptimizeArgs)
static void optimizeDiagnosticOpts(DiagnosticOptions &Opts, bool IsSystemModule)
static void collectModuleMap(std::vector< std::string > &ModuleMapFiles, llvm::SmallDenseSet< const FileEntry *, 16 > &SeenModuleMapFiles, FileEntryRef ModuleMapFile, StringRef Path, const bool Report)
static CowCompilerInvocation makeCommonInvocationForModuleBuild(CompilerInvocation CI)
static bool needsModules(FrontendInputFile FIF)
static bool isSafeToIgnoreCWD(const CowCompilerInvocation &CI)
static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD)
static StringRef makeAbsoluteAndCanonicalize(CompilerInstance &CI, StringRef Path, SmallVectorImpl< char > &Storage)
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.
Callback that records textual includes and direct modular includes/imports during preprocessing.
void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled, OptionalFileEntryRef File, SrcMgr::CharacteristicKind FileType) override
Hook called when a '__has_include' or '__has_include_next' directive is read.
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported) override
Callback invoked whenever there was an explicit module-import syntax.
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 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....
Reads an AST files chain containing the contents of a translation unit.
Definition ASTReader.h:427
static TemporarilyOwnedStringRef ResolveImportedPath(SmallString< 0 > &Buf, StringRef Path, ModuleFile &ModF)
Resolve Path in the context of module file M.
Represents a byte-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 -...
const char * Argv0
Executable and command-line used to create a given CompilerInvocation.
std::vector< std::string > CommandLineArgs
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.
HeaderSearchOptions & getHeaderSearchOpts()
const FrontendOptions & getFrontendOpts() const
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()
void visitPaths(llvm::function_ref< VisitConstResult(StringRef)> Cb) const
Visits paths stored in the invocation.
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...
unsigned IncludeModuleFiles
Include module file dependencies.
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).
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Definition FileEntry.h:57
StringRef getNameAsRequested() const
The name of this FileEntry, as originally requested without applying any remappings for VFS 'use-exte...
Definition FileEntry.h:68
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool makeAbsolutePath(SmallVectorImpl< char > &Path, bool Canonicalize=false) 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 by implicitly-built modules.
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.).
llvm::SmallSetVector< llvm::CachedHashString, 16 > ModulesIgnoreSearchPaths
The set of header search paths that should be ignored by implicitly-built modules.
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.
Deduplication key for a loaded module file in ModuleManager.
Definition Module.h:79
StringRef str() const
Returns the plain module file name.
Definition Module.h:188
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:340
StringRef getTopLevelModuleName() const
Retrieve the name of the top-level module.
Definition Module.h:953
const ModuleFileKey * getASTFileKey() const
The serialized AST file key for this module, if one was created.
Definition Module.h:964
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
Definition Module.h:592
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:723
void getExportedModules(SmallVectorImpl< Module * > &Exported) const
Appends this module's list of exported modules to Exported.
Definition Module.cpp:402
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:241
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
Definition Module.h:943
bool UseExportAsModuleLinkName
Autolinking uses the framework name for linking purposes when this is false and the export_as name ot...
Definition Module.h:727
This interface provides a way to observe the actions of the preprocessor as it does its thing.
Definition PPCallbacks.h:37
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.
std::optional< StringRef > getNonBuiltinFilenameForID(FileID FID) const
Returns the filename for the provided FileID, unless it's a built-in buffer that's not represented by...
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...
virtual void handleFileDependency(StringRef Filename)=0
virtual void handleDependencyOutputOpts(const DependencyOutputOptions &Opts)=0
virtual void handleModuleDependency(ModuleDeps MD)=0
virtual void handleVisibleModule(std::string ModuleName)=0
virtual void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD)=0
virtual void handleDirectModuleDependency(ModuleID MD)=0
virtual void handleContextHash(std::string Hash)=0
virtual void handleProvidedAndRequiredStdCXXModules(std::optional< P1689ModuleInfo > Provided, std::vector< P1689ModuleInfo > Requires)
The dependency scanning service contains shared configuration and state that is used by the individua...
void run(DependencyConsumer &Consumer)
Processes the accumulated dependency information and reports it to the Consumer.
ModuleDepCollector(DependencyScanningService &Service, std::unique_ptr< DependencyOutputOptions > Opts, CompilerInstance &ScanInstance, 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:158
std::vector< std::string > DirectoryDependencies
Directories this module file depends on the listing of.
Definition ModuleFile.h:208
llvm::SetVector< ModuleFile * > Imports
List of modules which this module directly imported.
Definition ModuleFile.h:558
llvm::BitVector SearchPathUsage
The bit vector denoting usage of each header search entry (true = used).
Definition ModuleFile.h:237
ModuleFileName FileName
The file name of the module file.
Definition ModuleFile.h:177
llvm::BitVector VFSUsage
The bit vector denoting usage of each VFS entry (true = used).
Definition ModuleFile.h:240
ModuleKind Kind
The type of this module.
Definition ModuleFile.h:174
std::string ModuleName
The name of the module.
Definition ModuleFile.h:183
std::string BaseDirectory
The base directory of the module.
Definition ModuleFile.h:186
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.
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:46
Top level wrappers for InstallAPI frontend operations.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:196
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.
@ MFDK_Direct
Include only directly imported module file dependencies.
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.
std::vector< std::string > DirectoryDeps
Absolute paths to directories this module depends on the listing of, including their subdirectories.
bool IgnoreCWD
Whether current working directory is ignored.
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.
std::string ClangModuleMapFile
The path to the modulemap file which defines this module.
bool IsSystem
Whether this is a "system" 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.