20#include "llvm/ADT/IntrusiveRefCntPtr.h"
21#include "llvm/ADT/ScopeExit.h"
22#include "llvm/Option/Option.h"
23#include "llvm/Support/AdvisoryLock.h"
24#include "llvm/Support/CrashRecoveryContext.h"
25#include "llvm/Support/VirtualFileSystem.h"
26#include "llvm/TargetParser/Host.h"
37 if (LangOpts.Modules) {
40 Diags->
Report(diag::warn_pch_vfsoverlay_mismatch);
42 if (VFSOverlays.empty()) {
43 Diags->
Report(diag::note_pch_vfsoverlay_empty) <<
Type;
45 std::string Files = llvm::join(VFSOverlays,
"\n");
46 Diags->
Report(diag::note_pch_vfsoverlay_files) <<
Type << Files;
64 PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
65 llvm::SmallVector<std::string> &NewModuleFiles,
67 const HeaderSearchOptions &HSOpts,
68 const LangOptions &LangOpts, DiagnosticsEngine &Diags,
69 const ArrayRef<StringRef> StableDirs)
70 : PrebuiltModuleFiles(PrebuiltModuleFiles),
71 NewModuleFiles(NewModuleFiles),
72 PrebuiltModulesASTMap(PrebuiltModulesASTMap), ExistingHSOpts(HSOpts),
73 ExistingLangOpts(LangOpts), Diags(Diags), StableDirs(StableDirs) {}
75 bool needsImportVisitation()
const override {
return true; }
76 bool needsInputFileVisitation()
override {
return true; }
77 bool needsSystemInputFileVisitation()
override {
return true; }
81 void visitImport(StringRef ModuleName, StringRef Filename)
override {
82 if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second)
83 NewModuleFiles.push_back(Filename.str());
85 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(Filename);
86 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
87 if (PrebuiltMapEntry.second)
90 if (
auto It = PrebuiltModulesASTMap.find(CurrentFile);
91 It != PrebuiltModulesASTMap.end() && CurrentFile != Filename)
98 bool visitInputFileAsRequested(StringRef FilenameAsRequested,
99 StringRef Filename,
bool isSystem,
100 bool isOverridden, time_t StoredTime,
101 bool isExplicitModule)
override {
102 if (StableDirs.empty())
104 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
105 if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end()) ||
106 (!PrebuiltEntryIt->second.isInStableDir()))
109 PrebuiltEntryIt->second.setInStableDir(
111 return PrebuiltEntryIt->second.isInStableDir();
116 bool DirectlyImported)
override {
119 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
120 if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end()) &&
121 !PrebuiltEntryIt->second.isInStableDir())
122 PrebuiltEntryIt->second.updateDependentsNotInStableDirs(
123 PrebuiltModulesASTMap);
124 CurrentFile = Filename.
str();
129 bool ReadHeaderSearchOptions(
const HeaderSearchOptions &HSOpts,
130 StringRef ModuleFilename, StringRef ContextHash,
131 bool Complain)
override {
133 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
134 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
135 if (PrebuiltMapEntry.second)
145 bool ReadHeaderSearchPaths(
const HeaderSearchOptions &HSOpts,
146 bool Complain)
override {
148 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
149 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
150 if (PrebuiltMapEntry.second)
157 HSOpts, ExistingHSOpts, Complain ? &Diags :
nullptr, ExistingLangOpts);
161 PrebuiltModuleFilesT &PrebuiltModuleFiles;
162 llvm::SmallVector<std::string> &NewModuleFiles;
164 const HeaderSearchOptions &ExistingHSOpts;
165 const LangOptions &ExistingLangOpts;
166 DiagnosticsEngine &Diags;
167 std::string CurrentFile;
168 const ArrayRef<StringRef> StableDirs;
176 PrebuiltModuleFilesT &ModuleFiles,
183 PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModulesASTMap,
197 while (!Worklist.empty()) {
219 llvm::sys::path::replace_extension(ObjFileName,
"o");
220 return std::string(ObjFileName);
227 if (OutputFile !=
"-")
230 if (InputFiles.empty() || !InputFiles.front().isFile())
231 return "clang-scan-deps\\ dependency";
247 StringRef Name =
Macro.split(
"=").first.ltrim(
" \t");
250 auto FinishName = [&]() -> std::optional<StringRef> {
251 StringRef SimpleName = Name.slice(0, I);
252 if (SimpleName.empty())
257 for (; I != Name.size(); ++I) {
266 if (llvm::isAlnum(Name[I]))
275 using MacroOpt = std::pair<StringRef, std::size_t>;
276 std::vector<MacroOpt> SimpleNames;
277 SimpleNames.reserve(PPOpts.
Macros.size());
278 std::size_t Index = 0;
279 for (
const auto &M : PPOpts.
Macros) {
284 SimpleNames.emplace_back(*SName, Index);
288 llvm::stable_sort(SimpleNames, llvm::less_first());
290 auto NewEnd = std::unique(
291 SimpleNames.rbegin(), SimpleNames.rend(),
292 [](
const MacroOpt &A,
const MacroOpt &B) { return A.first == B.first; });
293 SimpleNames.erase(SimpleNames.begin(), NewEnd.base());
296 decltype(PPOpts.
Macros) NewMacros;
297 NewMacros.reserve(SimpleNames.size());
298 for (std::size_t I = 0, E = SimpleNames.size(); I != E; ++I) {
299 std::size_t OriginalIndex = SimpleNames[I].second;
301 NewMacros.push_back(std::move(PPOpts.
Macros[OriginalIndex]));
303 std::swap(PPOpts.
Macros, NewMacros);
308 DependencyScanningWorkerFilesystem *DepFS;
311 ScanningDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(
nullptr) {
313 auto *
DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
315 assert(!DepFS &&
"Found multiple scanning VFSs");
319 assert(DepFS &&
"Did not find scanning VFS");
322 std::unique_ptr<DependencyDirectivesGetter>
323 cloneFor(FileManager &FileMgr)
override {
324 return std::make_unique<ScanningDependencyDirectivesGetter>(FileMgr);
327 std::optional<ArrayRef<dependency_directives_scan::Directive>>
328 operator()(FileEntryRef
File)
override {
329 return DepFS->getDirectiveTokens(
File.getName());
337 DiagOpts.ShowCarets =
false;
348 return llvm::StringSwitch<bool>(Warning)
349 .Cases({
"pch-vfs-diff",
"error=pch-vfs-diff"},
false)
350 .StartsWith(
"no-error=",
false)
355static std::unique_ptr<CompilerInvocation>
358 llvm::opt::ArgStringList Argv;
359 for (
const std::string &Str :
ArrayRef(CommandLine).drop_front())
360 Argv.push_back(Str.c_str());
362 auto Invocation = std::make_unique<CompilerInvocation>();
384 if (Service.
getOpts().
Mode == ScanningMode::DependencyDirectivesScan)
386 std::make_unique<ScanningDependencyDirectivesGetter>(
390static std::shared_ptr<CompilerInvocation>
394 auto ScanInvocation = std::make_shared<CompilerInvocation>(Invocation);
398 ScanInvocation->getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath =
401 if (ScanInvocation->getHeaderSearchOpts().ModulesValidateOncePerBuildSession)
402 ScanInvocation->getHeaderSearchOpts().BuildSessionTimestamp =
405 ScanInvocation->getFrontendOpts().DisableFree =
false;
406 ScanInvocation->getFrontendOpts().GenerateGlobalModuleIndex =
false;
407 ScanInvocation->getFrontendOpts().UseGlobalModuleIndex =
false;
408 ScanInvocation->getFrontendOpts().GenReducedBMI =
false;
409 ScanInvocation->getFrontendOpts().ModuleOutputPath.clear();
412 ScanInvocation->getFrontendOpts().ModulesShareFileManager =
true;
413 ScanInvocation->getHeaderSearchOpts().ModuleFormat =
"raw";
414 ScanInvocation->getHeaderSearchOpts().ModulesIncludeVFSUsage =
422 ScanInvocation->getHeaderSearchOpts().ModulesStrictContextHash =
true;
423 ScanInvocation->getHeaderSearchOpts().ModulesSerializeOnlyPreprocessor =
true;
424 ScanInvocation->getHeaderSearchOpts().ModulesSkipDiagnosticOptions =
true;
425 ScanInvocation->getHeaderSearchOpts().ModulesSkipHeaderSearchPaths =
true;
426 ScanInvocation->getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings =
428 ScanInvocation->getHeaderSearchOpts().ModulesForceValidateUserHeaders =
false;
431 ScanInvocation->getPreprocessorOpts().ModulesCheckRelocated =
false;
436 if (ScanInvocation->getPreprocessorOpts().ImplicitPCHInclude.empty()) {
439 ScanInvocation->getLangOpts().AppExt =
false;
444 ScanInvocation->getDependencyOutputOpts() = {};
448 return ScanInvocation;
458 if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot))
463static std::optional<PrebuiltModulesAttrsMap>
476 PrebuiltModulesASTMap, ScanInstance.
getDiagnostics(), StableDirs))
479 return PrebuiltModulesASTMap;
482static std::unique_ptr<DependencyOutputOptions>
484 auto Opts = std::make_unique<DependencyOutputOptions>(
488 if (Opts->Targets.empty())
491 Opts->IncludeSystemHeaders =
true;
496static std::shared_ptr<ModuleDepCollector>
499 std::unique_ptr<DependencyOutputOptions> DepOutputOpts,
504 auto MDC = std::make_shared<ModuleDepCollector>(
505 Service, std::move(DepOutputOpts), ScanInstance, Controller, Inv,
506 std::move(PrebuiltModulesASTMap), StableDirs);
513class AsyncModuleCompiles {
517 std::vector<std::thread> Compiles;
522 void add(llvm::unique_function<
void()> Compile) {
523 std::lock_guard<std::mutex> Lock(Mutex);
525 Compiles.emplace_back(std::move(Compile));
528 ~AsyncModuleCompiles() {
530 std::lock_guard<std::mutex> Lock(Mutex);
533 for (std::thread &Compile : Compiles)
539 DependencyScanningService &Service;
540 DependencyActionController &Controller;
541 AsyncModuleCompiles &Compiles;
543 SingleModuleWithAsyncModuleCompiles(DependencyScanningService &Service,
544 DependencyActionController &Controller,
545 AsyncModuleCompiles &Compiles)
546 : Service(Service), Controller(Controller), Compiles(Compiles) {}
548 bool BeginSourceFileAction(CompilerInstance &CI)
override;
554 DependencyScanningService &Service;
555 DependencyActionController &Controller;
556 AsyncModuleCompiles &Compiles;
558 SingleTUWithAsyncModuleCompiles(DependencyScanningService &Service,
559 DependencyActionController &Controller,
560 AsyncModuleCompiles &Compiles)
561 : Service(Service), Controller(Controller), Compiles(Compiles) {}
563 bool BeginSourceFileAction(CompilerInstance &CI)
override;
569 CompilerInstance &CI;
570 DependencyScanningService &Service;
571 DependencyActionController &Controller;
572 AsyncModuleCompiles &Compiles;
574 AsyncModuleCompile(CompilerInstance &CI, DependencyScanningService &Service,
575 DependencyActionController &Controller,
576 AsyncModuleCompiles &Compiles)
577 : CI(CI), Service(Service), Controller(Controller), Compiles(Compiles) {}
579 void moduleLoadSkipped(
Module *M)
override {
582 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
583 ModuleCache &ModCache = CI.getModuleCache();
588 if (Timestamp > CI.getHeaderSearchOpts().BuildSessionTimestamp)
591 if (!CI.getASTReader())
592 CI.createASTReader();
593 SmallVector<ASTReader::ImportedModule, 0> Imported;
598 switch (CI.getASTReader()->ReadASTCore(
600 nullptr, Imported, {}, {}, {},
619 auto Lock = ModCache.
getLock(ModuleFileName);
621 llvm::Error LockErr = Lock->tryLock().moveInto(Owned);
623 if (!LockErr && !Owned)
626 IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS =
627 llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
628 Service, Service.getOpts().MakeVFS());
630 CI.getDiagnostics(), std::move(
VFS));
631 auto DC = std::make_unique<DiagnosticConsumer>();
633 Service.getLogger());
634 CompilerInstance::ThreadSafeCloneConfig CloneConfig(std::move(
VFS), *DC,
636 auto ModCI1 = CI.cloneForModuleCompile(SourceLocation(), M, ModuleFileName,
638 auto ModCI2 = CI.cloneForModuleCompile(SourceLocation(), M, ModuleFileName,
641 auto ModController = Controller.clone();
646 Compiles.add([Lock = std::move(Lock), ModCI1 = std::move(ModCI1),
647 ModCI2 = std::move(ModCI2), DC = std::move(DC),
648 ModController = std::move(ModController), Service = &Service,
649 Compiles = &Compiles] {
650 llvm::CrashRecoveryContext CRC;
651 (void)CRC.RunSafely([&] {
653 SingleModuleWithAsyncModuleCompiles Action1(*Service, *ModController,
655 (void)ModCI1->ExecuteAction(Action1);
657 ModCI2->getPreprocessorOpts().SingleModuleParseMode = false;
658 GenerateModuleFromModuleMapAction Action2;
659 (void)ModCI2->ExecuteAction(Action2);
665bool SingleModuleWithAsyncModuleCompiles::BeginSourceFileAction(
669 std::make_unique<AsyncModuleCompile>(CI, Service, Controller, Compiles));
673bool SingleTUWithAsyncModuleCompiles::BeginSourceFileAction(
674 CompilerInstance &CI) {
677 std::make_unique<AsyncModuleCompile>(CI, Service, Controller, Compiles));
685 AsyncModuleCompiles &Compiles) {
686 SingleTUWithAsyncModuleCompiles Action(Service, Controller, Compiles);
691namespace dependencies {
693std::unique_ptr<DiagnosticOptions>
695 std::vector<const char *> CCommandLine(CommandLine.size(),
nullptr);
696 llvm::transform(CommandLine, CCommandLine.begin(),
697 [](
const std::string &Str) { return Str.c_str(); });
703class CompilerInstanceWithContext {
707 std::vector<std::string> CommandLine;
710 std::unique_ptr<CompilerInvocation> OriginalInvocation;
713 std::unique_ptr<DependencyOutputOptions> OutputOpts;
723 std::unique_ptr<CompilerInstance> CIPtr;
726 int32_t SrcLocOffset = 0;
730 :
Worker(Worker), CWD(CWD), CommandLine(CMD.begin(), CMD.end()) {}
736 auto LogLine = Worker.Service.getLogger().log();
741 ScanFS = Worker.makeEffectiveVFS(CWD, std::move(OverlayFS));
743 if (!OriginalInvocation) {
744 DiagEngine.
Report(diag::err_fe_expected_compiler_job)
745 << llvm::join(CommandLine,
" ");
749 return initializeScanInstance(Controller, DiagEngine.
getClient());
754 assert(OriginalInvocation && ScanFS &&
755 "OriginalInvocation and ScanFS must be set before this call");
757 if (
any(Worker.Service.getOpts().OptimizeArgs &
763 Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
764 CIPtr = std::make_unique<CompilerInstance>(
767 Worker.PCHContainerOps, std::move(ModCache));
774 auto MaybePrebuiltModulesASTMap =
776 if (!MaybePrebuiltModulesASTMap)
779 PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
790 bool prescanModulesAsync(AsyncModuleCompiles &Compiles,
793 Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
795 std::make_shared<CompilerInvocation>(CIPtr->getInvocation()),
796 Worker.PCHContainerOps, std::move(ModCache));
800 Worker.Service, Worker.DepFS);
816 static std::optional<CompilerInstanceWithContext>
822 CompilerInstanceWithContext CIWC(Worker, CWD, CC1CommandLine);
823 if (!CIWC.initialize(Controller, DiagEngine, std::move(OverlayFS)))
825 return std::move(CIWC);
830 Worker.Service.getLogger().log() <<
"start scan_by_name: " << ModuleName;
831 llvm::scope_exit ExitLogging([&] {
832 Worker.Service.getLogger().log() <<
"finish scan_by_name: " << ModuleName;
835 llvm::report_fatal_error(
"exceeded maximum by-name scans for worker");
837 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
848 llvm::scope_exit CleanUp([&]() {
857 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
862 *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
865 if (!Controller.
initialize(CI, ModuleInvocation))
871 std::unique_ptr<FrontendAction> Action =
872 std::make_unique<PreprocessOnlyAction>();
874 bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
875 assert(ActionBeginSucceeded &&
"Action BeginSourceFile must succeed");
876 (void)ActionBeginSucceeded;
889 assert(!PPFailed &&
"Preprocess must be able to enter the main file.");
891 CB = MDC->getPPCallbacks();
896 MDC->attachToPreprocessor(PP);
897 CB = MDC->getPPCallbacks();
904 FileType, PrevFID, IDLocation);
912 Path.emplace_back(IDLocation,
ModuleID);
915 assert(CB &&
"Must have PPCallbacks after module loading");
925 MDC->applyDiscoveredDependencies(ModuleInvocation);
929 return Controller.
finalize(CI, CowModuleInvocation);
940 std::shared_ptr<ModuleDepCollector>
943 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
946 std::optional<AsyncModuleCompiles> AsyncCompiles;
947 if (Worker.Service.getOpts().AsyncScanModules) {
948 AsyncCompiles.emplace();
949 if (!prescanModulesAsync(*AsyncCompiles, Controller))
954 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
955 Worker.Service, *OriginalInvocation, Controller, PrebuiltModuleASTMap,
961 if (!Controller.
initialize(CI, *OriginalInvocation))
969 if (!
applyAndReport(*MDC, *OriginalInvocation, Consumer, Controller,
979 StringRef Executable) {
983 return Controller.
finalize(*CIPtr, CowModuleInvocation);
998 PCHContainerOps = std::make_shared<PCHContainerOperations>();
1000 PCHContainerOps->registerReader(
1001 std::make_unique<ObjectFilePCHContainerReader>());
1003 PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>());
1005 auto BaseFS = Service.getOpts().MakeVFS();
1007 if (Service.getOpts().TraceVFS) {
1008 TracingFS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(
1013 DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
1014 Service, std::move(BaseFS));
1021 StringRef WorkingDirectory,
1026 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(std::move(FS));
1027 NewFS->pushOverlay(std::move(OverlayFS));
1028 FS = std::move(NewFS);
1030 FS->setCurrentWorkingDirectory(WorkingDirectory);
1041 bool Scanned =
false;
1042 std::shared_ptr<ModuleDepCollector> MDC;
1043 std::optional<CompilerInstanceWithContext> CIWC;
1045 const bool Success = llvm::all_of(CommandLines, [&](
const auto &Cmd) {
1046 if (StringRef(Cmd[1]) !=
"-cc1") {
1049 {Cmd.front(), {Cmd.begin() + 1, Cmd.end()}});
1053 Service.getLogger().log().logArray(
"starting scanning command:",
" ", Cmd);
1054 llvm::scope_exit ExitLogging([&] {
1055 Service.getLogger().log().logArray(
"finished scanning command:",
" ",
1072 *
this, WorkingDirectory, Cmd, *DiagEngine, OverlayFS, Controller);
1075 CIWC.emplace(std::move(*
Result));
1076 MDC = CIWC->scanTranslationUnit(DepConsumer, Controller);
1077 return MDC !=
nullptr;
1091 assert(CIWC &&
"Must have an initialized CIWC");
1092 return CIWC->applyAndReport(*MDC, *Invocation, DepConsumer, Controller,
1103 llvm::function_ref<std::optional<std::string>()> getNextName,
1110 std::optional<CompilerInstanceWithContext> CIWC =
1112 *
this, CWD, CC1CommandLine, *DiagEngine, std::move(OverlayFS),
1117 bool AllScansSucceeded =
true;
1118 while (std::optional<std::string> NextName = getNextName()) {
1120 CIWC->computeDependencies(*NextName, DepConsumer, Controller);
1122 AllScansSucceeded = AllScansSucceeded &&
Success;
1124 return AllScansSucceeded;
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)
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()
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...
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
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.
One of these records is kept for each identifier that is lexed.
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.
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.
@ 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 ...
The base class of the type hierarchy.
std::shared_ptr< ModuleDepCollector > scanTranslationUnit(DependencyConsumer &Consumer, DependencyActionController &Controller)
bool applyAndReport(ModuleDepCollector &MDC, CompilerInvocation &ModuleInvocation, DependencyConsumer &Consumer, DependencyActionController &Controller, StringRef Executable)
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.
DependencyScanningWorker(DependencyScanningService &Service)
Construct a dependency scanning worker.
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.
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.
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.
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
@ 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 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.