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()
402 .ModulesValidateOncePerBuildSession ||
404 ScanInvocation->getHeaderSearchOpts().BuildSessionTimestamp =
407 ScanInvocation->getHeaderSearchOpts().ModulesValidateDirectoryDependencies =
410 ScanInvocation->getFrontendOpts().DisableFree =
false;
411 ScanInvocation->getFrontendOpts().GenerateGlobalModuleIndex =
false;
412 ScanInvocation->getFrontendOpts().UseGlobalModuleIndex =
false;
413 ScanInvocation->getFrontendOpts().GenReducedBMI =
false;
414 ScanInvocation->getFrontendOpts().ModuleOutputPath.clear();
417 ScanInvocation->getFrontendOpts().ModulesShareFileManager =
true;
418 ScanInvocation->getHeaderSearchOpts().ModuleFormat =
"raw";
419 ScanInvocation->getHeaderSearchOpts().ModulesIncludeVFSUsage =
427 ScanInvocation->getHeaderSearchOpts().ModulesStrictContextHash =
true;
428 ScanInvocation->getHeaderSearchOpts().ModulesSerializeOnlyPreprocessor =
true;
429 ScanInvocation->getHeaderSearchOpts().ModulesSkipDiagnosticOptions =
true;
430 ScanInvocation->getHeaderSearchOpts().ModulesSkipHeaderSearchPaths =
true;
431 ScanInvocation->getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings =
433 ScanInvocation->getHeaderSearchOpts().ModulesForceValidateUserHeaders =
false;
438 if (ScanInvocation->getPreprocessorOpts().ImplicitPCHInclude.empty()) {
441 ScanInvocation->getLangOpts().AppExt =
false;
446 ScanInvocation->getDependencyOutputOpts() = {};
450 return ScanInvocation;
460 if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot))
465static std::optional<PrebuiltModulesAttrsMap>
478 PrebuiltModulesASTMap, ScanInstance.
getDiagnostics(), StableDirs))
481 return PrebuiltModulesASTMap;
484static std::unique_ptr<DependencyOutputOptions>
486 auto Opts = std::make_unique<DependencyOutputOptions>(
490 if (Opts->Targets.empty())
493 Opts->IncludeSystemHeaders =
true;
498static std::shared_ptr<ModuleDepCollector>
501 std::unique_ptr<DependencyOutputOptions> DepOutputOpts,
506 auto MDC = std::make_shared<ModuleDepCollector>(
507 Service, std::move(DepOutputOpts), ScanInstance, Controller, Inv,
508 std::move(PrebuiltModulesASTMap), StableDirs);
515class AsyncModuleCompiles {
519 std::vector<std::thread> Compiles;
524 void add(llvm::unique_function<
void()> Compile) {
525 std::lock_guard<std::mutex> Lock(Mutex);
527 Compiles.emplace_back(std::move(Compile));
530 ~AsyncModuleCompiles() {
532 std::lock_guard<std::mutex> Lock(Mutex);
535 for (std::thread &Compile : Compiles)
541 DependencyScanningService &Service;
542 DependencyActionController &Controller;
543 AsyncModuleCompiles &Compiles;
545 SingleModuleWithAsyncModuleCompiles(DependencyScanningService &Service,
546 DependencyActionController &Controller,
547 AsyncModuleCompiles &Compiles)
548 : Service(Service), Controller(Controller), Compiles(Compiles) {}
550 bool BeginSourceFileAction(CompilerInstance &CI)
override;
556 DependencyScanningService &Service;
557 DependencyActionController &Controller;
558 AsyncModuleCompiles &Compiles;
560 SingleTUWithAsyncModuleCompiles(DependencyScanningService &Service,
561 DependencyActionController &Controller,
562 AsyncModuleCompiles &Compiles)
563 : Service(Service), Controller(Controller), Compiles(Compiles) {}
565 bool BeginSourceFileAction(CompilerInstance &CI)
override;
571 CompilerInstance &CI;
572 DependencyScanningService &Service;
573 DependencyActionController &Controller;
574 AsyncModuleCompiles &Compiles;
576 AsyncModuleCompile(CompilerInstance &CI, DependencyScanningService &Service,
577 DependencyActionController &Controller,
578 AsyncModuleCompiles &Compiles)
579 : CI(CI), Service(Service), Controller(Controller), Compiles(Compiles) {}
581 void moduleLoadSkipped(
Module *M)
override {
584 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
585 ModuleCache &ModCache = CI.getModuleCache();
590 if (Timestamp > CI.getHeaderSearchOpts().BuildSessionTimestamp)
593 if (!CI.getASTReader())
594 CI.createASTReader();
595 SmallVector<ASTReader::ImportedModule, 0> Imported;
600 switch (CI.getASTReader()->ReadASTCore(
602 nullptr, Imported, {}, {}, {},
621 auto Lock = ModCache.
getLock(ModuleFileName);
623 llvm::Error LockErr = Lock->tryLock().moveInto(Owned);
625 if (!LockErr && !Owned)
628 IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS =
629 llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
630 Service, Service.getOpts().MakeVFS());
632 CI.getDiagnostics(), std::move(
VFS));
633 auto DC = std::make_unique<DiagnosticConsumer>();
635 Service.getLogger());
636 CompilerInstance::ThreadSafeCloneConfig CloneConfig(std::move(
VFS), *DC,
638 auto ModCI1 = CI.cloneForModuleCompile(SourceLocation(), M, ModuleFileName,
640 auto ModCI2 = CI.cloneForModuleCompile(SourceLocation(), M, ModuleFileName,
643 auto ModController = Controller.clone();
648 Compiles.add([Lock = std::move(Lock), ModCI1 = std::move(ModCI1),
649 ModCI2 = std::move(ModCI2), DC = std::move(DC),
650 ModController = std::move(ModController), Service = &Service,
651 Compiles = &Compiles] {
652 llvm::CrashRecoveryContext CRC;
653 (void)CRC.RunSafely([&] {
655 SingleModuleWithAsyncModuleCompiles Action1(*Service, *ModController,
657 (void)ModCI1->ExecuteAction(Action1);
659 ModCI2->getPreprocessorOpts().SingleModuleParseMode = false;
660 GenerateModuleFromModuleMapAction Action2;
661 (void)ModCI2->ExecuteAction(Action2);
667bool SingleModuleWithAsyncModuleCompiles::BeginSourceFileAction(
671 std::make_unique<AsyncModuleCompile>(CI, Service, Controller, Compiles));
675bool SingleTUWithAsyncModuleCompiles::BeginSourceFileAction(
676 CompilerInstance &CI) {
679 std::make_unique<AsyncModuleCompile>(CI, Service, Controller, Compiles));
687 AsyncModuleCompiles &Compiles) {
688 SingleTUWithAsyncModuleCompiles Action(Service, Controller, Compiles);
693namespace dependencies {
695std::unique_ptr<DiagnosticOptions>
697 std::vector<const char *> CCommandLine(CommandLine.size(),
nullptr);
698 llvm::transform(CommandLine, CCommandLine.begin(),
699 [](
const std::string &Str) { return Str.c_str(); });
705class CompilerInstanceWithContext {
709 std::vector<std::string> CommandLine;
712 std::unique_ptr<CompilerInvocation> OriginalInvocation;
715 std::unique_ptr<DependencyOutputOptions> OutputOpts;
725 std::unique_ptr<CompilerInstance> CIPtr;
728 int32_t SrcLocOffset = 0;
732 :
Worker(Worker), CWD(CWD), CommandLine(CMD.begin(), CMD.end()) {}
738 auto LogLine = Worker.Service.getLogger().log();
743 ScanFS = Worker.makeEffectiveVFS(CWD, std::move(OverlayFS));
745 if (!OriginalInvocation) {
746 DiagEngine.
Report(diag::err_fe_expected_compiler_job)
747 << llvm::join(CommandLine,
" ");
751 return initializeScanInstance(Controller, DiagEngine.
getClient());
756 assert(OriginalInvocation && ScanFS &&
757 "OriginalInvocation and ScanFS must be set before this call");
759 if (
any(Worker.Service.getOpts().OptimizeArgs &
765 Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
766 CIPtr = std::make_unique<CompilerInstance>(
769 Worker.PCHContainerOps, std::move(ModCache));
776 auto MaybePrebuiltModulesASTMap =
778 if (!MaybePrebuiltModulesASTMap)
781 PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
792 bool prescanModulesAsync(AsyncModuleCompiles &Compiles,
795 Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
797 std::make_shared<CompilerInvocation>(CIPtr->getInvocation()),
798 Worker.PCHContainerOps, std::move(ModCache));
802 Worker.Service, Worker.DepFS);
818 static std::optional<CompilerInstanceWithContext>
824 CompilerInstanceWithContext CIWC(Worker, CWD, CC1CommandLine);
825 if (!CIWC.initialize(Controller, DiagEngine, std::move(OverlayFS)))
827 return std::move(CIWC);
832 Worker.Service.getLogger().log() <<
"start scan_by_name: " << ModuleName;
833 llvm::scope_exit ExitLogging([&] {
834 Worker.Service.getLogger().log() <<
"finish scan_by_name: " << ModuleName;
837 llvm::report_fatal_error(
"exceeded maximum by-name scans for worker");
839 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
850 llvm::scope_exit CleanUp([&]() {
859 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
864 *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
867 if (!Controller.
initialize(CI, ModuleInvocation))
873 std::unique_ptr<FrontendAction> Action =
874 std::make_unique<PreprocessOnlyAction>();
876 bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
877 assert(ActionBeginSucceeded &&
"Action BeginSourceFile must succeed");
878 (void)ActionBeginSucceeded;
891 assert(!PPFailed &&
"Preprocess must be able to enter the main file.");
893 CB = MDC->getPPCallbacks();
898 MDC->attachToPreprocessor(PP);
899 CB = MDC->getPPCallbacks();
906 FileType, PrevFID, IDLocation);
914 Path.emplace_back(IDLocation,
ModuleID);
917 assert(CB &&
"Must have PPCallbacks after module loading");
927 MDC->applyDiscoveredDependencies(ModuleInvocation);
931 return Controller.
finalize(CI, CowModuleInvocation);
942 std::shared_ptr<ModuleDepCollector>
945 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
948 std::optional<AsyncModuleCompiles> AsyncCompiles;
949 if (Worker.Service.getOpts().AsyncScanModules) {
950 AsyncCompiles.emplace();
951 if (!prescanModulesAsync(*AsyncCompiles, Controller))
956 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
957 Worker.Service, *OriginalInvocation, Controller, PrebuiltModuleASTMap,
963 if (!Controller.
initialize(CI, *OriginalInvocation))
971 if (!
applyAndReport(*MDC, *OriginalInvocation, Consumer, Controller,
981 StringRef Executable) {
985 return Controller.
finalize(*CIPtr, CowModuleInvocation);
1000 PCHContainerOps = std::make_shared<PCHContainerOperations>();
1002 PCHContainerOps->registerReader(
1003 std::make_unique<ObjectFilePCHContainerReader>());
1005 PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>());
1007 auto BaseFS = Service.getOpts().MakeVFS();
1009 if (Service.getOpts().TraceVFS) {
1010 TracingFS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(
1015 DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
1016 Service, std::move(BaseFS));
1023 StringRef WorkingDirectory,
1028 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(std::move(FS));
1029 NewFS->pushOverlay(std::move(OverlayFS));
1030 FS = std::move(NewFS);
1032 FS->setCurrentWorkingDirectory(WorkingDirectory);
1043 bool Scanned =
false;
1044 std::shared_ptr<ModuleDepCollector> MDC;
1045 std::optional<CompilerInstanceWithContext> CIWC;
1047 const bool Success = llvm::all_of(CommandLines, [&](
const auto &Cmd) {
1048 if (StringRef(Cmd[1]) !=
"-cc1") {
1051 {Cmd.front(), {Cmd.begin() + 1, Cmd.end()}});
1055 Service.getLogger().log().logArray(
"starting scanning command:",
" ", Cmd);
1056 llvm::scope_exit ExitLogging([&] {
1057 Service.getLogger().log().logArray(
"finished scanning command:",
" ",
1074 *
this, WorkingDirectory, Cmd, *DiagEngine, OverlayFS, Controller);
1077 CIWC.emplace(std::move(*
Result));
1078 MDC = CIWC->scanTranslationUnit(DepConsumer, Controller);
1079 return MDC !=
nullptr;
1093 assert(CIWC &&
"Must have an initialized CIWC");
1094 return CIWC->applyAndReport(*MDC, *Invocation, DepConsumer, Controller,
1105 llvm::function_ref<std::optional<std::string>()> getNextName,
1112 std::optional<CompilerInstanceWithContext> CIWC =
1114 *
this, CWD, CC1CommandLine, *DiagEngine, std::move(OverlayFS),
1119 bool AllScansSucceeded =
true;
1120 while (std::optional<std::string> NextName = getNextName()) {
1122 CIWC->computeDependencies(*NextName, DepConsumer, Controller);
1124 AllScansSucceeded = AllScansSucceeded &&
Success;
1126 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 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.