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