23 DependencyConsumerForwarder(std::unique_ptr<DependencyOutputOptions> Opts,
24 StringRef WorkingDirectory, DependencyConsumer &C)
25 : DependencyFileGenerator(*Opts), WorkingDirectory(WorkingDirectory),
26 Opts(std::move(Opts)), C(C) {}
28 void finishedMainFile(DiagnosticsEngine &Diags)
override {
29 C.handleDependencyOutputOpts(*Opts);
30 llvm::SmallString<256> CanonPath;
31 for (
const auto &
File : getDependencies()) {
33 llvm::sys::path::remove_dots(CanonPath,
true);
34 llvm::sys::fs::make_absolute(WorkingDirectory, CanonPath);
35 C.handleFileDependency(CanonPath);
40 StringRef WorkingDirectory;
41 std::unique_ptr<DependencyOutputOptions> Opts;
42 DependencyConsumer &C;
49 if (LangOpts.Modules) {
52 Diags->
Report(diag::warn_pch_vfsoverlay_mismatch);
54 if (VFSOverlays.empty()) {
55 Diags->
Report(diag::note_pch_vfsoverlay_empty) <<
Type;
57 std::string Files = llvm::join(VFSOverlays,
"\n");
58 Diags->
Report(diag::note_pch_vfsoverlay_files) <<
Type << Files;
76 PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
77 llvm::SmallVector<std::string> &NewModuleFiles,
79 const HeaderSearchOptions &HSOpts,
80 const LangOptions &LangOpts, DiagnosticsEngine &Diags,
81 const ArrayRef<StringRef> StableDirs)
82 : PrebuiltModuleFiles(PrebuiltModuleFiles),
83 NewModuleFiles(NewModuleFiles),
84 PrebuiltModulesASTMap(PrebuiltModulesASTMap), ExistingHSOpts(HSOpts),
85 ExistingLangOpts(LangOpts), Diags(Diags), StableDirs(StableDirs) {}
87 bool needsImportVisitation()
const override {
return true; }
88 bool needsInputFileVisitation()
override {
return true; }
89 bool needsSystemInputFileVisitation()
override {
return true; }
93 void visitImport(StringRef ModuleName, StringRef Filename)
override {
94 if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second)
95 NewModuleFiles.push_back(Filename.str());
97 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(Filename);
98 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
99 if (PrebuiltMapEntry.second)
102 if (
auto It = PrebuiltModulesASTMap.find(CurrentFile);
103 It != PrebuiltModulesASTMap.end() && CurrentFile != Filename)
110 bool visitInputFileAsRequested(StringRef FilenameAsRequested,
111 StringRef Filename,
bool isSystem,
113 bool isExplicitModule)
override {
114 if (StableDirs.empty())
116 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
117 if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end()) ||
118 (!PrebuiltEntryIt->second.isInStableDir()))
121 PrebuiltEntryIt->second.setInStableDir(
123 return PrebuiltEntryIt->second.isInStableDir();
127 void visitModuleFile(StringRef Filename,
131 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
132 if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end()) &&
133 !PrebuiltEntryIt->second.isInStableDir())
134 PrebuiltEntryIt->second.updateDependentsNotInStableDirs(
135 PrebuiltModulesASTMap);
136 CurrentFile = Filename;
141 bool ReadHeaderSearchOptions(
const HeaderSearchOptions &HSOpts,
142 StringRef ModuleFilename,
143 StringRef SpecificModuleCachePath,
144 bool Complain)
override {
146 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
147 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
148 if (PrebuiltMapEntry.second)
158 bool ReadHeaderSearchPaths(
const HeaderSearchOptions &HSOpts,
159 bool Complain)
override {
161 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
162 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
163 if (PrebuiltMapEntry.second)
169 return checkHeaderSearchPaths(
170 HSOpts, ExistingHSOpts, Complain ? &Diags :
nullptr, ExistingLangOpts);
174 PrebuiltModuleFilesT &PrebuiltModuleFiles;
175 llvm::SmallVector<std::string> &NewModuleFiles;
177 const HeaderSearchOptions &ExistingHSOpts;
178 const LangOptions &ExistingLangOpts;
179 DiagnosticsEngine &Diags;
180 std::string CurrentFile;
181 const ArrayRef<StringRef> StableDirs;
186static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
188 PrebuiltModuleFilesT &ModuleFiles,
195 PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModulesASTMap,
199 Listener.visitModuleFile(PrebuiltModuleFilename,
208 while (!Worklist.empty()) {
221static std::string makeObjFileName(StringRef
FileName) {
223 llvm::sys::path::replace_extension(ObjFileName,
"o");
224 return std::string(ObjFileName);
229deduceDepTarget(
const std::string &OutputFile,
231 if (OutputFile !=
"-")
234 if (InputFiles.empty() || !InputFiles.front().isFile())
235 return "clang-scan-deps\\ dependency";
237 return makeObjFileName(InputFiles.front().getFile());
250static std::optional<StringRef> getSimpleMacroName(StringRef
Macro) {
251 StringRef Name =
Macro.split(
"=").first.ltrim(
" \t");
254 auto FinishName = [&]() -> std::optional<StringRef> {
255 StringRef SimpleName = Name.slice(0, I);
256 if (SimpleName.empty())
261 for (; I != Name.size(); ++I) {
270 if (llvm::isAlnum(Name[I]))
279 using MacroOpt = std::pair<StringRef, std::size_t>;
280 std::vector<MacroOpt> SimpleNames;
281 SimpleNames.reserve(PPOpts.
Macros.size());
282 std::size_t Index = 0;
283 for (
const auto &M : PPOpts.
Macros) {
284 auto SName = getSimpleMacroName(M.first);
288 SimpleNames.emplace_back(*SName, Index);
292 llvm::stable_sort(SimpleNames, llvm::less_first());
294 auto NewEnd = std::unique(
295 SimpleNames.rbegin(), SimpleNames.rend(),
296 [](
const MacroOpt &A,
const MacroOpt &B) { return A.first == B.first; });
297 SimpleNames.erase(SimpleNames.begin(), NewEnd.base());
300 decltype(PPOpts.
Macros) NewMacros;
301 NewMacros.reserve(SimpleNames.size());
302 for (std::size_t I = 0, E = SimpleNames.size(); I != E; ++I) {
303 std::size_t OriginalIndex = SimpleNames[I].second;
305 NewMacros.push_back(std::move(PPOpts.
Macros[OriginalIndex]));
307 std::swap(PPOpts.
Macros, NewMacros);
311 DependencyScanningWorkerFilesystem *DepFS;
314 ScanningDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(
nullptr) {
316 auto *
DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
318 assert(!DepFS &&
"Found multiple scanning VFSs");
322 assert(DepFS &&
"Did not find scanning VFS");
325 std::unique_ptr<DependencyDirectivesGetter>
326 cloneFor(FileManager &FileMgr)
override {
327 return std::make_unique<ScanningDependencyDirectivesGetter>(FileMgr);
330 std::optional<ArrayRef<dependency_directives_scan::Directive>>
331 operator()(FileEntryRef
File)
override {
332 return DepFS->getDirectiveTokens(
File.getName());
341 DiagOpts.ShowCarets =
false;
352 return llvm::StringSwitch<bool>(Warning)
353 .Cases(
"pch-vfs-diff",
"error=pch-vfs-diff", false)
354 .StartsWith(
"no-error=", false)
360 std::shared_ptr<CompilerInvocation> Invocation,
362 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
368 canonicalizeDefines(Invocation->getPreprocessorOpts());
378 setLastCC1Arguments(std::move(OriginalInvocation));
386 ScanInstanceStorage.emplace(std::move(Invocation), std::move(PCHContainerOps),
395 assert(!DiagConsumerFinished &&
"attempt to reuse finished consumer");
405 Service.getBuildSessionTimestamp();
422 DepFS->resetBypassedPathPrefix();
428 DepFS->setBypassedPathPrefix(ModulesCachePath);
432 std::make_unique<ScanningDependencyDirectivesGetter>(*
FileMgr));
442 if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot))
452 if (visitPrebuiltModule(
455 PrebuiltModulesASTMap, ScanInstance.
getDiagnostics(), StableDirs))
465 auto Opts = std::make_unique<DependencyOutputOptions>();
469 if (Opts->Targets.empty())
472 Opts->IncludeSystemHeaders =
true;
474 switch (Service.getFormat()) {
477 std::make_shared<DependencyConsumerForwarder>(
478 std::move(Opts), WorkingDirectory, Consumer));
482 MDC = std::make_shared<ModuleDepCollector>(
483 Service, std::move(Opts), ScanInstance, Consumer, Controller,
484 OriginalInvocation, std::move(PrebuiltModulesASTMap), StableDirs);
504 std::unique_ptr<FrontendAction> Action;
507 Action = std::make_unique<PreprocessOnlyAction>();
509 Action = std::make_unique<GetDependenciesByModuleNameAction>(*ModuleName);
511 Action = std::make_unique<ReadPCHAndPreprocessAction>();
519 DiagConsumerFinished =
true;
522 setLastCC1Arguments(std::move(OriginalInvocation));
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 createSourceManager(FileManager &FileMgr)
Create the source manager and replace any existing one with it.
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.
FileManager & getFileManager() const
Return the current file manager to the caller.
ModuleCache & getModuleCache() const
void addDependencyCollector(std::shared_ptr< DependencyCollector > Listener)
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()
CompilerInvocation & getInvocation()
PreprocessorOptions & getPreprocessorOpts()
FileManager * createFileManager()
Create the file manager and replace any existing one with it.
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)
Helper class for holding the data necessary to invoke the compiler.
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
llvm::vfs::FileSystem & getVirtualFileSystem() const
unsigned ModulesShareFileManager
Whether to share the FileManager when building modules.
std::string OutputFile
The output file, if any.
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.
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.
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
The base class of the type hierarchy.
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.
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.