21#include "llvm/ADT/IntrusiveRefCntPtr.h"
22#include "llvm/ADT/ScopeExit.h"
23#include "llvm/Option/Option.h"
24#include "llvm/Support/AdvisoryLock.h"
25#include "llvm/Support/CrashRecoveryContext.h"
26#include "llvm/Support/VirtualFileSystem.h"
27#include "llvm/TargetParser/Host.h"
38 if (LangOpts.Modules) {
41 Diags->
Report(diag::warn_pch_vfsoverlay_mismatch);
43 if (VFSOverlays.empty()) {
44 Diags->
Report(diag::note_pch_vfsoverlay_empty) <<
Type;
46 std::string Files = llvm::join(VFSOverlays,
"\n");
47 Diags->
Report(diag::note_pch_vfsoverlay_files) <<
Type << Files;
65 PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
66 llvm::SmallVector<std::string> &NewModuleFiles,
68 const HeaderSearchOptions &HSOpts,
69 const LangOptions &LangOpts, DiagnosticsEngine &Diags,
70 const ArrayRef<StringRef> StableDirs)
71 : PrebuiltModuleFiles(PrebuiltModuleFiles),
72 NewModuleFiles(NewModuleFiles),
73 PrebuiltModulesASTMap(PrebuiltModulesASTMap), ExistingHSOpts(HSOpts),
74 ExistingLangOpts(LangOpts), Diags(Diags), StableDirs(StableDirs) {}
76 bool needsImportVisitation()
const override {
return true; }
77 bool needsInputFileVisitation()
override {
return true; }
78 bool needsSystemInputFileVisitation()
override {
return true; }
82 void visitImport(StringRef ModuleName, StringRef Filename)
override {
83 if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second)
84 NewModuleFiles.push_back(Filename.str());
86 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(Filename);
87 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
88 if (PrebuiltMapEntry.second)
91 if (
auto It = PrebuiltModulesASTMap.find(CurrentFile);
92 It != PrebuiltModulesASTMap.end() && CurrentFile != Filename)
99 bool visitInputFileAsRequested(StringRef FilenameAsRequested,
100 StringRef Filename,
bool isSystem,
101 bool isOverridden, time_t StoredTime,
102 bool isExplicitModule)
override {
103 if (StableDirs.empty())
105 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
106 if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end()) ||
107 (!PrebuiltEntryIt->second.isInStableDir()))
110 PrebuiltEntryIt->second.setInStableDir(
112 return PrebuiltEntryIt->second.isInStableDir();
117 bool DirectlyImported)
override {
120 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
121 if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end()) &&
122 !PrebuiltEntryIt->second.isInStableDir())
123 PrebuiltEntryIt->second.updateDependentsNotInStableDirs(
124 PrebuiltModulesASTMap);
125 CurrentFile = Filename.
str();
130 bool ReadHeaderSearchOptions(
const HeaderSearchOptions &HSOpts,
131 StringRef ModuleFilename, StringRef ContextHash,
132 bool Complain)
override {
134 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
135 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
136 if (PrebuiltMapEntry.second)
146 bool ReadHeaderSearchPaths(
const HeaderSearchOptions &HSOpts,
147 bool Complain)
override {
149 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
150 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
151 if (PrebuiltMapEntry.second)
158 HSOpts, ExistingHSOpts, Complain ? &Diags :
nullptr, ExistingLangOpts);
162 PrebuiltModuleFilesT &PrebuiltModuleFiles;
163 llvm::SmallVector<std::string> &NewModuleFiles;
165 const HeaderSearchOptions &ExistingHSOpts;
166 const LangOptions &ExistingLangOpts;
167 DiagnosticsEngine &Diags;
168 std::string CurrentFile;
169 const ArrayRef<StringRef> StableDirs;
177 PrebuiltModuleFilesT &ModuleFiles,
184 PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModulesASTMap,
198 while (!Worklist.empty()) {
220 llvm::sys::path::replace_extension(ObjFileName,
"o");
221 return std::string(ObjFileName);
228 if (OutputFile !=
"-")
231 if (InputFiles.empty() || !InputFiles.front().isFile())
232 return "clang-scan-deps\\ dependency";
248 StringRef Name =
Macro.split(
"=").first.ltrim(
" \t");
251 auto FinishName = [&]() -> std::optional<StringRef> {
252 StringRef SimpleName = Name.slice(0, I);
253 if (SimpleName.empty())
258 for (; I != Name.size(); ++I) {
267 if (llvm::isAlnum(Name[I]))
276 using MacroOpt = std::pair<StringRef, std::size_t>;
277 std::vector<MacroOpt> SimpleNames;
278 SimpleNames.reserve(PPOpts.
Macros.size());
279 std::size_t Index = 0;
280 for (
const auto &M : PPOpts.
Macros) {
285 SimpleNames.emplace_back(*SName, Index);
289 llvm::stable_sort(SimpleNames, llvm::less_first());
291 auto NewEnd = std::unique(
292 SimpleNames.rbegin(), SimpleNames.rend(),
293 [](
const MacroOpt &A,
const MacroOpt &B) { return A.first == B.first; });
294 SimpleNames.erase(SimpleNames.begin(), NewEnd.base());
297 decltype(PPOpts.
Macros) NewMacros;
298 NewMacros.reserve(SimpleNames.size());
299 for (std::size_t I = 0, E = SimpleNames.size(); I != E; ++I) {
300 std::size_t OriginalIndex = SimpleNames[I].second;
302 NewMacros.push_back(std::move(PPOpts.
Macros[OriginalIndex]));
304 std::swap(PPOpts.
Macros, NewMacros);
309 DependencyScanningWorkerFilesystem *DepFS;
312 ScanningDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(
nullptr) {
314 auto *
DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
316 assert(!DepFS &&
"Found multiple scanning VFSs");
320 assert(DepFS &&
"Did not find scanning VFS");
323 std::unique_ptr<DependencyDirectivesGetter>
324 cloneFor(FileManager &FileMgr)
override {
325 return std::make_unique<ScanningDependencyDirectivesGetter>(FileMgr);
328 std::optional<ArrayRef<dependency_directives_scan::Directive>>
329 operator()(FileEntryRef
File)
override {
330 return DepFS->getDirectiveTokens(
File.getName());
338 DiagOpts.ShowCarets =
false;
349 return llvm::StringSwitch<bool>(Warning)
350 .Cases({
"pch-vfs-diff",
"error=pch-vfs-diff"},
false)
351 .StartsWith(
"no-error=",
false)
356static std::unique_ptr<CompilerInvocation>
359 llvm::opt::ArgStringList Argv;
360 for (
const std::string &Str :
ArrayRef(CommandLine).drop_front())
361 Argv.push_back(Str.c_str());
363 auto Invocation = std::make_unique<CompilerInvocation>();
385 if (Service.
getOpts().
Mode == ScanningMode::DependencyDirectivesScan)
387 std::make_unique<ScanningDependencyDirectivesGetter>(
391static std::shared_ptr<CompilerInvocation>
395 auto ScanInvocation = std::make_shared<CompilerInvocation>(Invocation);
399 ScanInvocation->getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath =
402 if (ScanInvocation->getHeaderSearchOpts()
403 .ModulesValidateOncePerBuildSession ||
405 ScanInvocation->getHeaderSearchOpts().BuildSessionTimestamp =
408 ScanInvocation->getHeaderSearchOpts().ModulesValidateDirectoryDependencies =
411 ScanInvocation->getFrontendOpts().DisableFree =
false;
412 ScanInvocation->getFrontendOpts().GenerateGlobalModuleIndex =
false;
413 ScanInvocation->getFrontendOpts().UseGlobalModuleIndex =
false;
414 ScanInvocation->getFrontendOpts().GenReducedBMI =
false;
415 ScanInvocation->getFrontendOpts().ModuleOutputPath.clear();
418 ScanInvocation->getFrontendOpts().ModulesShareFileManager =
true;
419 ScanInvocation->getHeaderSearchOpts().ModuleFormat =
"raw";
420 ScanInvocation->getHeaderSearchOpts().ModulesIncludeVFSUsage =
428 ScanInvocation->getHeaderSearchOpts().ModulesStrictContextHash =
true;
429 ScanInvocation->getHeaderSearchOpts().ModulesSerializeOnlyPreprocessor =
true;
430 ScanInvocation->getHeaderSearchOpts().ModulesSkipDiagnosticOptions =
true;
431 ScanInvocation->getHeaderSearchOpts().ModulesSkipHeaderSearchPaths =
true;
432 ScanInvocation->getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings =
434 ScanInvocation->getHeaderSearchOpts().ModulesForceValidateUserHeaders =
false;
439 if (ScanInvocation->getPreprocessorOpts().ImplicitPCHInclude.empty()) {
442 ScanInvocation->getLangOpts().AppExt =
false;
447 ScanInvocation->getDependencyOutputOpts() = {};
451 return ScanInvocation;
461 if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot))
466static std::optional<PrebuiltModulesAttrsMap>
479 PrebuiltModulesASTMap, ScanInstance.
getDiagnostics(), StableDirs))
482 return PrebuiltModulesASTMap;
485static std::unique_ptr<DependencyOutputOptions>
487 auto Opts = std::make_unique<DependencyOutputOptions>(
491 if (Opts->Targets.empty())
494 Opts->IncludeSystemHeaders =
true;
499static std::shared_ptr<ModuleDepCollector>
502 std::unique_ptr<DependencyOutputOptions> DepOutputOpts,
507 auto MDC = std::make_shared<ModuleDepCollector>(
508 Service, std::move(DepOutputOpts), ScanInstance, Controller, Inv,
509 std::move(PrebuiltModulesASTMap), StableDirs);
516class AsyncModuleCompiles {
520 std::vector<std::thread> Compiles;
525 void add(llvm::unique_function<
void()> Compile) {
526 std::lock_guard<std::mutex> Lock(Mutex);
528 Compiles.emplace_back(std::move(Compile));
531 ~AsyncModuleCompiles() {
533 std::lock_guard<std::mutex> Lock(Mutex);
536 for (std::thread &Compile : Compiles)
542 DependencyScanningService &Service;
543 DependencyActionController &Controller;
544 AsyncModuleCompiles &Compiles;
546 SingleModuleWithAsyncModuleCompiles(DependencyScanningService &Service,
547 DependencyActionController &Controller,
548 AsyncModuleCompiles &Compiles)
549 : Service(Service), Controller(Controller), Compiles(Compiles) {}
551 bool BeginSourceFileAction(CompilerInstance &CI)
override;
557 DependencyScanningService &Service;
558 DependencyActionController &Controller;
559 AsyncModuleCompiles &Compiles;
561 SingleTUWithAsyncModuleCompiles(DependencyScanningService &Service,
562 DependencyActionController &Controller,
563 AsyncModuleCompiles &Compiles)
564 : Service(Service), Controller(Controller), Compiles(Compiles) {}
566 bool BeginSourceFileAction(CompilerInstance &CI)
override;
572 CompilerInstance &CI;
573 DependencyScanningService &Service;
574 DependencyActionController &Controller;
575 AsyncModuleCompiles &Compiles;
577 AsyncModuleCompile(CompilerInstance &CI, DependencyScanningService &Service,
578 DependencyActionController &Controller,
579 AsyncModuleCompiles &Compiles)
580 : CI(CI), Service(Service), Controller(Controller), Compiles(Compiles) {}
582 void moduleLoadSkipped(
Module *M)
override {
585 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
586 ModuleCache &ModCache = CI.getModuleCache();
591 if (Timestamp > CI.getHeaderSearchOpts().BuildSessionTimestamp)
594 if (!CI.getASTReader())
595 CI.createASTReader();
596 SmallVector<ASTReader::ImportedModule, 0> Imported;
601 switch (CI.getASTReader()->ReadASTCore(
603 nullptr, Imported, {}, {}, {},
622 auto Lock = ModCache.
getLock(ModuleFileName);
624 llvm::Error LockErr = Lock->tryLock().moveInto(Owned);
626 if (!LockErr && !Owned)
629 IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS =
630 llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
631 Service, Service.getOpts().MakeVFS());
633 CI.getDiagnostics(), std::move(
VFS));
634 auto DC = std::make_unique<DiagnosticConsumer>();
636 Service.getLogger());
637 CompilerInstance::ThreadSafeCloneConfig CloneConfig(std::move(
VFS), *DC,
639 auto ModCI1 = CI.cloneForModuleCompile(SourceLocation(), M, ModuleFileName,
641 auto ModCI2 = CI.cloneForModuleCompile(SourceLocation(), M, ModuleFileName,
644 auto ModController = Controller.clone();
649 Compiles.add([Lock = std::move(Lock), ModCI1 = std::move(ModCI1),
650 ModCI2 = std::move(ModCI2), DC = std::move(DC),
651 ModController = std::move(ModController), Service = &Service,
652 Compiles = &Compiles] {
653 llvm::CrashRecoveryContext CRC;
654 (void)CRC.RunSafely([&] {
656 SingleModuleWithAsyncModuleCompiles Action1(*Service, *ModController,
658 (void)ModCI1->ExecuteAction(Action1);
660 ModCI2->getPreprocessorOpts().SingleModuleParseMode = false;
661 GenerateModuleFromModuleMapAction Action2;
662 (void)ModCI2->ExecuteAction(Action2);
668bool SingleModuleWithAsyncModuleCompiles::BeginSourceFileAction(
672 std::make_unique<AsyncModuleCompile>(CI, Service, Controller, Compiles));
676bool SingleTUWithAsyncModuleCompiles::BeginSourceFileAction(
677 CompilerInstance &CI) {
680 std::make_unique<AsyncModuleCompile>(CI, Service, Controller, Compiles));
688 AsyncModuleCompiles &Compiles) {
689 SingleTUWithAsyncModuleCompiles Action(Service, Controller, Compiles);
694namespace dependencies {
696std::unique_ptr<DiagnosticOptions>
698 std::vector<const char *> CCommandLine(CommandLine.size(),
nullptr);
699 llvm::transform(CommandLine, CCommandLine.begin(),
700 [](
const std::string &Str) { return Str.c_str(); });
708class ModuleMapLookup {
711 : CI(CI), HSOpts(CI.getHeaderSearchOpts()),
713 SourceMgr(Diags, CI.getFileManager()),
714 HS(HSOpts, SourceMgr, Diags, CI.getLangOpts(), &CI.getTarget()) {
722 llvm::StringMap<std::string>
734 llvm::StringMap<std::string>
Result;
736 for (StringRef Name : ModuleNames) {
748 Result[Name] = std::string(Path);
754 CompilerInstance &CI;
755 HeaderSearchOptions HSOpts;
756 DiagnosticOptions DiagOpts;
757 DiagnosticsEngine Diags;
758 SourceManager SourceMgr;
763class CompilerInstanceWithContext {
767 std::vector<std::string> CommandLine;
770 std::unique_ptr<CompilerInvocation> OriginalInvocation;
773 std::unique_ptr<DependencyOutputOptions> OutputOpts;
783 std::unique_ptr<CompilerInstance> CIPtr;
786 int32_t SrcLocOffset = 0;
790 :
Worker(Worker), CWD(CWD), CommandLine(CMD.begin(), CMD.end()) {}
796 auto LogLine = Worker.Service.getLogger().log();
801 ScanFS = Worker.makeEffectiveVFS(CWD, std::move(OverlayFS));
803 if (!OriginalInvocation) {
804 DiagEngine.
Report(diag::err_fe_expected_compiler_job)
805 << llvm::join(CommandLine,
" ");
809 return initializeScanInstance(Controller, DiagEngine.
getClient());
814 assert(OriginalInvocation && ScanFS &&
815 "OriginalInvocation and ScanFS must be set before this call");
817 if (
any(Worker.Service.getOpts().OptimizeArgs &
823 Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
824 CIPtr = std::make_unique<CompilerInstance>(
827 Worker.PCHContainerOps, std::move(ModCache));
834 auto MaybePrebuiltModulesASTMap =
836 if (!MaybePrebuiltModulesASTMap)
839 PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
850 bool prescanModulesAsync(AsyncModuleCompiles &Compiles,
853 Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
855 std::make_shared<CompilerInvocation>(CIPtr->getInvocation()),
856 Worker.PCHContainerOps, std::move(ModCache));
860 Worker.Service, Worker.DepFS);
876 static std::optional<CompilerInstanceWithContext>
882 CompilerInstanceWithContext CIWC(Worker, CWD, CC1CommandLine);
883 if (!CIWC.initialize(Controller, DiagEngine, std::move(OverlayFS)))
885 return std::move(CIWC);
890 static std::optional<CompilerInstanceWithContext>
896 auto FS = Worker.makeEffectiveVFS(CWD, OverlayFS);
902 *DiagEngine, std::move(OverlayFS),
908 Worker.Service.getLogger().log() <<
"start scan_by_name: " << ModuleName;
909 llvm::scope_exit ExitLogging([&] {
910 Worker.Service.getLogger().log() <<
"finish scan_by_name: " << ModuleName;
913 llvm::report_fatal_error(
"exceeded maximum by-name scans for worker");
915 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
926 llvm::scope_exit CleanUp([&]() {
935 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
940 *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
943 if (!Controller.
initialize(CI, ModuleInvocation))
949 std::unique_ptr<FrontendAction> Action =
950 std::make_unique<PreprocessOnlyAction>();
952 bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
953 assert(ActionBeginSucceeded &&
"Action BeginSourceFile must succeed");
954 (void)ActionBeginSucceeded;
967 assert(!PPFailed &&
"Preprocess must be able to enter the main file.");
969 CB = MDC->getPPCallbacks();
974 MDC->attachToPreprocessor(PP);
975 CB = MDC->getPPCallbacks();
982 FileType, PrevFID, IDLocation);
990 Path.emplace_back(IDLocation,
ModuleID);
994 assert(CB &&
"Must have PPCallbacks after module loading");
1004 MDC->applyDiscoveredDependencies(ModuleInvocation);
1008 return Controller.
finalize(CI, CowModuleInvocation);
1019 llvm::StringMap<std::string>
1021 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
1022 return ModuleMapLookup(*CIPtr).computeModuleMapsForModules(ModuleNames);
1025 std::shared_ptr<ModuleDepCollector>
1028 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
1031 std::optional<AsyncModuleCompiles> AsyncCompiles;
1032 if (Worker.Service.getOpts().AsyncScanModules) {
1033 AsyncCompiles.emplace();
1034 if (!prescanModulesAsync(*AsyncCompiles, Controller))
1039 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
1040 Worker.Service, *OriginalInvocation, Controller, PrebuiltModuleASTMap,
1046 if (!Controller.
initialize(CI, *OriginalInvocation))
1054 if (!
applyAndReport(*MDC, *OriginalInvocation, Consumer, Controller,
1064 StringRef Executable) {
1068 return Controller.
finalize(*CIPtr, CowModuleInvocation);
1083 : Service(Service) {
1084 PCHContainerOps = std::make_shared<PCHContainerOperations>();
1086 PCHContainerOps->registerReader(
1087 std::make_unique<ObjectFilePCHContainerReader>());
1089 PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>());
1091 auto BaseFS = Service.getOpts().MakeVFS();
1093 if (Service.getOpts().TraceVFS) {
1094 TracingFS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(
1099 DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
1100 Service, std::move(BaseFS), std::move(LocalFS));
1107 StringRef WorkingDirectory,
1112 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(std::move(FS));
1113 NewFS->pushOverlay(std::move(OverlayFS));
1114 FS = std::move(NewFS);
1116 FS->setCurrentWorkingDirectory(WorkingDirectory);
1127 bool Scanned =
false;
1128 std::shared_ptr<ModuleDepCollector> MDC;
1129 std::optional<CompilerInstanceWithContext> CIWC;
1131 const bool Success = llvm::all_of(CommandLines, [&](
const auto &Cmd) {
1132 if (StringRef(Cmd[1]) !=
"-cc1") {
1135 {Cmd.front(), {Cmd.begin() + 1, Cmd.end()}});
1139 Service.getLogger().log().logArray(
"starting scanning command:",
" ", Cmd);
1140 llvm::scope_exit ExitLogging([&] {
1141 Service.getLogger().log().logArray(
"finished scanning command:",
" ",
1158 *
this, WorkingDirectory, Cmd, *DiagEngine, OverlayFS, Controller);
1161 CIWC.emplace(std::move(*
Result));
1162 MDC = CIWC->scanTranslationUnit(DepConsumer, Controller);
1163 return MDC !=
nullptr;
1177 assert(CIWC &&
"Must have an initialized CIWC");
1178 return CIWC->applyAndReport(*MDC, *Invocation, DepConsumer, Controller,
1189 llvm::function_ref<std::optional<std::string>()> getNextName,
1191 std::optional<CompilerInstanceWithContext> CIWC =
1193 *
this, CWD, CC1CommandLine, DiagConsumer, std::move(OverlayFS),
1198 bool AllScansSucceeded =
true;
1199 while (std::optional<std::string> NextName = getNextName()) {
1201 CIWC->computeDependencies(*NextName, DepConsumer, Controller);
1203 AllScansSucceeded = AllScansSucceeded &&
Success;
1205 return AllScansSucceeded;
1208std::optional<llvm::StringMap<std::string>>
1214 std::optional<CompilerInstanceWithContext> CIWC =
1216 *
this, CWD, CC1CommandLine, DiagConsumer, std::move(OverlayFS),
1219 return std::nullopt;
1220 return CIWC->computeModuleMapsForModules(ModuleNames);
Defines the Diagnostic-related interfaces.
static std::shared_ptr< ModuleDepCollector > initializeScanInstanceDependencyCollector(CompilerInstance &ScanInstance, std::unique_ptr< DependencyOutputOptions > DepOutputOpts, DependencyScanningService &Service, CompilerInvocation &Inv, DependencyActionController &Controller, PrebuiltModulesAttrsMap PrebuiltModulesASTMap, SmallVector< StringRef > &StableDirs)
static std::unique_ptr< CompilerInvocation > createCompilerInvocation(ArrayRef< std::string > CommandLine, DiagnosticsEngine &Diags)
static std::unique_ptr< DependencyOutputOptions > createDependencyOutputOptions(const CompilerInvocation &Invocation)
static std::shared_ptr< CompilerInvocation > createScanCompilerInvocation(const CompilerInvocation &Invocation, const DependencyScanningService &Service, DependencyActionController &Controller)
static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts, const HeaderSearchOptions &ExistingHSOpts, DiagnosticsEngine *Diags, const LangOptions &LangOpts)
static std::string deduceDepTarget(const std::string &OutputFile, const SmallVectorImpl< FrontendInputFile > &InputFiles)
Deduce the dependency target based on the output file and input files.
static std::optional< PrebuiltModulesAttrsMap > computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, llvm::SmallVector< StringRef > &StableDirs)
static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename, CompilerInstance &CI, PrebuiltModuleFilesT &ModuleFiles, PrebuiltModulesAttrsMap &PrebuiltModulesASTMap, DiagnosticsEngine &Diags, const ArrayRef< StringRef > StableDirs)
Visit the given prebuilt module and collect all of the modules it transitively imports and contributi...
static void sanitizeDiagOpts(DiagnosticOptions &DiagOpts)
Sanitize diagnostic options for dependency scan.
static void runTUModulePrescan(CompilerInstance &PrescanCI, DependencyScanningService &Service, DependencyActionController &Controller, AsyncModuleCompiles &Compiles)
static void initializeScanCompilerInstance(CompilerInstance &ScanInstance, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service, IntrusiveRefCntPtr< DependencyScanningWorkerFilesystem > DepFS)
static llvm::SmallVector< StringRef > getInitialStableDirs(const CompilerInstance &ScanInstance)
static void canonicalizeDefines(PreprocessorOptions &PPOpts)
static std::string makeObjFileName(StringRef FileName)
Transform arbitrary file name into an object-like file name.
static std::optional< StringRef > getSimpleMacroName(StringRef Macro)
Result
Implement __builtin_bit_cast and related operations.
Defines the clang::Preprocessor interface.
This file declares semantic analysis for OpenACC constructs and clauses.
Abstract interface for callback invocations by the ASTReader.
@ ARR_Missing
The client can handle an AST file that cannot load because it is missing.
@ ARR_OutOfDate
The client can handle an AST file that cannot load because it is out-of-date relative to its input fi...
@ ARR_TreatModuleWithErrorsAsOutOfDate
If a module file is marked with errors treat it as out-of-date so the caller can rebuild it.
static bool readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache, const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, ASTReaderListener &Listener, bool ValidateDiagnosticOptions, unsigned ClientLoadCapabilities=ARR_ConfigurationMismatch|ARR_OutOfDate)
Read the control block for the named AST file.
@ Success
The control block was read successfully.
@ OutOfDate
The AST file is out-of-date relative to its input files, and needs to be regenerated.
@ Missing
The AST file was missing.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
void clearDependencyCollectors()
void createDiagnostics(DiagnosticConsumer *Client=nullptr, bool ShouldOwnClient=true)
Create the diagnostics engine using the invocation's diagnostic options and replace any existing one ...
const PCHContainerReader & getPCHContainerReader() const
Return the appropriate PCHContainerReader depending on the current CodeGenOptions.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective) override
Attempt to load the given module.
void createFileManager()
Create the file manager and replace any existing one with it.
FileManager & getFileManager() const
Return the current file manager to the caller.
ModuleCache & getModuleCache() const
void addDependencyCollector(std::shared_ptr< DependencyCollector > Listener)
Preprocessor & getPreprocessor() const
Return the current preprocessor.
void createVirtualFileSystem(IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS=llvm::vfs::getRealFileSystem(), DiagnosticConsumer *DC=nullptr)
Create a virtual file system instance based on the invocation.
FrontendOptions & getFrontendOpts()
HeaderSearchOptions & getHeaderSearchOpts()
void createSourceManager()
Create the source manager and replace any existing one with it.
CompilerInvocation & getInvocation()
PreprocessorOptions & getPreprocessorOpts()
TargetInfo & getTarget() const
bool ExecuteAction(FrontendAction &Act)
ExecuteAction - Execute the provided action against the compiler's CompilerInvocation object.
LangOptions & getLangOpts()
void setDependencyDirectivesGetter(std::unique_ptr< DependencyDirectivesGetter > Getter)
std::vector< std::string > getCC1CommandLine() const
Generate cc1-compatible command line arguments from this instance, wrapping the result as a std::vect...
Helper class for holding the data necessary to invoke the compiler.
PreprocessorOptions & getPreprocessorOpts()
static bool CreateFromArgs(CompilerInvocation &Res, ArrayRef< const char * > CommandLineArgs, DiagnosticsEngine &Diags, const char *Argv0=nullptr)
Create a compiler invocation from a list of input options.
DependencyOutputOptions & getDependencyOutputOpts()
R withCowRef(llvm::function_ref< R(CowCompilerInvocation &)> Fn)
Invokes the Fn with CowCompilerInvocation representing this.
FrontendOptions & getFrontendOpts()
Same as CompilerInvocation, but with copy-on-write optimization.
Functor that returns the dependency directives for a given file.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Used for handling and querying diagnostic IDs.
Options for controlling the compiler diagnostics engine.
std::vector< std::string > Warnings
The list of -W... options used to alter the diagnostic mappings, with the prefixes removed.
std::string DiagnosticSerializationFile
The file to serialize diagnostics to (non-appending).
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool hasErrorOccurred() const
void setIgnoreAllWarnings(bool Val)
When set to true, any unmapped warnings are ignored.
DiagnosticConsumer * getClient()
void Reset(bool soft=false)
Reset the state of the diagnostic object to its initial configuration.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
llvm::vfs::FileSystem & getVirtualFileSystem() const
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Get a FileEntryRef if it exists, without doing anything on error.
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.
One of these records is kept for each identifier that is lexed.
A diagnostic client that ignores all diagnostics.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
void logArray(StringRef Prefix, StringRef Sep, const RangeT &Arr)
virtual std::time_t getModuleTimestamp(StringRef ModuleFilename)=0
Returns the timestamp denoting the last time inputs of the module file were validated.
virtual std::unique_ptr< llvm::AdvisoryLock > getLock(StringRef ModuleFilename)=0
Returns lock for the given module file. The lock is initially unlocked.
bool empty() const
Checks whether the module file name is empty.
static ModuleFileName makeExplicit(std::string Name)
Creates a file name for an explicit module.
StringRef str() const
Returns the plain module file name.
void setBuildingModule(bool BuildingModuleFlag)
Flag indicating whether this instance is building a module.
std::error_code canonicalizeModuleMapPath(SmallVectorImpl< char > &Path)
Canonicalize Path in a manner suitable for a module map file.
@ Hidden
All of the names in this module are hidden.
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
This interface provides a way to observe the actions of the preprocessor as it does its thing.
virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc)
Callback invoked whenever the Lexer moves to a different file for lexing.
virtual void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported)
Callback invoked whenever there was an explicit module-import syntax.
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
bool SingleModuleParseMode
When enabled, preprocessor is in a mode for parsing a single module only.
std::vector< std::pair< std::string, bool > > Macros
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
bool EnterSourceFile(FileID FID, ConstSearchDirIterator Dir, SourceLocation Loc, bool IsFirstIncludeOfFile=true)
Add a source file to the top of the include stack and start lexing tokens from it instead of the curr...
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
SourceManager & getSourceManager() const
Preprocessor-based frontend action that also loads PCH files.
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
FileID getMainFileID() const
Returns the FileID of the main source file.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
The base class of the type hierarchy.
static std::optional< CompilerInstanceWithContext > initializeFromCC1Commandline(DependencyScanningWorker &Worker, StringRef CWD, ArrayRef< std::string > CC1CommandLine, DiagnosticConsumer &DiagConsumer, IntrusiveRefCntPtr< llvm::vfs::FileSystem > OverlayFS, DependencyActionController &Controller)
Initialize from a cc1 command line, reporting diagnostics to DiagConsumer.
std::shared_ptr< ModuleDepCollector > scanTranslationUnit(DependencyConsumer &Consumer, DependencyActionController &Controller)
bool applyAndReport(ModuleDepCollector &MDC, CompilerInvocation &ModuleInvocation, DependencyConsumer &Consumer, DependencyActionController &Controller, StringRef Executable)
llvm::StringMap< std::string > computeModuleMapsForModules(ArrayRef< StringRef > ModuleNames)
bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer, DependencyActionController &Controller)
static std::optional< CompilerInstanceWithContext > initializeFromCC1Commandline(DependencyScanningWorker &Worker, StringRef CWD, ArrayRef< std::string > CC1CommandLine, DiagnosticsEngine &DiagEngine, IntrusiveRefCntPtr< llvm::vfs::FileSystem > OverlayFS, DependencyActionController &Controller)
Dependency scanner callbacks that are used during scanning to influence the behaviour of the scan - f...
virtual void initializeScanInvocation(CompilerInvocation &ScanInvocation)
Initializes the scan invocation.
virtual bool initialize(CompilerInstance &ScanInstance, CompilerInvocation &NewInvocation)
Initializes the scan instance and modifies the resulting TU invocation.
virtual bool finalize(CompilerInstance &ScanInstance, CowCompilerInvocation &NewInvocation)
Finalizes the scan instance and modifies the resulting TU invocation.
virtual void handleBuildCommand(Command Cmd)
virtual void finishQuery(StringRef ModuleName, bool Success)
The dependency scanning service contains shared configuration and state that is used by the individua...
const DependencyScanningServiceOptions & getOpts() const
An individual dependency scanning worker that is able to run on its own thread.
bool computeDependenciesByName(StringRef CWD, ArrayRef< std::string > CC1CommandLine, IntrusiveRefCntPtr< llvm::vfs::FileSystem > OverlayFS, DiagnosticConsumer &DiagConsumer, DependencyActionController &Controller, llvm::function_ref< std::optional< std::string >()> getNextName, DependencyConsumer &DepConsumer)
By-name scanning over a single cc1 command line.
DependencyScanningWorker(DependencyScanningService &Service, IntrusiveRefCntPtr< llvm::vfs::FileSystem > LocalFS=nullptr)
Construct a dependency scanning worker.
bool computeDependencies(StringRef WorkingDirectory, ArrayRef< ArrayRef< std::string > > CommandLines, DependencyConsumer &DepConsumer, DependencyActionController &Controller, DiagnosticConsumer &DiagConsumer, IntrusiveRefCntPtr< llvm::vfs::FileSystem > OverlayFS=nullptr)
Run the dependency scanning tool for all given frontend command-lines, and report the discovered depe...
~DependencyScanningWorker()
IntrusiveRefCntPtr< llvm::vfs::FileSystem > makeEffectiveVFS(StringRef WorkingDirectory, IntrusiveRefCntPtr< llvm::vfs::FileSystem > OverlayFS=nullptr) const
Creates the effective VFS that will be used for the scan.
std::optional< llvm::StringMap< std::string > > computeModuleMapsForModules(StringRef CWD, ArrayRef< std::string > CC1CommandLine, IntrusiveRefCntPtr< llvm::vfs::FileSystem > OverlayFS, DiagnosticConsumer &DiagConsumer, DependencyActionController &Controller, ArrayRef< StringRef > ModuleNames)
Creates a compiler instance to return a map of module names to their defined module map path.
static const int32_t MaxNumOfByNameQueries
Collects modular and non-modular dependencies of the main file by attaching ModuleDepCollectorPP to t...
void applyDiscoveredDependencies(CompilerInvocation &CI)
Apply any changes implied by the discovered dependencies to the given invocation, (e....
void setVFS(llvm::StringSet<> &&VFS)
Update the VFSMap to the one discovered from serializing the AST file.
bool isInStableDir() const
Read-only access to whether the module is made up of dependencies in stable directories.
void addDependent(StringRef ModuleFile)
Add a direct dependent module file, so it can be updated if the current module is from stable directo...
void setInStableDir(bool V=false)
Update whether the prebuilt module resolves entirely in a stable directories.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool areOptionsInStableDir(const ArrayRef< StringRef > Directories, const HeaderSearchOptions &HSOpts)
Determine if options collected from a module's compilation can safely be considered as stable.
@ VFS
Remove unused -ivfsoverlay arguments.
@ Macros
Canonicalize -D and -U options.
@ HeaderSearch
Remove unused header search paths including header maps.
llvm::StringMap< PrebuiltModuleASTAttrs > PrebuiltModulesAttrsMap
Attributes loaded from AST files of prebuilt modules collected prior to ModuleDepCollector creation.
std::unique_ptr< DiagnosticOptions > createScanningDiagOptions(ArrayRef< std::string > CommandLine)
std::shared_ptr< ModuleCache > makeInProcessModuleCache(ModuleCacheEntries &Entries, AtomicLineLogger &Logger)
bool isPathInStableDir(const ArrayRef< StringRef > Directories, const StringRef Input)
Determine if Input can be resolved within a stable directory.
@ GeneratePCH
Generate pre-compiled header.
ModuleKind
Specifies the kind of module that has been loaded.
@ MK_ExplicitModule
File is an explicitly-loaded module.
@ MK_ImplicitModule
File is an implicitly-loaded module.
Top level wrappers for InstallAPI frontend operations.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
void ApplyHeaderSearchOptions(HeaderSearch &HS, const HeaderSearchOptions &HSOpts, const LangOptions &Lang, const llvm::Triple &triple)
Apply the header search options to get given HeaderSearch object.
@ Success
Annotation was successful.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ Result
The result type of a method or function.
IntrusiveRefCntPtr< llvm::vfs::FileSystem > createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags)
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
ScanningMode Mode
Whether to use optimized dependency directive scan or full preprocessing.
bool ValidateAgainstInvalidatedPaths
Whether scanning modules validate their directory deps against paths reported via DependencyScanningS...
bool EmitWarnings
Whether the scanner should emit warnings.
std::time_t BuildSessionTimestamp
The build session timestamp for validate-once-per-build-session logic.
ScanningOptimizations OptimizeArgs
How to optimize resulting explicit module command lines.
This is used to identify a specific module.