clang: lib/DependencyScanning/DependencyScannerImpl.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
15#include "llvm/ADT/ScopeExit.h"
16#include "llvm/TargetParser/Host.h"
17
18using namespace clang;
20
21namespace {
22
24public:
25 DependencyConsumerForwarder(std::unique_ptr Opts,
26 StringRef WorkingDirectory, DependencyConsumer &C)
27 : DependencyFileGenerator(*Opts), WorkingDirectory(WorkingDirectory),
28 Opts(std::move(Opts)), C(C) {}
29
30 void finishedMainFile(DiagnosticsEngine &Diags) override {
31 C.handleDependencyOutputOpts(*Opts);
32 llvm::SmallString<256> CanonPath;
33 for (const auto &File : getDependencies()) {
34 CanonPath = File;
35 llvm::sys::path::remove_dots(CanonPath, true);
36 llvm::sys::path::make_absolute(WorkingDirectory, CanonPath);
37 C.handleFileDependency(CanonPath);
38 }
39 }
40
41private:
42 StringRef WorkingDirectory;
43 std::unique_ptr Opts;
44 DependencyConsumer &C;
45};
46
51 if (LangOpts.Modules) {
53 if (Diags) {
54 Diags->Report(diag::warn_pch_vfsoverlay_mismatch);
56 if (VFSOverlays.empty()) {
57 Diags->Report(diag::note_pch_vfsoverlay_empty) << Type;
58 } else {
59 std::string Files = llvm::join(VFSOverlays, "\n");
60 Diags->Report(diag::note_pch_vfsoverlay_files) << Type << Files;
61 }
62 };
65 }
66 }
67 }
68 return false;
69}
70
72
73
74
75
77public:
78 PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
79 llvm::SmallVectorstd::string &NewModuleFiles,
81 const HeaderSearchOptions &HSOpts,
82 const LangOptions &LangOpts, DiagnosticsEngine &Diags,
83 const ArrayRef StableDirs)
84 : PrebuiltModuleFiles(PrebuiltModuleFiles),
85 NewModuleFiles(NewModuleFiles),
86 PrebuiltModulesASTMap(PrebuiltModulesASTMap), ExistingHSOpts(HSOpts),
87 ExistingLangOpts(LangOpts), Diags(Diags), StableDirs(StableDirs) {}
88
89 bool needsImportVisitation() const override { return true; }
90 bool needsInputFileVisitation() override { return true; }
91 bool needsSystemInputFileVisitation() override { return true; }
92
93
94
95 void visitImport(StringRef ModuleName, StringRef Filename) override {
96 if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second)
97 NewModuleFiles.push_back(Filename.str());
98
99 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(Filename);
100 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
101 if (PrebuiltMapEntry.second)
103
104 if (auto It = PrebuiltModulesASTMap.find(CurrentFile);
105 It != PrebuiltModulesASTMap.end() && CurrentFile != Filename)
107 }
108
109
110
111
112 bool visitInputFileAsRequested(StringRef FilenameAsRequested,
113 StringRef Filename, bool isSystem,
114 bool isOverridden,
115 bool isExplicitModule) override {
116 if (StableDirs.empty())
117 return false;
118 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
119 if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end()) ||
120 (!PrebuiltEntryIt->second.isInStableDir()))
121 return false;
122
123 PrebuiltEntryIt->second.setInStableDir(
125 return PrebuiltEntryIt->second.isInStableDir();
126 }
127
128
129 void visitModuleFile(StringRef Filename,
131
132
133 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
134 if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end()) &&
135 !PrebuiltEntryIt->second.isInStableDir())
136 PrebuiltEntryIt->second.updateDependentsNotInStableDirs(
137 PrebuiltModulesASTMap);
138 CurrentFile = Filename;
139 }
140
141
142
143 bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
144 StringRef ModuleFilename,
145 StringRef SpecificModuleCachePath,
146 bool Complain) override {
147
148 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
149 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
150 if (PrebuiltMapEntry.second)
152
155
156 return false;
157 }
158
159
160 bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
161 bool Complain) override {
162
163 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
164 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
165 if (PrebuiltMapEntry.second)
167
168 PrebuiltModule.setVFS(
169 llvm::StringSet<>(llvm::from_range, HSOpts.VFSOverlayFiles));
170
171 return checkHeaderSearchPaths(
172 HSOpts, ExistingHSOpts, Complain ? &Diags : nullptr, ExistingLangOpts);
173 }
174
175private:
176 PrebuiltModuleFilesT &PrebuiltModuleFiles;
177 llvm::SmallVectorstd::string &NewModuleFiles;
179 const HeaderSearchOptions &ExistingHSOpts;
180 const LangOptions &ExistingLangOpts;
181 DiagnosticsEngine &Diags;
182 std::string CurrentFile;
183 const ArrayRef StableDirs;
184};
185
186
187
188static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
190 PrebuiltModuleFilesT &ModuleFiles,
194
196
197 PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModulesASTMap,
199 Diags, StableDirs);
200
201 Listener.visitModuleFile(PrebuiltModuleFilename,
206 false, Listener,
208 return true;
209
210 while (!Worklist.empty()) {
215 false, Listener,
216 false))
217 return true;
218 }
219 return false;
220}
221
222
223static std::string makeObjFileName(StringRef FileName) {
225 llvm::sys::path::replace_extension(ObjFileName, "o");
226 return std::string(ObjFileName);
227}
228
229
230static std::string
231deduceDepTarget(const std::string &OutputFile,
233 if (OutputFile != "-")
234 return OutputFile;
235
236 if (InputFiles.empty() || !InputFiles.front().isFile())
237 return "clang-scan-deps\\ dependency";
238
239 return makeObjFileName(InputFiles.front().getFile());
240}
241
242
243
244
245
246
247
248
249
250
251
252static std::optional getSimpleMacroName(StringRef Macro) {
253 StringRef Name = Macro.split("=").first.ltrim(" \t");
254 std::size_t I = 0;
255
256 auto FinishName = [&]() -> std::optional {
257 StringRef SimpleName = Name.slice(0, I);
258 if (SimpleName.empty())
259 return std::nullopt;
260 return SimpleName;
261 };
262
263 for (; I != Name.size(); ++I) {
264 switch (Name[I]) {
265 case '(':
266 case ' ':
267 case '\t':
268 return FinishName();
269 case '_':
270 continue;
271 default:
272 if (llvm::isAlnum(Name[I]))
273 continue;
274 return std::nullopt;
275 }
276 }
277 return FinishName();
278}
279
281 using MacroOpt = std::pair<StringRef, std::size_t>;
282 std::vector SimpleNames;
283 SimpleNames.reserve(PPOpts.Macros.size());
284 std::size_t Index = 0;
285 for (const auto &M : PPOpts.Macros) {
286 auto SName = getSimpleMacroName(M.first);
287
288 if (!SName)
289 return;
290 SimpleNames.emplace_back(*SName, Index);
291 ++Index;
292 }
293
294 llvm::stable_sort(SimpleNames, llvm::less_first());
295
296 auto NewEnd = std::unique(
297 SimpleNames.rbegin(), SimpleNames.rend(),
298 [](const MacroOpt &A, const MacroOpt &B) { return A.first == B.first; });
299 SimpleNames.erase(SimpleNames.begin(), NewEnd.base());
300
301
302 decltype(PPOpts.Macros) NewMacros;
303 NewMacros.reserve(SimpleNames.size());
304 for (std::size_t I = 0, E = SimpleNames.size(); I != E; ++I) {
305 std::size_t OriginalIndex = SimpleNames[I].second;
306
307 NewMacros.push_back(std::move(PPOpts.Macros[OriginalIndex]));
308 }
309 std::swap(PPOpts.Macros, NewMacros);
310}
311
313 DependencyScanningWorkerFilesystem *DepFS;
314
315public:
316 ScanningDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(nullptr) {
318 auto *DFS = llvm::dyn_cast(&FS);
319 if (DFS) {
320 assert(!DepFS && "Found multiple scanning VFSs");
321 DepFS = DFS;
322 }
323 });
324 assert(DepFS && "Did not find scanning VFS");
325 }
326
327 std::unique_ptr
328 cloneFor(FileManager &FileMgr) override {
329 return std::make_unique(FileMgr);
330 }
331
332 std::optional<ArrayRef<dependency_directives_scan::Directive>>
333 operator()(FileEntryRef File) override {
334 return DepFS->getDirectiveTokens(File.getName());
335 }
336};
337
338
340
341 DiagOpts.ShowCarets = false;
342
344
345
346
347
348
349
350
351 llvm::erase_if(DiagOpts.Warnings, [](StringRef Warning) {
352 return llvm::StringSwitch(Warning)
353 .Cases({"pch-vfs-diff", "error=pch-vfs-diff"}, false)
354 .StartsWith("no-error=", false)
355 .Default(true);
356 });
357}
358}
359
360std::unique_ptr
362 std::vector<const char *> CLI;
363 for (const std::string &Arg : CommandLine)
364 CLI.push_back(Arg.c_str());
366 sanitizeDiagOpts(*DiagOpts);
367 return DiagOpts;
368}
369
373 std::vector<const char *> CCommandLine(CommandLine.size(), nullptr);
374 llvm::transform(CommandLine, CCommandLine.begin(),
375 [](const std::string &Str) { return Str.c_str(); });
379 false);
380}
381
382std::pair<std::unique_ptrdriver::Driver, std::unique_ptrdriver::Compilation>
386 llvm::BumpPtrAllocator &Alloc) {
388 Argv.reserve(ArgStrs.size());
389 for (const std::string &Arg : ArgStrs)
390 Argv.push_back(Arg.c_str());
391
392 std::unique_ptrdriver::Driver Driver = std::make_uniquedriver::Driver(
393 Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
394 "clang LLVM compiler", FS);
395 Driver->setTitle("clang_based_tool");
396
399
400 if (llvm::Error E =
402 Diags.Report(diag::err_drv_expand_response_file)
403 << llvm::toString(std::move(E));
404 return std::make_pair(nullptr, nullptr);
405 }
406
407 std::unique_ptrdriver::Compilation Compilation(
408 Driver->BuildCompilation(Argv));
409 if (!Compilation)
410 return std::make_pair(nullptr, nullptr);
411
412 if (Compilation->containsError())
413 return std::make_pair(nullptr, nullptr);
414
415 return std::make_pair(std::move(Driver), std::move(Compilation));
416}
417
418std::unique_ptr
421 llvm::opt::ArgStringList Argv;
422 for (const std::string &Str : ArrayRef(CommandLine).drop_front())
423 Argv.push_back(Str.c_str());
424
425 auto Invocation = std::make_unique();
427
428 return nullptr;
429 }
430 return Invocation;
431}
432
433std::pair<IntrusiveRefCntPtrllvm::vfs::FileSystem, std::vectorstd::string>
437 llvm::MemoryBufferRef TUBuffer) {
438
439 BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
440
442 auto OverlayFS =
443 llvm::makeIntrusiveRefCntllvm::vfs::OverlayFileSystem(BaseFS);
444 auto InMemoryFS = llvm::makeIntrusiveRefCntllvm::vfs::InMemoryFileSystem();
445 InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
446 auto InputPath = TUBuffer.getBufferIdentifier();
447 InMemoryFS->addFile(
448 InputPath, 0, llvm::MemoryBuffer::getMemBufferCopy(TUBuffer.getBuffer()));
450
451 OverlayFS->pushOverlay(InMemoryOverlay);
452 ModifiedFS = OverlayFS;
453 std::vectorstd::string ModifiedCommandLine(CommandLine);
454 ModifiedCommandLine.emplace_back(InputPath);
455
456 return std::make_pair(ModifiedFS, ModifiedCommandLine);
457}
458
459std::pair<IntrusiveRefCntPtrllvm::vfs::OverlayFileSystem,
460 std::vectorstd::string>
464 StringRef ModuleName) {
465
466 BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
467
468
469
470
471 auto OverlayFS =
472 llvm::makeIntrusiveRefCntllvm::vfs::OverlayFileSystem(BaseFS);
473 auto InMemoryFS = llvm::makeIntrusiveRefCntllvm::vfs::InMemoryFileSystem();
474 InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
476
477 llvm::sys::fs::createUniquePath(ModuleName + "-%%%%%%%%.input", FakeInputPath,
478 false);
479 InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
481 OverlayFS->pushOverlay(InMemoryOverlay);
482
483 std::vectorstd::string ModifiedCommandLine(CommandLine);
484 ModifiedCommandLine.emplace_back(FakeInputPath);
485
486 return std::make_pair(OverlayFS, ModifiedCommandLine);
487}
488
495
497
498
500 ScanInstance.createDiagnostics(DiagConsumer, false);
502 return false;
503
505 true;
506
510
516
517
522
523
525
526
528 DepFS->resetBypassedPathPrefix();
532 ModulesCachePath);
533 if (!ModulesCachePath.empty())
534 DepFS->setBypassedPathPrefix(ModulesCachePath);
535
537 std::make_unique(
539 }
540
542
543
544
545
546
547
554
555
557
558 return true;
559}
560
563
564
565
568 if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot))
570 return StableDirs;
571}
572
573std::optional
576
577
578
579
581
583 if (visitPrebuiltModule(
586 PrebuiltModulesASTMap, ScanInstance.getDiagnostics(), StableDirs))
587 return {};
588
589 return PrebuiltModulesASTMap;
590}
591
592std::unique_ptr
595
596
597
598
599 auto Opts = std::make_unique();
601
602
603 if (Opts->Targets.empty())
606 Opts->IncludeSystemHeaders = true;
607
608 return Opts;
609}
610
611std::shared_ptr
614 std::unique_ptr DepOutputOpts,
620 std::shared_ptr MDC;
624 std::make_shared(
625 std::move(DepOutputOpts), WorkingDirectory, Consumer));
626 break;
629 MDC = std::make_shared(
630 Service, std::move(DepOutputOpts), ScanInstance, Consumer, Controller,
631 Inv, std::move(PrebuiltModulesASTMap), StableDirs);
633 break;
634 }
635
636 return MDC;
637}
638
640 std::string Executable, std::unique_ptr Invocation,
642 std::shared_ptr PCHContainerOps,
644
645
646
648 canonicalizeDefines(Invocation->getPreprocessorOpts());
649
650
652
653 if (Scanned) {
654
655
656
657
658 if (MDC)
659 MDC->applyDiscoveredDependencies(OriginalInvocation);
660 Consumer.handleBuildCommand(
662 return true;
663 }
664
665 Scanned = true;
666
667
669 ScanInstanceStorage.emplace(std::move(Invocation), std::move(PCHContainerOps),
670 ModCache.get());
672
673 assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
675 DepFS))
676 return false;
677
679 auto MaybePrebuiltModulesASTMap =
681 if (!MaybePrebuiltModulesASTMap)
682 return false;
683
685
687 ScanInstance, std::move(DepOutputOpts), WorkingDirectory, Consumer,
688 Service, OriginalInvocation, Controller, *MaybePrebuiltModulesASTMap,
689 StableDirs);
690
691 std::unique_ptr Action;
692
694 Action = std::make_unique();
695 else
696 Action = std::make_unique();
697
699 return false;
700
702
703
704 DiagConsumerFinished = true;
705
707 if (MDC)
708 MDC->applyDiscoveredDependencies(OriginalInvocation);
709 Consumer.handleBuildCommand(
711 }
712
714}
715
717 if (DC) {
718 DiagConsumer = DC;
719 } else {
720 DiagPrinterWithOS =
721 std::make_unique(CommandLine);
722 DiagConsumer = &DiagPrinterWithOS->DiagPrinter;
723 }
724
726 Worker.DepFS, CommandLine, CWD, "ScanningByName");
727
728 DiagEngineWithCmdAndOpts = std::make_unique(
729 CommandLine, OverlayFS, *DiagConsumer);
730
732 CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine, OverlayFS, Alloc);
733
734 if (!Compilation)
735 return false;
736
737 assert(Compilation->getJobs().size() &&
738 "Must have a job list of non-zero size");
740 const auto &CommandArgs = Command.getArguments();
741 assert(!CommandArgs.empty() && "Cannot have a command with 0 args");
742 assert(StringRef(CommandArgs[0]) == "-cc1" && "Requires a cc1 job.");
743 OriginalInvocation = std::make_unique();
744
746 *DiagEngineWithCmdAndOpts->DiagEngine,
747 Command.getExecutable())) {
748 DiagEngineWithCmdAndOpts->DiagEngine->Report(
749 diag::err_fe_expected_compiler_job)
750 << llvm::join(CommandLine, " ");
751 return false;
752 }
753
755 canonicalizeDefines(OriginalInvocation->getPreprocessorOpts());
756
757
760 CIPtr = std::make_unique(
761 std::make_shared(*OriginalInvocation),
762 Worker.PCHContainerOps, ModCache.get());
763 auto &CI = *CIPtr;
764
766 CI, OverlayFS, DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
767 Worker.Service, Worker.DepFS))
768 return false;
769
771 auto MaybePrebuiltModulesASTMap =
773 if (!MaybePrebuiltModulesASTMap)
774 return false;
775
776 PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
778
779
780
781
782
783
785
786 return true;
787}
788
792 assert(CIPtr && "CIPtr must be initialized before calling this method");
793 auto &CI = *CIPtr;
794
795
796
797 auto CleanUp = llvm::make_scope_exit([&]() {
799
800
801
803 });
804
806 CI, std::make_unique(*OutputOpts), CWD, Consumer,
807 Worker.Service,
808
809
810
811 *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
812
813 if (!SrcLocOffset) {
814
815
816 std::unique_ptr Action =
817 std::make_unique();
819 bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
820 assert(ActionBeginSucceeded && "Action BeginSourceFile must succeed");
821 (void)ActionBeginSucceeded;
822 }
823
826 FileID MainFileID = SM.getMainFileID();
827 SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
830 if (!SrcLocOffset) {
831
832
834 assert(!PPFailed && "Preprocess must be able to enter the main file.");
835 (void)PPFailed;
836 CB = MDC->getPPCallbacks();
837 } else {
838
839
840
841 MDC->attachToPreprocessor(PP);
842 CB = MDC->getPPCallbacks();
843
848 FileType, PrevFID, IDLocation);
849 }
850
851 SrcLocOffset++;
854 Path.emplace_back(IDLocation, ModuleID);
856
857 assert(CB && "Must have PPCallbacks after module loading");
859
860
861
863
864 if (!ModResult)
865 return false;
866
868 MDC->applyDiscoveredDependencies(ModuleInvocation);
871
872 return true;
873}
874
876 DiagConsumer->finish();
877 return true;
878}
879
881 assert(DiagPrinterWithOS && "Must use the default DiagnosticConsumer.");
882 return Success ? llvm::Error::success()
883 : llvm::make_errorllvm::StringError(
884 DiagPrinterWithOS->DiagnosticsOS.str(),
885 llvm::inconvertibleErrorCode());
886}
Abstract interface for callback invocations by the ASTReader.
@ ARR_OutOfDate
The client can handle an AST file that cannot load because it is out-of-date relative to its input fi...
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.
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()
bool hasDiagnostics() const
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.
DiagnosticOptions & getDiagnosticOpts()
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.
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()
Functor that returns the dependency directives for a given file.
Builds a dependency file when attached to a Preprocessor (for includes) and ASTReader (for module imp...
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
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
llvm::vfs::FileSystem & getVirtualFileSystem() const
unsigned ModulesShareFileManager
Whether to share the FileManager when building modules.
std::string OutputFile
The output file, if any.
unsigned GenReducedBMI
Whether to generate reduced BMI for C++20 named modules.
std::string ModuleOutputPath
Output Path for module output file.
unsigned GenerateGlobalModuleIndex
Whether we can generate the global module index if needed.
unsigned DisableFree
Disable memory freeing on exit.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
unsigned UseGlobalModuleIndex
Whether we can use the global module index if available.
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 setBuildingModule(bool BuildingModuleFlag)
Flag indicating whether this instance is building a module.
@ Hidden
All of the names in this module are hidden.
This interface provides a way to observe the actions of the preprocessor as it does its thing.
virtual void EndOfMainFile()
Callback invoked when the end of the main file is reached.
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...
bool ModulesCheckRelocated
Perform extra checks when loading PCM files for mutable file systems.
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
bool AllowPCHWithDifferentModulesCachePath
When true, a PCH with modules cache path different to the current compilation will not be rejected.
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...
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
SourceManager & getSourceManager() const
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.
The base class of the type hierarchy.
bool initialize(DiagnosticConsumer *DC)
Definition DependencyScannerImpl.cpp:716
llvm::Error handleReturnStatus(bool Success)
Definition DependencyScannerImpl.cpp:880
bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer, DependencyActionController &Controller)
Definition DependencyScannerImpl.cpp:789
bool finalize()
Definition DependencyScannerImpl.cpp:875
Dependency scanner callbacks that are used during scanning to influence the behaviour of the scan - f...
virtual void handleBuildCommand(Command Cmd)
bool runInvocation(std::string Executable, std::unique_ptr< CompilerInvocation > Invocation, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagConsumer)
Definition DependencyScannerImpl.cpp:639
The dependency scanning service contains shared configuration and state that is used by the individua...
std::time_t getBuildSessionTimestamp() const
ScanningOptimizations getOptimizeArgs() const
ScanningMode getMode() const
ScanningOutputFormat getFormat() const
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.
Command - An executable path/name and argument vector to execute.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
SmallVector< StringRef > getInitialStableDirs(const CompilerInstance &ScanInstance)
Definition DependencyScannerImpl.cpp:562
std::pair< IntrusiveRefCntPtr< llvm::vfs::FileSystem >, std::vector< std::string > > initVFSForTUBufferScanning(IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS, ArrayRef< std::string > CommandLine, StringRef WorkingDirectory, llvm::MemoryBufferRef TUBuffer)
Definition DependencyScannerImpl.cpp:434
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.
bool initializeScanCompilerInstance(CompilerInstance &ScanInstance, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service, IntrusiveRefCntPtr< DependencyScanningWorkerFilesystem > DepFS)
Definition DependencyScannerImpl.cpp:489
llvm::StringMap< PrebuiltModuleASTAttrs > PrebuiltModulesAttrsMap
Attributes loaded from AST files of prebuilt modules collected prior to ModuleDepCollector creation.
std::unique_ptr< CompilerInvocation > createCompilerInvocation(ArrayRef< std::string > CommandLine, DiagnosticsEngine &Diags)
Definition DependencyScannerImpl.cpp:419
std::optional< PrebuiltModulesAttrsMap > computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, SmallVector< StringRef > &StableDirs)
Definition DependencyScannerImpl.cpp:574
std::pair< IntrusiveRefCntPtr< llvm::vfs::OverlayFileSystem >, std::vector< std::string > > initVFSForByNameScanning(IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS, ArrayRef< std::string > CommandLine, StringRef WorkingDirectory, StringRef ModuleName)
Definition DependencyScannerImpl.cpp:461
std::pair< std::unique_ptr< driver::Driver >, std::unique_ptr< driver::Compilation > > buildCompilation(ArrayRef< std::string > ArgStrs, DiagnosticsEngine &Diags, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, llvm::BumpPtrAllocator &Alloc)
Definition DependencyScannerImpl.cpp:383
std::unique_ptr< DependencyOutputOptions > takeAndUpdateDependencyOutputOptionsFrom(CompilerInstance &ScanInstance)
Definition DependencyScannerImpl.cpp:593
std::shared_ptr< ModuleDepCollector > initializeScanInstanceDependencyCollector(CompilerInstance &ScanInstance, std::unique_ptr< DependencyOutputOptions > DepOutputOpts, StringRef WorkingDirectory, DependencyConsumer &Consumer, DependencyScanningService &Service, CompilerInvocation &Inv, DependencyActionController &Controller, PrebuiltModulesAttrsMap PrebuiltModulesASTMap, llvm::SmallVector< StringRef > &StableDirs)
Create the dependency collector that will collect the produced dependencies.
Definition DependencyScannerImpl.cpp:612
std::unique_ptr< DiagnosticOptions > createDiagOptions(ArrayRef< std::string > CommandLine)
Definition DependencyScannerImpl.cpp:361
bool isPathInStableDir(const ArrayRef< StringRef > Directories, const StringRef Input)
Determine if Input can be resolved within a stable directory.
@ Make
This is the Makefile compatible dep format.
@ Full
This outputs the full clang module dependency graph suitable for use for explicitly building modules.
@ P1689
This outputs the dependency graph for standard c++ modules in P1689R5 format.
@ DependencyDirectivesScan
This mode is used to compute the dependencies by running the preprocessor with special kind of lexing...
IntrusiveRefCntPtr< ModuleCache > makeInProcessModuleCache(ModuleCacheEntries &Entries)
llvm::StringRef getDriverMode(StringRef ProgName, ArrayRef< const char * > Args)
Returns the driver mode option's value, i.e.
llvm::Error expandResponseFiles(SmallVectorImpl< const char * > &Args, bool ClangCLMode, llvm::BumpPtrAllocator &Alloc, llvm::vfs::FileSystem *FS=nullptr)
Expand response files from a clang driver or cc1 invocation.
bool IsClangCL(StringRef DriverMode)
Checks whether the value produced by getDriverMode is for CL mode.
ModuleKind
Specifies the kind of module that has been loaded.
@ MK_ExplicitModule
File is an explicitly-loaded module.
The JSON file list parser is used to communicate input to InstallAPI.
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
@ Success
Annotation was successful.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Result
The result type of a method or function.
void normalizeModuleCachePath(FileManager &FileMgr, StringRef Path, SmallVectorImpl< char > &NormalizedPath)
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
A command-line tool invocation that is part of building a TU.
IntrusiveRefCntPtr< DiagnosticsEngine > DiagEngine
DiagnosticsEngineWithDiagOpts(ArrayRef< std::string > CommandLine, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, DiagnosticConsumer &DC)
Definition DependencyScannerImpl.cpp:370
std::unique_ptr< DiagnosticOptions > DiagOpts
This is used to identify a specific module.