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) {
164 Controller.lookupModuleOutput(Deps, ModuleOutputKind::ModuleFile);
167 Controller.lookupModuleOutput(
169 if (!CI.getDependencyOutputOpts().OutputFile.empty()) {
171 Controller.lookupModuleOutput(Deps, ModuleOutputKind::DependencyFile);
173 splitString(Controller.lookupModuleOutput(
175 '\0');
176 if (!CI.getDependencyOutputOpts().OutputFile.empty() &&
177 CI.getDependencyOutputOpts().Targets.empty()) {
178 // Fallback to -o as dependency target, as in the driver.
179 SmallString<128> Target;
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 CI.getFrontendOpts().GenReducedBMI = false;
270 // LLVM options are not going to affect the AST
271 CI.getFrontendOpts().LLVMArgs.clear();
272
274 CI.getCodeGenOpts());
275
276 // Map output paths that affect behaviour to "-" so their existence is in the
277 // context hash. The final path will be computed in addOutputPaths.
280 if (!CI.getDependencyOutputOpts().OutputFile.empty())
282 CI.getDependencyOutputOpts().Targets.clear();
283
285 CI.getLangOpts().ModuleName.clear();
286
287 // Remove any macro definitions that are explicitly ignored.
288 if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) {
289 llvm::erase_if(
291 [&CI](const std::pair<std::string, bool> &Def) {
292 StringRef MacroDef = Def.first;
293 return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
294 llvm::CachedHashString(MacroDef.split('=').first));
295 });
296 // Remove the now unused option.
298 }
299
300 return CI;
301}
302
303CowCompilerInvocation
304ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs(
305 const ModuleDeps &Deps,
306 llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const {
307 CowCompilerInvocation CI = CommonInvocation;
308
311
312 // Inputs
313 InputKind ModuleMapInputKind(CI.getFrontendOpts().DashX.getLanguage(),
315 CI.getMutFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile,
316 ModuleMapInputKind);
317
318 auto CurrentModuleMapEntry =
319 ScanInstance.getFileManager().getOptionalFileRef(Deps.ClangModuleMapFile);
320 assert(CurrentModuleMapEntry && "module map file entry not found");
321
322 // Remove directly passed modulemap files. They will get added back if they
323 // were actually used.
325
326 auto DepModuleMapFiles = collectModuleMapFiles(Deps.ClangModuleDeps);
327 for (StringRef ModuleMapFile : Deps.ModuleMapFileDeps) {
328 // TODO: Track these as `FileEntryRef` to simplify the equality check below.
329 auto ModuleMapEntry =
330 ScanInstance.getFileManager().getOptionalFileRef(ModuleMapFile);
331 assert(ModuleMapEntry && "module map file entry not found");
332
333 // Don't report module maps describing eagerly-loaded dependency. This
334 // information will be deserialized from the PCM.
335 // TODO: Verify this works fine when modulemap for module A is eagerly
336 // loaded from A.pcm, and module map passed on the command line contains
337 // definition of a submodule: "explicit module A.Private { ... }".
338 if (Service.shouldEagerLoadModules() &&
339 DepModuleMapFiles.contains(*ModuleMapEntry))
340 continue;
341
342 // Don't report module map file of the current module unless it also
343 // describes a dependency (for symmetry).
344 if (*ModuleMapEntry == *CurrentModuleMapEntry &&
345 !DepModuleMapFiles.contains(*ModuleMapEntry))
346 continue;
347
348 CI.getMutFrontendOpts().ModuleMapFiles.emplace_back(ModuleMapFile);
349 }
350
351 // Report the prebuilt modules this module uses.
352 for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps)
353 CI.getMutFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
354
355 // Add module file inputs from dependencies.
356 addModuleFiles(CI, Deps.ClangModuleDeps);
357
359 // Apply -Wsystem-headers-in-module for the current module.
360 if (llvm::is_contained(CI.getDiagnosticOpts().SystemHeaderWarningsModules,
361 Deps.ID.ModuleName))
362 CI.getMutDiagnosticOpts().Warnings.push_back("system-headers");
363 // Remove the now unused option(s).
365 }
366
367 Optimize(CI);
368
369 return CI;
370}
371
372llvm::DenseSet<const FileEntry *> ModuleDepCollector::collectModuleMapFiles(
373 ArrayRef<ModuleID> ClangModuleDeps) const {
374 llvm::DenseSet<const FileEntry *> ModuleMapFiles;
375 for (const ModuleID &MID : ClangModuleDeps) {
376 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
377 assert(MD && "Inconsistent dependency info");
378 // TODO: Track ClangModuleMapFile as `FileEntryRef`.
379 auto FE = ScanInstance.getFileManager().getOptionalFileRef(
381 assert(FE && "Missing module map file that was previously found");
382 ModuleMapFiles.insert(*FE);
383 }
384 return ModuleMapFiles;
385}
386
387void ModuleDepCollector::addModuleMapFiles(
388 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
389 if (Service.shouldEagerLoadModules())
390 return; // Only pcm is needed for eager load.
391
392 for (const ModuleID &MID : ClangModuleDeps) {
393 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
394 assert(MD && "Inconsistent dependency info");
396 }
397}
398
399void ModuleDepCollector::addModuleFiles(
400 CompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
401 for (const ModuleID &MID : ClangModuleDeps) {
402 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
403 std::string PCMPath =
404 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile);
405
406 if (Service.shouldEagerLoadModules())
407 CI.getFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
408 else
410 {MID.ModuleName, std::move(PCMPath)});
411 }
412}
413
414void ModuleDepCollector::addModuleFiles(
415 CowCompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
416 for (const ModuleID &MID : ClangModuleDeps) {
417 ModuleDeps *MD = ModuleDepsByID.lookup(MID);
418 std::string PCMPath =
419 Controller.lookupModuleOutput(*MD, ModuleOutputKind::ModuleFile);
420
421 if (Service.shouldEagerLoadModules())
422 CI.getMutFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
423 else
425 {MID.ModuleName, std::move(PCMPath)});
426 }
427}
428
430 switch (FIF.getKind().getLanguage()) {
432 case Language::Asm:
434 return false;
435 default:
436 return true;
437 }
438}
439
443 CI.getLangOpts(), CI.getCodeGenOpts());
444
445 if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) {
446 Preprocessor &PP = ScanInstance.getPreprocessor();
447 if (Module *CurrentModule = PP.getCurrentModuleImplementation())
448 if (OptionalFileEntryRef CurrentModuleMap =
450 .getModuleMap()
451 .getModuleMapFileForUniquing(CurrentModule))
452 CI.getFrontendOpts().ModuleMapFiles.emplace_back(
453 CurrentModuleMap->getNameAsRequested());
454
455 SmallVector<ModuleID> DirectDeps;
456 for (const auto &KV : ModularDeps)
457 if (DirectModularDeps.contains(KV.first))
458 DirectDeps.push_back(KV.second->ID);
459
460 // TODO: Report module maps the same way it's done for modular dependencies.
461 addModuleMapFiles(CI, DirectDeps);
462
463 addModuleFiles(CI, DirectDeps);
464
465 for (const auto &KV : DirectPrebuiltModularDeps)
466 CI.getFrontendOpts().ModuleFiles.push_back(KV.second.PCMFile);
467 }
468}
469
471 // Check if the command line input uses relative paths.
472 // It is not safe to ignore the current working directory if any of the
473 // command line inputs use relative paths.
474#define IF_RELATIVE_RETURN_FALSE(PATH) \
475 do { \
476 if (!PATH.empty() && !llvm::sys::path::is_absolute(PATH)) \
477 return false; \
478 } while (0)
479
480#define IF_ANY_RELATIVE_RETURN_FALSE(PATHS) \
481 do { \
482 if (llvm::any_of(PATHS, [](const auto &P) { \
483 return !P.empty() && !llvm::sys::path::is_absolute(P); \
484 })) \
485 return false; \
486 } while (0)
487
488 // Header search paths.
489 const auto &HeaderSearchOpts = CI.getHeaderSearchOpts();
490 IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.Sysroot);
491 for (auto &Entry : HeaderSearchOpts.UserEntries)
492 if (Entry.IgnoreSysRoot)
493 IF_RELATIVE_RETURN_FALSE(Entry.Path);
494 IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ResourceDir);
495 IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ModuleCachePath);
496 IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ModuleUserBuildPath);
497 for (auto I = HeaderSearchOpts.PrebuiltModuleFiles.begin(),
498 E = HeaderSearchOpts.PrebuiltModuleFiles.end();
499 I != E;) {
500 auto Current = I++;
501 IF_RELATIVE_RETURN_FALSE(Current->second);
502 }
503 IF_ANY_RELATIVE_RETURN_FALSE(HeaderSearchOpts.PrebuiltModulePaths);
504 IF_ANY_RELATIVE_RETURN_FALSE(HeaderSearchOpts.VFSOverlayFiles);
505
506 // Preprocessor options.
507 const auto &PPOpts = CI.getPreprocessorOpts();
508 IF_ANY_RELATIVE_RETURN_FALSE(PPOpts.MacroIncludes);
509 IF_ANY_RELATIVE_RETURN_FALSE(PPOpts.Includes);
510 IF_RELATIVE_RETURN_FALSE(PPOpts.ImplicitPCHInclude);
511
512 // Frontend options.
513 const auto &FrontendOpts = CI.getFrontendOpts();
514 for (const FrontendInputFile &Input : FrontendOpts.Inputs) {
515 if (Input.isBuffer())
516 continue; // FIXME: Can this happen when parsing command-line?
517
519 }
520 IF_RELATIVE_RETURN_FALSE(FrontendOpts.CodeCompletionAt.FileName);
521 IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModuleMapFiles);
522 IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModuleFiles);
523 IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModulesEmbedFiles);
524 IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ASTMergeFiles);
525 IF_RELATIVE_RETURN_FALSE(FrontendOpts.OverrideRecordLayoutsFile);
526 IF_RELATIVE_RETURN_FALSE(FrontendOpts.StatsFile);
527
528 // Filesystem options.
529 const auto &FileSystemOpts = CI.getFileSystemOpts();
530 IF_RELATIVE_RETURN_FALSE(FileSystemOpts.WorkingDir);
531
532 // Codegen options.
533 const auto &CodeGenOpts = CI.getCodeGenOpts();
534 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.DebugCompilationDir);
535 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.CoverageCompilationDir);
536
537 // Sanitizer options.
539
540 // Coverage mappings.
541 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.ProfileInstrumentUsePath);
542 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.SampleProfileFile);
543 IF_RELATIVE_RETURN_FALSE(CodeGenOpts.ProfileRemappingFile);
544
545 // Dependency output options.
546 for (auto &ExtraDep : CI.getDependencyOutputOpts().ExtraDeps)
547 IF_RELATIVE_RETURN_FALSE(ExtraDep.first);
548
549 return true;
550}
551
552static std::string getModuleContextHash(const ModuleDeps &MD,
553 const CowCompilerInvocation &CI,
554 bool EagerLoadModules, bool IgnoreCWD,
555 llvm::vfs::FileSystem &VFS) {
556 llvm::HashBuilder<llvm::TruncatedBLAKE3<16>, llvm::endianness::native>
557 HashBuilder;
558
559 // Hash the compiler version and serialization version to ensure the module
560 // will be readable.
561 HashBuilder.add(getClangFullRepositoryVersion());
563 llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory();
564 if (CWD && !IgnoreCWD)
565 HashBuilder.add(*CWD);
566
567 // Hash the BuildInvocation without any input files.
568 SmallString<0> ArgVec;
569 ArgVec.reserve(4096);
570 CI.generateCC1CommandLine([&](const Twine &Arg) {
571 Arg.toVector(ArgVec);
572 ArgVec.push_back('\0');
573 });
574 HashBuilder.add(ArgVec);
575
576 // Hash the module dependencies. These paths may differ even if the invocation
577 // is identical if they depend on the contents of the files in the TU -- for
578 // example, case-insensitive paths to modulemap files. Usually such a case
579 // would indicate a missed optimization to canonicalize, but it may be
580 // difficult to canonicalize all cases when there is a VFS.
581 for (const auto &ID : MD.ClangModuleDeps) {
582 HashBuilder.add(ID.ModuleName);
583 HashBuilder.add(ID.ContextHash);
584 }
585
586 HashBuilder.add(EagerLoadModules);
587
588 llvm::BLAKE3Result<16> Hash = HashBuilder.final();
589 std::array<uint64_t, 2> Words;
590 static_assert(sizeof(Hash) == sizeof(Words), "Hash must match Words");
591 std::memcpy(Words.data(), Hash.data(), sizeof(Hash));
592 return toString(llvm::APInt(sizeof(Words) * 8, Words), 36, /*Signed=*/false);
593}
594
595void ModuleDepCollector::associateWithContextHash(
596 const CowCompilerInvocation &CI, bool IgnoreCWD, ModuleDeps &Deps) {
597 Deps.ID.ContextHash =
598 getModuleContextHash(Deps, CI, Service.shouldEagerLoadModules(),
599 IgnoreCWD, ScanInstance.getVirtualFileSystem());
600 bool Inserted = ModuleDepsByID.insert({Deps.ID, &Deps}).second;
601 (void)Inserted;
602 assert(Inserted && "duplicate module mapping");
603}
604
608 FileID PrevFID,
609 SourceLocation Loc) {
611 return;
612
613 SourceManager &SM = MDC.ScanInstance.getSourceManager();
614
615 // Dependency generation really does want to go all the way to the
616 // file entry for a source location to find out what is depended on.
617 // We do not want #line markers to affect dependency generation!
618 if (std::optional<StringRef> Filename = SM.getNonBuiltinFilenameForID(FID))
619 MDC.addFileDep(llvm::sys::path::remove_leading_dotslash(*Filename));
620}
621
623 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
624 bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
625 StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule,
626 bool ModuleImported, SrcMgr::CharacteristicKind FileType) {
627 if (!File && !ModuleImported) {
628 // This is a non-modular include that HeaderSearch failed to find. Add it
629 // here as `FileChanged` will never see it.
630 MDC.addFileDep(FileName);
631 }
632 handleImport(SuggestedModule);
633}
634
636 ModuleIdPath Path,
637 const Module *Imported) {
638 if (MDC.ScanInstance.getPreprocessor().isInImportingCXXNamedModules()) {
639 P1689ModuleInfo RequiredModule;
640 RequiredModule.ModuleName = Path[0].getIdentifierInfo()->getName().str();
642 MDC.RequiredStdCXXModules.push_back(std::move(RequiredModule));
643 return;
644 }
645
646 handleImport(Imported);
647}
648
649void ModuleDepCollectorPP::handleImport(const Module *Imported) {
650 if (!Imported)
651 return;
652
653 const Module *TopLevelModule = Imported->getTopLevelModule();
654
655 if (MDC.isPrebuiltModule(TopLevelModule))
656 MDC.DirectPrebuiltModularDeps.insert(
657 {TopLevelModule, PrebuiltModuleDep{TopLevelModule}});
658 else {
659 MDC.DirectModularDeps.insert(TopLevelModule);
660 MDC.DirectImports.insert(Imported);
661 }
662}
663
665 FileID MainFileID = MDC.ScanInstance.getSourceManager().getMainFileID();
666 MDC.MainFile = std::string(MDC.ScanInstance.getSourceManager()
667 .getFileEntryRefForID(MainFileID)
668 ->getName());
669
670 auto &PP = MDC.ScanInstance.getPreprocessor();
671 if (PP.isInNamedModule()) {
672 P1689ModuleInfo ProvidedModule;
673 ProvidedModule.ModuleName = PP.getNamedModuleName();
675 ProvidedModule.IsStdCXXModuleInterface = PP.isInNamedInterfaceUnit();
676 // Don't put implementation (non partition) unit as Provide.
677 // Put the module as required instead. Since the implementation
678 // unit will import the primary module implicitly.
679 if (PP.isInImplementationUnit())
680 MDC.RequiredStdCXXModules.push_back(ProvidedModule);
681 else
682 MDC.ProvidedStdCXXModule = ProvidedModule;
683 }
684
685 if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
686 MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude);
687
688 for (const Module *M :
689 MDC.ScanInstance.getPreprocessor().getAffectingClangModules())
690 if (!MDC.isPrebuiltModule(M))
691 MDC.DirectModularDeps.insert(M);
692
693 MDC.addVisibleModules();
694
695 for (const Module *M : MDC.DirectModularDeps)
696 handleTopLevelModule(M);
697
698 MDC.Consumer.handleContextHash(
699 MDC.ScanInstance.getInvocation().getModuleHash());
700
701 MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts);
702
703 MDC.Consumer.handleProvidedAndRequiredStdCXXModules(
704 MDC.ProvidedStdCXXModule, MDC.RequiredStdCXXModules);
705
706 for (auto &&I : MDC.ModularDeps)
707 MDC.Consumer.handleModuleDependency(*I.second);
708
709 for (const Module *M : MDC.DirectModularDeps) {
710 auto It = MDC.ModularDeps.find(M);
711 // Only report direct dependencies that were successfully handled.
712 if (It != MDC.ModularDeps.end())
713 MDC.Consumer.handleDirectModuleDependency(It->second->ID);
714 }
715
716 for (auto &&I : MDC.VisibleModules)
717 MDC.Consumer.handleVisibleModule(std::string(I.getKey()));
718
719 for (auto &&I : MDC.FileDeps)
720 MDC.Consumer.handleFileDependency(I);
721
722 for (auto &&I : MDC.DirectPrebuiltModularDeps)
723 MDC.Consumer.handlePrebuiltModuleDependency(I.second);
724}
725
726std::optional<ModuleID>
727ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
728 assert(M == M->getTopLevelModule() && "Expected top level module!");
729
730 // A top-level module might not be actually imported as a module when
731 // -fmodule-name is used to compile a translation unit that imports this
732 // module. In that case it can be skipped. The appropriate header
733 // dependencies will still be reported as expected.
734 if (!M->getASTFile())
735 return {};
736
737 // If this module has been handled already, just return its ID.
738 if (auto ModI = MDC.ModularDeps.find(M); ModI != MDC.ModularDeps.end())
739 return ModI->second->ID;
740
741 auto OwnedMD = std::make_unique<ModuleDeps>();
742 ModuleDeps &MD = *OwnedMD;
743
745 MD.IsSystem = M->IsSystem;
746
747 // Start off with the assumption that this module is shareable when there
748 // are stable directories. As more dependencies are discovered, check if those
749 // come from the provided directories.
750 MD.IsInStableDirectories = !MDC.StableDirs.empty();
751
752 // For modules which use export_as link name, the linked product that of the
753 // corresponding export_as-named module.
756
757 ModuleMap &ModMapInfo =
758 MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
759
760 if (auto ModuleMap = ModMapInfo.getModuleMapFileForUniquing(M)) {
761 SmallString<128> Path = ModuleMap->getNameAsRequested();
762 ModMapInfo.canonicalizeModuleMapPath(Path);
763 MD.ClangModuleMapFile = std::string(Path);
764 }
765
767 MDC.ScanInstance.getASTReader()->getModuleManager().lookup(
768 *M->getASTFile());
769 MD.FileDepsBaseDir = MF->BaseDirectory;
770 MDC.ScanInstance.getASTReader()->visitInputFileInfos(
771 *MF, /*IncludeSystem=*/true,
772 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
773 // The __inferred_module.map file is an insignificant implementation
774 // detail of implicitly-built modules. The PCM will also report the
775 // actual on-disk module map file that allowed inferring the module,
776 // which is what we need for building the module explicitly
777 // Let's ignore this file.
778 if (IFI.UnresolvedImportedFilename.ends_with("__inferred_module.map"))
779 return;
780 MDC.addFileDep(MD, IFI.UnresolvedImportedFilename);
781 });
782
783 llvm::DenseSet<const Module *> SeenDeps;
784 addAllSubmodulePrebuiltDeps(M, MD, SeenDeps);
785 addAllSubmoduleDeps(M, MD, SeenDeps);
786 addAllAffectingClangModules(M, MD, SeenDeps);
787
788 SmallString<0> PathBuf;
789 PathBuf.reserve(256);
790 MDC.ScanInstance.getASTReader()->visitInputFileInfos(
791 *MF, /*IncludeSystem=*/true,
792 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
793 if (MD.IsInStableDirectories) {
794 auto FullFilePath = ASTReader::ResolveImportedPath(
795 PathBuf, IFI.UnresolvedImportedFilename, MF->BaseDirectory);
797 isPathInStableDir(MDC.StableDirs, *FullFilePath);
798 }
799 if (!(IFI.TopLevel && IFI.ModuleMap))
800 return;
802 "__inferred_module.map"))
803 return;
804 auto ResolvedFilenameAsRequested = ASTReader::ResolveImportedPath(
806 MF->BaseDirectory);
807 MD.ModuleMapFileDeps.emplace_back(*ResolvedFilenameAsRequested);
808 });
809
810 bool IgnoreCWD = false;
811 CowCompilerInvocation CI =
812 MDC.getInvocationAdjustedForModuleBuildWithoutOutputs(
813 MD, [&](CowCompilerInvocation &BuildInvocation) {
814 if (any(MDC.Service.getOptimizeArgs() &
818 *MDC.ScanInstance.getASTReader(), *MF,
819 MDC.PrebuiltModulesASTMap,
820 MDC.Service.getOptimizeArgs());
821
822 if (any(MDC.Service.getOptimizeArgs() &
825 BuildInvocation.getMutDiagnosticOpts(),
826 BuildInvocation.getFrontendOpts().IsSystemModule);
827
828 IgnoreCWD = any(MDC.Service.getOptimizeArgs() &
830 isSafeToIgnoreCWD(BuildInvocation);
831 if (IgnoreCWD) {
832 llvm::ErrorOr<std::string> CWD =
833 MDC.ScanInstance.getVirtualFileSystem()
834 .getCurrentWorkingDirectory();
835 if (CWD)
836 optimizeCWD(BuildInvocation, *CWD);
837 }
838 });
839
840 // Check provided input paths from the invocation for determining
841 // IsInStableDirectories.
844 areOptionsInStableDir(MDC.StableDirs, CI.getHeaderSearchOpts());
845
846 MDC.associateWithContextHash(CI, IgnoreCWD, MD);
847
848 // Finish the compiler invocation. Requires dependencies and the context hash.
849 MDC.addOutputPaths(CI, MD);
850
851 MD.BuildInfo = std::move(CI);
852
853 MDC.ModularDeps.insert({M, std::move(OwnedMD)});
854
855 return MD.ID;
856}
857
858static void forEachSubmoduleSorted(const Module *M,
859 llvm::function_ref<void(const Module *)> F) {
860 // Submodule order depends on order of header includes for inferred submodules
861 // we don't care about the exact order, so sort so that it's consistent across
862 // TUs to improve sharing.
864 llvm::stable_sort(Submodules, [](const Module *A, const Module *B) {
865 return A->Name < B->Name;
866 });
867 for (const Module *SubM : Submodules)
868 F(SubM);
869}
870
871void ModuleDepCollectorPP::addAllSubmodulePrebuiltDeps(
872 const Module *M, ModuleDeps &MD,
873 llvm::DenseSet<const Module *> &SeenSubmodules) {
874 addModulePrebuiltDeps(M, MD, SeenSubmodules);
875
876 forEachSubmoduleSorted(M, [&](const Module *SubM) {
877 addAllSubmodulePrebuiltDeps(SubM, MD, SeenSubmodules);
878 });
879}
880
881void ModuleDepCollectorPP::addModulePrebuiltDeps(
882 const Module *M, ModuleDeps &MD,
883 llvm::DenseSet<const Module *> &SeenSubmodules) {
884 for (const Module *Import : M->Imports)
885 if (Import->getTopLevelModule() != M->getTopLevelModule())
886 if (MDC.isPrebuiltModule(Import->getTopLevelModule()))
887 if (SeenSubmodules.insert(Import->getTopLevelModule()).second) {
888 MD.PrebuiltModuleDeps.emplace_back(Import->getTopLevelModule());
889 if (MD.IsInStableDirectories) {
890 auto PrebuiltModulePropIt = MDC.PrebuiltModulesASTMap.find(
891 MD.PrebuiltModuleDeps.back().PCMFile);
893 (PrebuiltModulePropIt != MDC.PrebuiltModulesASTMap.end()) &&
894 PrebuiltModulePropIt->second.isInStableDir();
895 }
896 }
897}
898
899void ModuleDepCollectorPP::addAllSubmoduleDeps(
900 const Module *M, ModuleDeps &MD,
901 llvm::DenseSet<const Module *> &AddedModules) {
902 addModuleDep(M, MD, AddedModules);
903
904 forEachSubmoduleSorted(M, [&](const Module *SubM) {
905 addAllSubmoduleDeps(SubM, MD, AddedModules);
906 });
907}
908
909void ModuleDepCollectorPP::addOneModuleDep(const Module *M, const ModuleID ID,
910 ModuleDeps &MD) {
911 MD.ClangModuleDeps.push_back(std::move(ID));
913 MD.IsInStableDirectories = MDC.ModularDeps[M]->IsInStableDirectories;
914}
915
916void ModuleDepCollectorPP::addModuleDep(
917 const Module *M, ModuleDeps &MD,
918 llvm::DenseSet<const Module *> &AddedModules) {
919 for (const Module *Import : M->Imports) {
920 if (Import->getTopLevelModule() != M->getTopLevelModule() &&
921 !MDC.isPrebuiltModule(Import)) {
922 if (auto ImportID = handleTopLevelModule(Import->getTopLevelModule()))
923 if (AddedModules.insert(Import->getTopLevelModule()).second)
924 addOneModuleDep(Import->getTopLevelModule(), *ImportID, MD);
925 }
926 }
927}
928
929void ModuleDepCollectorPP::addAllAffectingClangModules(
930 const Module *M, ModuleDeps &MD,
931 llvm::DenseSet<const Module *> &AddedModules) {
932 addAffectingClangModule(M, MD, AddedModules);
933
934 for (const Module *SubM : M->submodules())
935 addAllAffectingClangModules(SubM, MD, AddedModules);
936}
937
938void ModuleDepCollectorPP::addAffectingClangModule(
939 const Module *M, ModuleDeps &MD,
940 llvm::DenseSet<const Module *> &AddedModules) {
941 for (const Module *Affecting : M->AffectingClangModules) {
942 assert(Affecting == Affecting->getTopLevelModule() &&
943 "Not quite import not top-level module");
944 if (Affecting != M->getTopLevelModule() &&
945 !MDC.isPrebuiltModule(Affecting)) {
946 if (auto ImportID = handleTopLevelModule(Affecting))
947 if (AddedModules.insert(Affecting).second)
948 addOneModuleDep(Affecting, *ImportID, MD);
949 }
950 }
951}
952
955 std::unique_ptr<DependencyOutputOptions> Opts,
956 CompilerInstance &ScanInstance, DependencyConsumer &C,
957 DependencyActionController &Controller, CompilerInvocation OriginalCI,
958 const PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
959 const ArrayRef<StringRef> StableDirs)
960 : Service(Service), ScanInstance(ScanInstance), Consumer(C),
961 Controller(Controller),
962 PrebuiltModulesASTMap(std::move(PrebuiltModulesASTMap)),
963 StableDirs(StableDirs), Opts(std::move(Opts)),
964 CommonInvocation(
965 makeCommonInvocationForModuleBuild(std::move(OriginalCI))) {}
966
968 PP.addPPCallbacks(std::make_unique<ModuleDepCollectorPP>(*this));
969}
970
972
973bool ModuleDepCollector::isPrebuiltModule(const Module *M) {
974 std::string Name(M->getTopLevelModuleName());
975 const auto &PrebuiltModuleFiles =
977 auto PrebuiltModuleFileIt = PrebuiltModuleFiles.find(Name);
978 if (PrebuiltModuleFileIt == PrebuiltModuleFiles.end())
979 return false;
980 assert("Prebuilt module came from the expected AST file" &&
981 PrebuiltModuleFileIt->second == M->getASTFile()->getName());
982 return true;
983}
984
985void ModuleDepCollector::addVisibleModules() {
986 llvm::DenseSet<const Module *> ImportedModules;
987 auto InsertVisibleModules = [&](const Module *M) {
988 if (ImportedModules.contains(M))
989 return;
990
991 VisibleModules.insert(M->getTopLevelModuleName());
993 M->getExportedModules(Stack);
994 while (!Stack.empty()) {
995 const Module *CurrModule = Stack.pop_back_val();
996 if (ImportedModules.contains(CurrModule))
997 continue;
998 ImportedModules.insert(CurrModule);
999 VisibleModules.insert(CurrModule->getTopLevelModuleName());
1000 CurrModule->getExportedModules(Stack);
1001 }
1002 };
1003
1004 for (const Module *Import : DirectImports)
1005 InsertVisibleModules(Import);
1006}
1007
1008static StringRef makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path,
1009 SmallVectorImpl<char> &Storage) {
1010 if (llvm::sys::path::is_absolute(Path) &&
1011 !llvm::sys::path::is_style_windows(llvm::sys::path::Style::native))
1012 return Path;
1013 Storage.assign(Path.begin(), Path.end());
1014 CI.getFileManager().makeAbsolutePath(Storage);
1015 llvm::sys::path::make_preferred(Storage);
1016 return StringRef(Storage.data(), Storage.size());
1017}
1018
1019void ModuleDepCollector::addFileDep(StringRef Path) {
1020 if (Service.getFormat() == ScanningOutputFormat::P1689) {
1021 // Within P1689 format, we don't want all the paths to be absolute path
1022 // since it may violate the traditional make style dependencies info.
1023 FileDeps.emplace_back(Path);
1024 return;
1025 }
1026
1027 llvm::SmallString<256> Storage;
1028 Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage);
1029 FileDeps.emplace_back(Path);
1030}
1031
1032void ModuleDepCollector::addFileDep(ModuleDeps &MD, StringRef Path) {
1033 MD.FileDeps.emplace_back(Path);
1034}
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)
Defines the clang::Preprocessor interface.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Reads an AST files chain containing the contents of a translation unit.
Definition ASTReader.h:430
static TemporarilyOwnedStringRef ResolveImportedPath(SmallString< 0 > &Buf, StringRef Path, ModuleFile &ModF)
Resolve Path in the context of module file M.
Represents a character-granular source range.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
std::string CoverageNotesFile
The filename with path we use for coverage notes files.
std::string ProfileInstrumentUsePath
Name of the profile file to use as input for -fprofile-instr-use.
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
std::string CoverageDataFile
The filename with path we use for coverage data files.
std::string DebugCompilationDir
The string to embed in debug information as the current working directory.
std::string MainFileName
The user provided name for the "main file", if non-empty.
std::string CoverageCompilationDir
The string to embed in coverage mapping as the current working directory.
std::string ProfileRemappingFile
Name of the profile remapping file to apply to the profile data supplied by -fprofile-sample-use or -...
std::string DwarfDebugFlags
The string to embed in the debug information for the compile unit, if non-empty.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
FileManager & getFileManager() const
Return the current file manager to the caller.
IntrusiveRefCntPtr< ASTReader > getASTReader() const
Preprocessor & getPreprocessor() const
Return the current preprocessor.
HeaderSearchOptions & getHeaderSearchOpts()
const FrontendOptions & getFrontendOpts() const
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()
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...
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...
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.
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.
std::vector< std::string > NoSanitizeFiles
Paths to files specifying which objects (files, functions, variables) should not be instrumented.
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
std::error_code canonicalizeModuleMapPath(SmallVectorImpl< char > &Path)
Canonicalize Path in a manner suitable for a module map file.
Describes a module or submodule.
Definition Module.h:144
StringRef getTopLevelModuleName() const
Retrieve the name of the top-level module.
Definition Module.h:732
llvm::SmallSetVector< Module *, 2 > Imports
The set of modules imported by this module, and on which this module depends.
Definition Module.h:458
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
Definition Module.h:389
std::string Name
The name of this module.
Definition Module.h:147
llvm::iterator_range< submodule_iterator > submodules()
Definition Module.h:838
llvm::SmallVector< LinkLibrary, 2 > LinkLibraries
The set of libraries or frameworks to link against when an entity from this module is used.
Definition Module.h:520
llvm::SmallSetVector< Module *, 2 > AffectingClangModules
The set of top-level modules that affected the compilation of this module, but were not imported.
Definition Module.h:462
void getExportedModules(SmallVectorImpl< Module * > &Exported) const
Appends this module's list of exported modules to Exported.
Definition Module.cpp:383
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
Definition Module.cpp:239
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
Definition Module.h:722
OptionalFileEntryRef getASTFile() const
The serialized AST file for this module, if one was created.
Definition Module.h:737
bool UseExportAsModuleLinkName
Autolinking uses the framework name for linking purposes when this is false and the export_as name ot...
Definition Module.h:524
std::vector< std::pair< std::string, bool > > Macros
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Module * getCurrentModuleImplementation()
Retrieves the module whose implementation we're current compiling, if any.
HeaderSearch & getHeaderSearchInfo() const
Encodes a location in the source.
This class handles loading and caching of source files into memory.
Token - This structure provides full information about a lexed token.
Definition Token.h:36
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...
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 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...
@ 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.
@ IgnoreCWD
Ignore the compiler's working directory if it is safe.
@ 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.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:208
void quoteMakeTarget(StringRef Target, SmallVectorImpl< char > &Res)
Quote target names for inclusion in GNU Make dependency files.
ArrayRef< IdentifierLoc > ModuleIdPath
A sequence of identifier/location pairs used to describe a particular module or submodule,...
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
Definition Linkage.h:54
@ Asm
Assembly: we accept this only so that we can preprocess it.
std::string getClangFullRepositoryVersion()
Retrieves the full repository version that is an amalgamation of the information in getClangRepositor...
Definition Version.cpp:68
int const char * function
Definition c++config.h:31
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
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.