clang 23.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 // Map output paths that affect behaviour to "-" so their existence is in the
267 // context hash. The final path will be computed in addOutputPaths.
270 if (!CI.getDependencyOutputOpts().OutputFile.empty())
272 CI.getDependencyOutputOpts().Targets.clear();
274
276 CI.getLangOpts().ModuleName.clear();
277
278 // Remove any macro definitions that are explicitly ignored.
279 if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) {
280 llvm::erase_if(
282 [&CI](const std::pair<std::string, bool> &Def) {
283 StringRef MacroDef = Def.first;
284 return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
285 llvm::CachedHashString(MacroDef.split('=').first));
286 });
287 // Remove the now unused option.
289 }
290
291 return CI;
292}
293
294CowCompilerInvocation
295ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs(
296 const ModuleDeps &Deps,
297 llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const {
298 CowCompilerInvocation CI = CommonInvocation;
299
302
303 // Inputs
304 InputKind ModuleMapInputKind(CI.getFrontendOpts().DashX.getLanguage(),
306 CI.getMutFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile,
307 ModuleMapInputKind);
308
309 auto CurrentModuleMapEntry =
310 ScanInstance.getFileManager().getOptionalFileRef(Deps.ClangModuleMapFile);
311 assert(CurrentModuleMapEntry && "module map file entry not found");
312
313 // Remove directly passed modulemap files. They will get added back if they
314 // were actually used.
316
317 auto DepModuleMapFiles = collectModuleMapFiles(Deps.ClangModuleDeps);
318 for (StringRef ModuleMapFile : Deps.ModuleMapFileDeps) {
319 // TODO: Track these as `FileEntryRef` to simplify the equality check below.
320 auto ModuleMapEntry =
321 ScanInstance.getFileManager().getOptionalFileRef(ModuleMapFile);
322 assert(ModuleMapEntry && "module map file entry not found");
323
324 // Don't report module maps describing eagerly-loaded dependency. This
325 // information will be deserialized from the PCM.
326 // TODO: Verify this works fine when modulemap for module A is eagerly
327 // loaded from A.pcm, and module map passed on the command line contains
328 // definition of a submodule: "explicit module A.Private { ... }".
329 if (Service.getOpts().EagerLoadModules &&
330 DepModuleMapFiles.contains(*ModuleMapEntry))
331 continue;
332
333 // Don't report module map file of the current module unless it also
334 // describes a dependency (for symmetry).
335 if (*ModuleMapEntry == *CurrentModuleMapEntry &&
336 !DepModuleMapFiles.contains(*ModuleMapEntry))
337 continue;
338
339 CI.getMutFrontendOpts().ModuleMapFiles.emplace_back(ModuleMapFile);
340 }
341
342 // Report the prebuilt modules this module uses.
343 for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps)
344 CI.getMutFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
345
346 // Add module file inputs from dependencies.
347 addModuleFiles(CI, Deps.ClangModuleDeps);
348
350 // Apply -Wsystem-headers-in-module for the current module.
351 if (llvm::is_contained(CI.getDiagnosticOpts().SystemHeaderWarningsModules,
352 Deps.ID.ModuleName))
353 CI.getMutDiagnosticOpts().Warnings.push_back("system-headers");
354 // Remove the now unused option(s).
356 }
357
358 Optimize(CI);
359
360 return CI;
361}
362
363llvm::DenseSet<const FileEntry *> ModuleDepCollector::collectModuleMapFiles(
364 ArrayRef<ModuleID> ClangModuleDeps) const {
365 llvm::DenseSet<const FileEntry *> ModuleMapFiles;
366 for (const ModuleID &MID : ClangModuleDeps) {
367 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
368 assert(MD && "Inconsistent dependency info");
369 // TODO: Track ClangModuleMapFile as `FileEntryRef`.
370 auto FE = ScanInstance.getFileManager().getOptionalFileRef(
372 assert(FE && "Missing module map file that was previously found");
373 ModuleMapFiles.insert(*FE);
374 }
375 return ModuleMapFiles;
376}
377
378void ModuleDepCollector::addModuleMapFiles(
379 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
380 if (Service.getOpts().EagerLoadModules)
381 return; // Only pcm is needed for eager load.
382
383 for (const ModuleID &MID : ClangModuleDeps) {
384 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
385 assert(MD && "Inconsistent dependency info");
387 }
388}
389
390void ModuleDepCollector::addModuleFiles(
391 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
392 for (const ModuleID &MID : ClangModuleDeps) {
393 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
394 std::string PCMPath =
395 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile);
396
397 if (Service.getOpts().EagerLoadModules)
398 CI.getFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
399 else
401 {MID.ModuleName, std::move(PCMPath)});
402 }
403}
404
405void ModuleDepCollector::addModuleFiles(
406 CowCompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
407 for (const ModuleID &MID : ClangModuleDeps) {
408 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
409 std::string PCMPath =
410 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile);
411
412 if (Service.getOpts().EagerLoadModules)
413 CI.getMutFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
414 else
416 {MID.ModuleName, std::move(PCMPath)});
417 }
418}
419
421 switch (FIF.getKind().getLanguage()) {
423 case Language::Asm:
425 return false;
426 default:
427 return true;
428 }
429}
430
434 CI.getLangOpts(), CI.getCodeGenOpts());
436
437 if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) {
438 Preprocessor &PP = ScanInstance.getPreprocessor();
439 if (Module *CurrentModule = PP.getCurrentModuleImplementation())
440 if (OptionalFileEntryRef CurrentModuleMap =
442 .getModuleMap()
443 .getModuleMapFileForUniquing(CurrentModule))
444 CI.getFrontendOpts().ModuleMapFiles.emplace_back(
445 CurrentModuleMap->getNameAsRequested());
446
447 SmallVector<ModuleID> DirectDeps;
448 for (const auto &KV : ModularDeps)
449 if (DirectModularDeps.contains(KV.first))
450 DirectDeps.push_back(KV.second->ID);
451
452 // TODO: Report module maps the same way it's done for modular dependencies.
453 addModuleMapFiles(CI, DirectDeps);
454
455 addModuleFiles(CI, DirectDeps);
456
457 for (const auto &KV : DirectPrebuiltModularDeps)
458 CI.getFrontendOpts().ModuleFiles.push_back(KV.second.PCMFile);
459 }
460}
461
463 // Check if the command line input uses relative paths.
464 // It is not safe to ignore the current working directory if any of the
465 // command line inputs use relative paths.
466 bool AnyRelative = false;
467 CI.visitPaths([&](StringRef Path) {
468 assert(!AnyRelative && "Continuing path visitation despite returning true");
469 AnyRelative |= !Path.empty() && !llvm::sys::path::is_absolute(Path);
470 return AnyRelative;
471 });
472 return !AnyRelative;
473}
474
475static std::string getModuleContextHash(const ModuleDeps &MD,
476 const CowCompilerInvocation &CI,
477 bool EagerLoadModules,
478 llvm::vfs::FileSystem &VFS) {
479 llvm::HashBuilder<llvm::TruncatedBLAKE3<16>, llvm::endianness::native>
480 HashBuilder;
481
482 // Hash the compiler version and serialization version to ensure the module
483 // will be readable.
484 HashBuilder.add(getClangFullRepositoryVersion());
486 llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory();
487 if (CWD && !MD.IgnoreCWD)
488 HashBuilder.add(*CWD);
489
490 // Hash the BuildInvocation without any input files.
491 SmallString<0> ArgVec;
492 ArgVec.reserve(4096);
493 CI.generateCC1CommandLine([&](const Twine &Arg) {
494 Arg.toVector(ArgVec);
495 ArgVec.push_back('\0');
496 });
497 HashBuilder.add(ArgVec);
498
499 // Hash the module dependencies. These paths may differ even if the invocation
500 // is identical if they depend on the contents of the files in the TU -- for
501 // example, case-insensitive paths to modulemap files. Usually such a case
502 // would indicate a missed optimization to canonicalize, but it may be
503 // difficult to canonicalize all cases when there is a VFS.
504 for (const auto &ID : MD.ClangModuleDeps) {
505 HashBuilder.add(ID.ModuleName);
506 HashBuilder.add(ID.ContextHash);
507 }
508
509 HashBuilder.add(EagerLoadModules);
510
511 llvm::BLAKE3Result<16> Hash = HashBuilder.final();
512 std::array<uint64_t, 2> Words;
513 static_assert(sizeof(Hash) == sizeof(Words), "Hash must match Words");
514 std::memcpy(Words.data(), Hash.data(), sizeof(Hash));
515 return toString(llvm::APInt(sizeof(Words) * 8, Words), 36, /*Signed=*/false);
516}
517
518void ModuleDepCollector::associateWithContextHash(
519 const CowCompilerInvocation &CI, ModuleDeps &Deps) {
520 Deps.ID.ContextHash =
521 getModuleContextHash(Deps, CI, Service.getOpts().EagerLoadModules,
522 ScanInstance.getVirtualFileSystem());
523 bool Inserted = ModuleDepsByID.insert({Deps.ID, &Deps}).second;
524 (void)Inserted;
525 assert(Inserted && "duplicate module mapping");
526}
527
528/// Callback that records textual includes and direct modular includes/imports
529/// during preprocessing.
531 /// The parent dependency collector.
533
534public:
536
538 SrcMgr::CharacteristicKind FileType, FileID PrevFID,
539 SourceLocation Loc) override {
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
552 void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
554 SrcMgr::CharacteristicKind FileType) override {
555 if (File)
556 MDC.addFileDep(File->getName());
557 }
558
559 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
560 StringRef FileName, bool IsAngled,
561 CharSourceRange FilenameRange,
562 OptionalFileEntryRef File, StringRef SearchPath,
563 StringRef RelativePath, const Module *SuggestedModule,
564 bool ModuleImported,
565 SrcMgr::CharacteristicKind FileType) override {
566 if (!File && !ModuleImported) {
567 // This is a non-modular include that HeaderSearch failed to find. Add it
568 // here as `FileChanged` will never see it.
569 MDC.addFileDep(FileName);
570 }
571 MDC.handleImport(SuggestedModule);
572 }
573
575 const Module *Imported) override {
576 auto &PP = MDC.ScanInstance.getPreprocessor();
577 if (PP.getLangOpts().CPlusPlusModules && PP.isImportingCXXNamedModules()) {
578 P1689ModuleInfo RequiredModule;
579 RequiredModule.ModuleName = Path[0].getIdentifierInfo()->getName().str();
581 MDC.RequiredStdCXXModules.push_back(std::move(RequiredModule));
582 return;
583 }
584
585 MDC.handleImport(Imported);
586 }
587};
588
589void ModuleDepCollector::handleImport(const Module *Imported) {
590 auto &MDC = *this;
591
592 if (!Imported)
593 return;
594
595 const Module *TopLevelModule = Imported->getTopLevelModule();
596 const ModuleFileKey *MFKey = TopLevelModule->getASTFileKey();
597 if (!MFKey)
598 return;
600 MDC.ScanInstance.getASTReader()->getModuleManager().lookup(*MFKey);
601
602 if (MDC.isPrebuiltModule(MF))
603 MDC.DirectPrebuiltModularDeps.insert({MF, createPrebuiltModuleDep(MF)});
604 else {
605 MDC.DirectModularDeps.insert(MF);
606 MDC.DirectImports.insert(Imported);
607 }
608}
609
611 auto &MDC = *this;
612
613 FileID MainFileID = MDC.ScanInstance.getSourceManager().getMainFileID();
614 MDC.MainFile = std::string(MDC.ScanInstance.getSourceManager()
615 .getFileEntryRefForID(MainFileID)
616 ->getName());
617
618 auto &PP = MDC.ScanInstance.getPreprocessor();
619 if (PP.isInNamedModule()) {
620 P1689ModuleInfo ProvidedModule;
621 ProvidedModule.ModuleName = PP.getNamedModuleName();
623 ProvidedModule.IsStdCXXModuleInterface = PP.isInNamedInterfaceUnit();
624 // Don't put implementation (non partition) unit as Provide.
625 // Put the module as required instead. Since the implementation
626 // unit will import the primary module implicitly.
627 if (PP.isInImplementationUnit())
628 MDC.RequiredStdCXXModules.push_back(ProvidedModule);
629 else
630 MDC.ProvidedStdCXXModule = ProvidedModule;
631 }
632
633 if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
634 MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude);
635
636 for (StringRef VFS : MDC.ScanInstance.getHeaderSearchOpts().VFSOverlayFiles)
637 MDC.addFileDep(VFS);
638
639 if (Module *CurrentModule = PP.getCurrentModuleImplementation()) {
640 if (OptionalFileEntryRef CurrentModuleMap =
641 PP.getHeaderSearchInfo().getModuleMap().getModuleMapFileForUniquing(
642 CurrentModule))
643 MDC.addFileDep(CurrentModuleMap->getName());
644 }
645
646 for (const Module *M :
647 MDC.ScanInstance.getPreprocessor().getAffectingClangModules()) {
649 MDC.ScanInstance.getASTReader()->getModuleManager().lookup(
650 *M->getASTFileKey());
651 if (!MDC.isPrebuiltModule(MF))
652 MDC.DirectModularDeps.insert(MF);
653 }
654
655 if (MDC.Service.getOpts().ReportVisibleModules)
656 MDC.addVisibleModules();
657
658 for (serialization::ModuleFile *MF : MDC.DirectModularDeps)
659 handleTopLevelModule(MF);
660
661 Consumer.handleContextHash(
662 MDC.ScanInstance.getInvocation().computeContextHash());
663
664 Consumer.handleDependencyOutputOpts(*MDC.Opts);
665
666 Consumer.handleProvidedAndRequiredStdCXXModules(MDC.ProvidedStdCXXModule,
667 MDC.RequiredStdCXXModules);
668
669 for (auto &&I : MDC.ModularDeps)
670 Consumer.handleModuleDependency(*I.second);
671
672 for (serialization::ModuleFile *MF : MDC.DirectModularDeps) {
673 auto It = MDC.ModularDeps.find(MF);
674 // Only report direct dependencies that were successfully handled.
675 if (It != MDC.ModularDeps.end())
676 Consumer.handleDirectModuleDependency(It->second->ID);
677 }
678
679 for (auto &&I : MDC.VisibleModules)
680 Consumer.handleVisibleModule(std::string(I.getKey()));
681
682 for (auto &&I : MDC.FileDeps)
683 Consumer.handleFileDependency(I);
684
685 for (auto &&I : MDC.DirectPrebuiltModularDeps)
686 Consumer.handlePrebuiltModuleDependency(I.second);
687}
688
690 StringRef Path,
691 SmallVectorImpl<char> &Storage) {
692 // FIXME: Consider skipping if path is already absolute & canonicalized.
693
694 Storage.assign(Path.begin(), Path.end());
695 CI.getFileManager().makeAbsolutePath(Storage, /*Canonicalize=*/true);
696 return StringRef(Storage.data(), Storage.size());
697}
698
699std::optional<ModuleID>
700ModuleDepCollector::handleTopLevelModule(serialization::ModuleFile *MF) {
701 auto &MDC = *this;
702
703 // If this module has been handled already, just return its ID.
704 if (auto ModI = MDC.ModularDeps.find(MF); ModI != MDC.ModularDeps.end())
705 return ModI->second->ID;
706
707 Module *M = MDC.ScanInstance.getPreprocessor()
708 .getHeaderSearchInfo()
709 .getModuleMap()
710 .findModule(MF->ModuleName);
711 assert(M && M == M->getTopLevelModule() &&
712 "ModuleFile without top-level Module");
713
714 auto OwnedMD = std::make_unique<ModuleDeps>();
715 ModuleDeps &MD = *OwnedMD;
716
717 MD.ID.ModuleName = MF->ModuleName;
718 MD.IsSystem = M->IsSystem;
719
720 // Start off with the assumption that this module is shareable when there
721 // are stable directories. As more dependencies are discovered, check if those
722 // come from the provided directories.
723 MD.IsInStableDirectories = !MDC.StableDirs.empty();
724
725 // For modules which use export_as link name, the linked product that of the
726 // corresponding export_as-named module.
729
730 ModuleMap &ModMapInfo =
731 MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
732
733 if (auto ModuleMap = ModMapInfo.getModuleMapFileForUniquing(M)) {
734 SmallString<128> Path = ModuleMap->getNameAsRequested();
735 ModMapInfo.canonicalizeModuleMapPath(Path);
736 MD.ClangModuleMapFile = std::string(Path);
737 }
738
739 llvm::SmallString<256> Storage;
740 MD.FileDepsBaseDir =
741 makeAbsoluteAndCanonicalize(MDC.ScanInstance, MF->BaseDirectory, Storage);
742 MDC.ScanInstance.getASTReader()->visitInputFileInfos(
743 *MF, /*IncludeSystem=*/true,
744 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
745 // The __inferred_module.map file is an insignificant implementation
746 // detail of implicitly-built modules. The PCM will also report the
747 // actual on-disk module map file that allowed inferring the module,
748 // which is what we need for building the module explicitly
749 // Let's ignore this file.
750 if (IFI.UnresolvedImportedFilename.ends_with("__inferred_module.map"))
751 return;
752 MDC.addFileDep(MD, IFI.UnresolvedImportedFilename);
753 });
754
755 addAllModuleDeps(*MF, MD);
756
757 SmallString<0> PathBuf;
758 PathBuf.reserve(256);
759 MDC.ScanInstance.getASTReader()->visitInputFileInfos(
760 *MF, /*IncludeSystem=*/true,
761 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
762 if (MD.IsInStableDirectories) {
763 auto FullFilePath = ASTReader::ResolveImportedPath(
764 PathBuf, IFI.UnresolvedImportedFilename, MF->BaseDirectory);
766 isPathInStableDir(MDC.StableDirs, *FullFilePath);
767 }
768 if (!(IFI.TopLevel && IFI.ModuleMap))
769 return;
771 "__inferred_module.map"))
772 return;
773 auto ResolvedFilenameAsRequested = ASTReader::ResolveImportedPath(
775 MF->BaseDirectory);
776 MD.ModuleMapFileDeps.emplace_back(*ResolvedFilenameAsRequested);
777 });
778
779 bool IgnoreCWD = false;
780 CowCompilerInvocation CI =
781 MDC.getInvocationAdjustedForModuleBuildWithoutOutputs(
782 MD, [&](CowCompilerInvocation &BuildInvocation) {
783 if (any(MDC.Service.getOpts().OptimizeArgs &
787 *MDC.ScanInstance.getASTReader(), *MF,
788 MDC.PrebuiltModulesASTMap,
789 MDC.Service.getOpts().OptimizeArgs);
790
791 if (any(MDC.Service.getOpts().OptimizeArgs &
794 BuildInvocation.getMutDiagnosticOpts(),
795 BuildInvocation.getFrontendOpts().IsSystemModule);
796
797 IgnoreCWD = any(MDC.Service.getOpts().OptimizeArgs &
799 isSafeToIgnoreCWD(BuildInvocation);
800 if (IgnoreCWD) {
801 llvm::ErrorOr<std::string> CWD =
802 MDC.ScanInstance.getVirtualFileSystem()
803 .getCurrentWorkingDirectory();
804 if (CWD)
805 optimizeCWD(BuildInvocation, *CWD);
806 }
807 });
808
809 // FIXME: Propagate errors up.
810 (void)MDC.Controller.finalizeModuleInvocation(MDC.ScanInstance, CI, MD);
811
812 // Check provided input paths from the invocation for determining
813 // IsInStableDirectories.
816 areOptionsInStableDir(MDC.StableDirs, CI.getHeaderSearchOpts());
817
818 MD.IgnoreCWD = IgnoreCWD;
819 MDC.associateWithContextHash(CI, MD);
820
821 // Finish the compiler invocation. Requires dependencies and the context hash.
822 MDC.addOutputPaths(CI, MD);
823
824 MD.BuildInfo = std::move(CI);
825
826 MDC.ModularDeps.insert({MF, std::move(OwnedMD)});
827
828 return MD.ID;
829}
830
831void ModuleDepCollector::addAllModuleDeps(serialization::ModuleFile &MF,
832 ModuleDeps &MD) {
833 auto &MDC = *this;
834
835 llvm::DenseSet<const Module *> Seen;
836 for (serialization::ModuleFile *Import : MF.Imports) {
837 if (MDC.isPrebuiltModule(Import)) {
838 MD.PrebuiltModuleDeps.push_back(createPrebuiltModuleDep(Import));
839 if (MD.IsInStableDirectories) {
840 auto It = MDC.PrebuiltModulesASTMap.find(
841 MD.PrebuiltModuleDeps.back().PCMFile);
843 It != MDC.PrebuiltModulesASTMap.end() && It->second.isInStableDir();
844 }
845 } else {
846 if (auto ID = handleTopLevelModule(Import)) {
847 MD.ClangModuleDeps.push_back(std::move(*ID));
850 MDC.ModularDeps[Import]->IsInStableDirectories;
851 }
852 }
853 }
854}
855
858 std::unique_ptr<DependencyOutputOptions> Opts,
859 CompilerInstance &ScanInstance, DependencyActionController &Controller,
860 CompilerInvocation OriginalCI,
861 const PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
862 const ArrayRef<StringRef> StableDirs)
863 : Service(Service), ScanInstance(ScanInstance), Controller(Controller),
864 PrebuiltModulesASTMap(std::move(PrebuiltModulesASTMap)),
865 StableDirs(StableDirs), Opts(std::move(Opts)),
866 CommonInvocation(
867 makeCommonInvocationForModuleBuild(std::move(OriginalCI))) {}
868
870 auto CollectorPP = std::make_unique<ModuleDepCollectorPP>(*this);
871 CollectorPPPtr = CollectorPP.get();
872 PP.addPPCallbacks(std::move(CollectorPP));
873}
874
876
877bool ModuleDepCollector::isPrebuiltModule(const serialization::ModuleFile *MF) {
878 const auto &PrebuiltModuleFiles =
880 auto PrebuiltModuleFileIt = PrebuiltModuleFiles.find(MF->ModuleName);
881 if (PrebuiltModuleFileIt == PrebuiltModuleFiles.end())
882 return false;
883 assert("Prebuilt module came from the expected AST file" &&
884 PrebuiltModuleFileIt->second == MF->FileName.str());
885 return true;
886}
887
888void ModuleDepCollector::addVisibleModules() {
889 llvm::DenseSet<const Module *> ImportedModules;
890 auto InsertVisibleModules = [&](const Module *M) {
891 if (ImportedModules.contains(M))
892 return;
893
894 VisibleModules.insert(M->getTopLevelModuleName());
896 M->getExportedModules(Stack);
897 while (!Stack.empty()) {
898 const Module *CurrModule = Stack.pop_back_val();
899 if (ImportedModules.contains(CurrModule))
900 continue;
901 ImportedModules.insert(CurrModule);
902 VisibleModules.insert(CurrModule->getTopLevelModuleName());
903 CurrModule->getExportedModules(Stack);
904 }
905 };
906
907 for (const Module *Import : DirectImports)
908 InsertVisibleModules(Import);
909}
910
911void ModuleDepCollector::addFileDep(StringRef Path) {
912 if (!Service.getOpts().ReportAbsolutePaths) {
913 FileDeps.emplace_back(Path);
914 return;
915 }
916
917 llvm::SmallString<256> Storage;
918 Path = makeAbsoluteAndCanonicalize(ScanInstance, Path, Storage);
919 FileDeps.emplace_back(Path);
920}
921
922void ModuleDepCollector::addFileDep(ModuleDeps &MD, StringRef Path) {
923 MD.FileDeps.emplace_back(Path);
924}
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 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)
#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.
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 -...
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 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...
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).
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 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.
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:950
const ModuleFileKey * getASTFileKey() const
The serialized AST file key for this module, if one was created.
Definition Module.h:961
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
Definition Module.h:589
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:720
void getExportedModules(SmallVectorImpl< Module * > &Exported) const
Appends this module's list of exported modules to Exported.
Definition Module.cpp:379
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
Definition Module.h:940
bool UseExportAsModuleLinkName
Autolinking uses the framework name for linking purposes when this is false and the export_as name ot...
Definition Module.h:724
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.
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
llvm::SetVector< ModuleFile * > Imports
List of modules which this module directly imported.
Definition ModuleFile.h:555
llvm::BitVector SearchPathUsage
The bit vector denoting usage of each header search entry (true = used).
Definition ModuleFile.h:234
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:237
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
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.
@ 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.
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.