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;
433 if (ScanInvocation->getPreprocessorOpts().ImplicitPCHInclude.empty()) {
436 ScanInvocation->getLangOpts().AppExt =
false;
441 ScanInvocation->getDependencyOutputOpts() = {};
445 return ScanInvocation;
455 if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot))
460static std::optional<PrebuiltModulesAttrsMap>
473 PrebuiltModulesASTMap, ScanInstance.
getDiagnostics(), StableDirs))
476 return PrebuiltModulesASTMap;
479static std::unique_ptr<DependencyOutputOptions>
481 auto Opts = std::make_unique<DependencyOutputOptions>(
485 if (Opts->Targets.empty())
488 Opts->IncludeSystemHeaders =
true;
493static std::shared_ptr<ModuleDepCollector>
496 std::unique_ptr<DependencyOutputOptions> DepOutputOpts,
501 auto MDC = std::make_shared<ModuleDepCollector>(
502 Service, std::move(DepOutputOpts), ScanInstance, Controller, Inv,
503 std::move(PrebuiltModulesASTMap), StableDirs);
510class AsyncModuleCompiles {
514 std::vector<std::thread> Compiles;
519 void add(llvm::unique_function<
void()> Compile) {
520 std::lock_guard<std::mutex> Lock(Mutex);
522 Compiles.emplace_back(std::move(Compile));
525 ~AsyncModuleCompiles() {
527 std::lock_guard<std::mutex> Lock(Mutex);
530 for (std::thread &Compile : Compiles)
536 DependencyScanningService &Service;
537 DependencyActionController &Controller;
538 AsyncModuleCompiles &Compiles;
540 SingleModuleWithAsyncModuleCompiles(DependencyScanningService &Service,
541 DependencyActionController &Controller,
542 AsyncModuleCompiles &Compiles)
543 : Service(Service), Controller(Controller), Compiles(Compiles) {}
545 bool BeginSourceFileAction(CompilerInstance &CI)
override;
551 DependencyScanningService &Service;
552 DependencyActionController &Controller;
553 AsyncModuleCompiles &Compiles;
555 SingleTUWithAsyncModuleCompiles(DependencyScanningService &Service,
556 DependencyActionController &Controller,
557 AsyncModuleCompiles &Compiles)
558 : Service(Service), Controller(Controller), Compiles(Compiles) {}
560 bool BeginSourceFileAction(CompilerInstance &CI)
override;
566 CompilerInstance &CI;
567 DependencyScanningService &Service;
568 DependencyActionController &Controller;
569 AsyncModuleCompiles &Compiles;
571 AsyncModuleCompile(CompilerInstance &CI, DependencyScanningService &Service,
572 DependencyActionController &Controller,
573 AsyncModuleCompiles &Compiles)
574 : CI(CI), Service(Service), Controller(Controller), Compiles(Compiles) {}
576 void moduleLoadSkipped(
Module *M)
override {
579 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
580 ModuleCache &ModCache = CI.getModuleCache();
585 if (Timestamp > CI.getHeaderSearchOpts().BuildSessionTimestamp)
588 if (!CI.getASTReader())
589 CI.createASTReader();
590 SmallVector<ASTReader::ImportedModule, 0> Imported;
595 switch (CI.getASTReader()->ReadASTCore(
597 nullptr, Imported, {}, {}, {},
616 auto Lock = ModCache.
getLock(ModuleFileName);
618 llvm::Error LockErr = Lock->tryLock().moveInto(Owned);
620 if (!LockErr && !Owned)
623 IntrusiveRefCntPtr<llvm::vfs::FileSystem>
VFS =
624 llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
625 Service, Service.getOpts().MakeVFS());
627 CI.getDiagnostics(), std::move(
VFS));
628 auto DC = std::make_unique<DiagnosticConsumer>();
630 Service.getLogger());
631 CompilerInstance::ThreadSafeCloneConfig CloneConfig(std::move(
VFS), *DC,
633 auto ModCI1 = CI.cloneForModuleCompile(SourceLocation(), M, ModuleFileName,
635 auto ModCI2 = CI.cloneForModuleCompile(SourceLocation(), M, ModuleFileName,
638 auto ModController = Controller.clone();
643 Compiles.add([Lock = std::move(Lock), ModCI1 = std::move(ModCI1),
644 ModCI2 = std::move(ModCI2), DC = std::move(DC),
645 ModController = std::move(ModController), Service = &Service,
646 Compiles = &Compiles] {
647 llvm::CrashRecoveryContext CRC;
648 (void)CRC.RunSafely([&] {
650 SingleModuleWithAsyncModuleCompiles Action1(*Service, *ModController,
652 (void)ModCI1->ExecuteAction(Action1);
654 ModCI2->getPreprocessorOpts().SingleModuleParseMode = false;
655 GenerateModuleFromModuleMapAction Action2;
656 (void)ModCI2->ExecuteAction(Action2);
662bool SingleModuleWithAsyncModuleCompiles::BeginSourceFileAction(
666 std::make_unique<AsyncModuleCompile>(CI, Service, Controller, Compiles));
670bool SingleTUWithAsyncModuleCompiles::BeginSourceFileAction(
671 CompilerInstance &CI) {
674 std::make_unique<AsyncModuleCompile>(CI, Service, Controller, Compiles));
682 AsyncModuleCompiles &Compiles) {
683 SingleTUWithAsyncModuleCompiles Action(Service, Controller, Compiles);
688namespace dependencies {
690std::unique_ptr<DiagnosticOptions>
692 std::vector<const char *> CCommandLine(CommandLine.size(),
nullptr);
693 llvm::transform(CommandLine, CCommandLine.begin(),
694 [](
const std::string &Str) { return Str.c_str(); });
700class CompilerInstanceWithContext {
704 std::vector<std::string> CommandLine;
707 std::unique_ptr<CompilerInvocation> OriginalInvocation;
710 std::unique_ptr<DependencyOutputOptions> OutputOpts;
720 std::unique_ptr<CompilerInstance> CIPtr;
723 int32_t SrcLocOffset = 0;
727 :
Worker(Worker), CWD(CWD), CommandLine(CMD.begin(), CMD.end()) {}
733 auto LogLine = Worker.Service.getLogger().log();
738 ScanFS = Worker.makeEffectiveVFS(CWD, std::move(OverlayFS));
740 if (!OriginalInvocation) {
741 DiagEngine.
Report(diag::err_fe_expected_compiler_job)
742 << llvm::join(CommandLine,
" ");
746 return initializeScanInstance(Controller, DiagEngine.
getClient());
751 assert(OriginalInvocation && ScanFS &&
752 "OriginalInvocation and ScanFS must be set before this call");
754 if (
any(Worker.Service.getOpts().OptimizeArgs &
760 Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
761 CIPtr = std::make_unique<CompilerInstance>(
764 Worker.PCHContainerOps, std::move(ModCache));
771 auto MaybePrebuiltModulesASTMap =
773 if (!MaybePrebuiltModulesASTMap)
776 PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
787 bool prescanModulesAsync(AsyncModuleCompiles &Compiles,
790 Worker.Service.getModuleCacheEntries(), Worker.Service.getLogger());
792 std::make_shared<CompilerInvocation>(CIPtr->getInvocation()),
793 Worker.PCHContainerOps, std::move(ModCache));
797 Worker.Service, Worker.DepFS);
813 static std::optional<CompilerInstanceWithContext>
819 CompilerInstanceWithContext CIWC(Worker, CWD, CC1CommandLine);
820 if (!CIWC.initialize(Controller, DiagEngine, std::move(OverlayFS)))
822 return std::move(CIWC);
827 Worker.Service.getLogger().log() <<
"start scan_by_name: " << ModuleName;
828 llvm::scope_exit ExitLogging([&] {
829 Worker.Service.getLogger().log() <<
"finish scan_by_name: " << ModuleName;
832 llvm::report_fatal_error(
"exceeded maximum by-name scans for worker");
834 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
845 llvm::scope_exit CleanUp([&]() {
854 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
859 *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
862 if (!Controller.
initialize(CI, ModuleInvocation))
868 std::unique_ptr<FrontendAction> Action =
869 std::make_unique<PreprocessOnlyAction>();
871 bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
872 assert(ActionBeginSucceeded &&
"Action BeginSourceFile must succeed");
873 (void)ActionBeginSucceeded;
886 assert(!PPFailed &&
"Preprocess must be able to enter the main file.");
888 CB = MDC->getPPCallbacks();
893 MDC->attachToPreprocessor(PP);
894 CB = MDC->getPPCallbacks();
901 FileType, PrevFID, IDLocation);
909 Path.emplace_back(IDLocation,
ModuleID);
912 assert(CB &&
"Must have PPCallbacks after module loading");
922 MDC->applyDiscoveredDependencies(ModuleInvocation);
926 return Controller.
finalize(CI, CowModuleInvocation);
937 std::shared_ptr<ModuleDepCollector>
940 assert(CIPtr &&
"CIPtr must be initialized before calling this method");
943 std::optional<AsyncModuleCompiles> AsyncCompiles;
944 if (Worker.Service.getOpts().AsyncScanModules) {
945 AsyncCompiles.emplace();
946 if (!prescanModulesAsync(*AsyncCompiles, Controller))
951 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts),
952 Worker.Service, *OriginalInvocation, Controller, PrebuiltModuleASTMap,
958 if (!Controller.
initialize(CI, *OriginalInvocation))
966 if (!
applyAndReport(*MDC, *OriginalInvocation, Consumer, Controller,
976 StringRef Executable) {
980 return Controller.
finalize(*CIPtr, CowModuleInvocation);
995 PCHContainerOps = std::make_shared<PCHContainerOperations>();
997 PCHContainerOps->registerReader(
998 std::make_unique<ObjectFilePCHContainerReader>());
1000 PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>());
1002 auto BaseFS = Service.getOpts().MakeVFS();
1004 if (Service.getOpts().TraceVFS) {
1005 TracingFS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(
1010 DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
1011 Service, std::move(BaseFS));
1018 StringRef WorkingDirectory,
1023 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(std::move(FS));
1024 NewFS->pushOverlay(std::move(OverlayFS));
1025 FS = std::move(NewFS);
1027 FS->setCurrentWorkingDirectory(WorkingDirectory);
1038 bool Scanned =
false;
1039 std::shared_ptr<ModuleDepCollector> MDC;
1040 std::optional<CompilerInstanceWithContext> CIWC;
1042 const bool Success = llvm::all_of(CommandLines, [&](
const auto &Cmd) {
1043 if (StringRef(Cmd[1]) !=
"-cc1") {
1046 {Cmd.front(), {Cmd.begin() + 1, Cmd.end()}});
1050 Service.getLogger().log().logArray(
"starting scanning command:",
" ", Cmd);
1051 llvm::scope_exit ExitLogging([&] {
1052 Service.getLogger().log().logArray(
"finished scanning command:",
" ",
1069 *
this, WorkingDirectory, Cmd, *DiagEngine, OverlayFS, Controller);
1072 CIWC.emplace(std::move(*
Result));
1073 MDC = CIWC->scanTranslationUnit(DepConsumer, Controller);
1074 return MDC !=
nullptr;
1088 assert(CIWC &&
"Must have an initialized CIWC");
1089 return CIWC->applyAndReport(*MDC, *Invocation, DepConsumer, Controller,
1100 llvm::function_ref<std::optional<std::string>()> getNextName,
1107 std::optional<CompilerInstanceWithContext> CIWC =
1109 *
this, CWD, CC1CommandLine, *DiagEngine, std::move(OverlayFS),
1114 bool AllScansSucceeded =
true;
1115 while (std::optional<std::string> NextName = getNextName()) {
1117 CIWC->computeDependencies(*NextName, DepConsumer, Controller);
1119 AllScansSucceeded = AllScansSucceeded &&
Success;
1121 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.