clang 22.0.0git
DependencyScannerImpl.cpp
Go to the documentation of this file.
1//===- DependencyScannerImpl.cpp - Implements module dependency scanning --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
13#include "clang/Driver/Driver.h"
15#include "llvm/ADT/ScopeExit.h"
16#include "llvm/TargetParser/Host.h"
17
18using namespace clang;
19using namespace dependencies;
20
21namespace {
22/// Forwards the gatherered dependencies to the consumer.
23class DependencyConsumerForwarder : public DependencyFileGenerator {
24public:
25 DependencyConsumerForwarder(std::unique_ptr<DependencyOutputOptions> 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, /*remove_dot_dot=*/true);
36 llvm::sys::path::make_absolute(WorkingDirectory, CanonPath);
37 C.handleFileDependency(CanonPath);
38 }
39 }
40
41private:
42 StringRef WorkingDirectory;
43 std::unique_ptr<DependencyOutputOptions> Opts;
44 DependencyConsumer &C;
45};
46
47static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
48 const HeaderSearchOptions &ExistingHSOpts,
49 DiagnosticsEngine *Diags,
50 const LangOptions &LangOpts) {
51 if (LangOpts.Modules) {
52 if (HSOpts.VFSOverlayFiles != ExistingHSOpts.VFSOverlayFiles) {
53 if (Diags) {
54 Diags->Report(diag::warn_pch_vfsoverlay_mismatch);
55 auto VFSNote = [&](int Type, ArrayRef<std::string> VFSOverlays) {
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 };
63 VFSNote(0, HSOpts.VFSOverlayFiles);
64 VFSNote(1, ExistingHSOpts.VFSOverlayFiles);
65 }
66 }
67 }
68 return false;
69}
70
71using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles);
72
73/// A listener that collects the imported modules and the input
74/// files. While visiting, collect vfsoverlays and file inputs that determine
75/// whether prebuilt modules fully resolve in stable directories.
76class PrebuiltModuleListener : public ASTReaderListener {
77public:
78 PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
79 llvm::SmallVector<std::string> &NewModuleFiles,
80 PrebuiltModulesAttrsMap &PrebuiltModulesASTMap,
81 const HeaderSearchOptions &HSOpts,
82 const LangOptions &LangOpts, DiagnosticsEngine &Diags,
83 const ArrayRef<StringRef> 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 /// Accumulate the modules are transitively depended on by the initial
94 /// prebuilt module.
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)
102 PrebuiltModule.setInStableDir(!StableDirs.empty());
103
104 if (auto It = PrebuiltModulesASTMap.find(CurrentFile);
105 It != PrebuiltModulesASTMap.end() && CurrentFile != Filename)
106 PrebuiltModule.addDependent(It->getKey());
107 }
108
109 /// For each input file discovered, check whether it's external path is in a
110 /// stable directory. Traversal is stopped if the current module is not
111 /// considered stable.
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(
124 isPathInStableDir(StableDirs, Filename));
125 return PrebuiltEntryIt->second.isInStableDir();
126 }
127
128 /// Update which module that is being actively traversed.
129 void visitModuleFile(StringRef Filename,
130 serialization::ModuleKind Kind) override {
131 // If the CurrentFile is not
132 // considered stable, update any of it's transitive dependents.
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 /// Check the header search options for a given module when considering
142 /// if the module comes from stable directories.
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)
151 PrebuiltModule.setInStableDir(!StableDirs.empty());
152
153 if (PrebuiltModule.isInStableDir())
154 PrebuiltModule.setInStableDir(areOptionsInStableDir(StableDirs, HSOpts));
155
156 return false;
157 }
158
159 /// Accumulate vfsoverlays used to build these prebuilt modules.
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)
166 PrebuiltModule.setInStableDir(!StableDirs.empty());
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::SmallVector<std::string> &NewModuleFiles;
178 PrebuiltModulesAttrsMap &PrebuiltModulesASTMap;
179 const HeaderSearchOptions &ExistingHSOpts;
180 const LangOptions &ExistingLangOpts;
181 DiagnosticsEngine &Diags;
182 std::string CurrentFile;
183 const ArrayRef<StringRef> StableDirs;
184};
185
186/// Visit the given prebuilt module and collect all of the modules it
187/// transitively imports and contributing input files.
188static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
190 PrebuiltModuleFilesT &ModuleFiles,
191 PrebuiltModulesAttrsMap &PrebuiltModulesASTMap,
192 DiagnosticsEngine &Diags,
193 const ArrayRef<StringRef> StableDirs) {
194 // List of module files to be processed.
196
197 PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModulesASTMap,
199 Diags, StableDirs);
200
201 Listener.visitModuleFile(PrebuiltModuleFilename,
204 PrebuiltModuleFilename, CI.getFileManager(), CI.getModuleCache(),
206 /*FindModuleFileExtensions=*/false, Listener,
207 /*ValidateDiagnosticOptions=*/false, ASTReader::ARR_OutOfDate))
208 return true;
209
210 while (!Worklist.empty()) {
211 Listener.visitModuleFile(Worklist.back(), serialization::MK_ExplicitModule);
213 Worklist.pop_back_val(), CI.getFileManager(), CI.getModuleCache(),
215 /*FindModuleFileExtensions=*/false, Listener,
216 /*ValidateDiagnosticOptions=*/false))
217 return true;
218 }
219 return false;
220}
221
222/// Transform arbitrary file name into an object-like file name.
223static std::string makeObjFileName(StringRef FileName) {
224 SmallString<128> ObjFileName(FileName);
225 llvm::sys::path::replace_extension(ObjFileName, "o");
226 return std::string(ObjFileName);
227}
228
229/// Deduce the dependency target based on the output file and input files.
230static std::string
231deduceDepTarget(const std::string &OutputFile,
232 const SmallVectorImpl<FrontendInputFile> &InputFiles) {
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// Clang implements -D and -U by splatting text into a predefines buffer. This
243// allows constructs such as `-DFඞ=3 "-D F\u{0D9E} 4 3 2”` to be accepted and
244// define the same macro, or adding C++ style comments before the macro name.
245//
246// This function checks that the first non-space characters in the macro
247// obviously form an identifier that can be uniqued on without lexing. Failing
248// to do this could lead to changing the final definition of a macro.
249//
250// We could set up a preprocessor and actually lex the name, but that's very
251// heavyweight for a situation that will almost never happen in practice.
252static std::optional<StringRef> getSimpleMacroName(StringRef Macro) {
253 StringRef Name = Macro.split("=").first.ltrim(" \t");
254 std::size_t I = 0;
255
256 auto FinishName = [&]() -> std::optional<StringRef> {
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 '(': // Start of macro parameter list
266 case ' ': // End of macro name
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
280static void canonicalizeDefines(PreprocessorOptions &PPOpts) {
281 using MacroOpt = std::pair<StringRef, std::size_t>;
282 std::vector<MacroOpt> 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 // Skip optimizing if we can't guarantee we can preserve relative order.
288 if (!SName)
289 return;
290 SimpleNames.emplace_back(*SName, Index);
291 ++Index;
292 }
293
294 llvm::stable_sort(SimpleNames, llvm::less_first());
295 // Keep the last instance of each macro name by going in reverse
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 // Apply permutation.
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 // We still emit undefines here as they may be undefining a predefined macro
307 NewMacros.push_back(std::move(PPOpts.Macros[OriginalIndex]));
308 }
309 std::swap(PPOpts.Macros, NewMacros);
310}
311
312class ScanningDependencyDirectivesGetter : public DependencyDirectivesGetter {
313 DependencyScanningWorkerFilesystem *DepFS;
314
315public:
316 ScanningDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(nullptr) {
317 FileMgr.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) {
318 auto *DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&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<DependencyDirectivesGetter>
328 cloneFor(FileManager &FileMgr) override {
329 return std::make_unique<ScanningDependencyDirectivesGetter>(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/// Sanitize diagnostic options for dependency scan.
339void sanitizeDiagOpts(DiagnosticOptions &DiagOpts) {
340 // Don't print 'X warnings and Y errors generated'.
341 DiagOpts.ShowCarets = false;
342 // Don't write out diagnostic file.
343 DiagOpts.DiagnosticSerializationFile.clear();
344 // Don't emit warnings except for scanning specific warnings.
345 // TODO: It would be useful to add a more principled way to ignore all
346 // warnings that come from source code. The issue is that we need to
347 // ignore warnings that could be surpressed by
348 // `#pragma clang diagnostic`, while still allowing some scanning
349 // warnings for things we're not ready to turn into errors yet.
350 // See `test/ClangScanDeps/diagnostic-pragmas.c` for an example.
351 llvm::erase_if(DiagOpts.Warnings, [](StringRef Warning) {
352 return llvm::StringSwitch<bool>(Warning)
353 .Cases({"pch-vfs-diff", "error=pch-vfs-diff"}, false)
354 .StartsWith("no-error=", false)
355 .Default(true);
356 });
357}
358} // namespace
359
360std::unique_ptr<DiagnosticOptions>
362 std::vector<const char *> CLI;
363 for (const std::string &Arg : CommandLine)
364 CLI.push_back(Arg.c_str());
365 auto DiagOpts = CreateAndPopulateDiagOpts(CLI);
366 sanitizeDiagOpts(*DiagOpts);
367 return DiagOpts;
368}
369
371 ArrayRef<std::string> CommandLine,
373 std::vector<const char *> CCommandLine(CommandLine.size(), nullptr);
374 llvm::transform(CommandLine, CCommandLine.begin(),
375 [](const std::string &Str) { return Str.c_str(); });
376 DiagOpts = CreateAndPopulateDiagOpts(CCommandLine);
377 sanitizeDiagOpts(*DiagOpts);
379 /*ShouldOwnClient=*/false);
380}
381
382std::pair<std::unique_ptr<driver::Driver>, std::unique_ptr<driver::Compilation>>
384 DiagnosticsEngine &Diags,
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_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
393 Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
394 "clang LLVM compiler", FS);
395 Driver->setTitle("clang_based_tool");
396
397 bool CLMode = driver::IsClangCL(
398 driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1)));
399
400 if (llvm::Error E =
401 driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) {
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_ptr<driver::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<CompilerInvocation>
420 DiagnosticsEngine &Diags) {
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<CompilerInvocation>();
426 if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) {
427 // FIXME: Should we just go on like cc1_main does?
428 return nullptr;
429 }
430 return Invocation;
431}
432
433std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::vector<std::string>>
436 ArrayRef<std::string> CommandLine, StringRef WorkingDirectory,
437 llvm::MemoryBufferRef TUBuffer) {
438 // Reset what might have been modified in the previous worker invocation.
439 BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
440
442 auto OverlayFS =
443 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
444 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
445 InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
446 auto InputPath = TUBuffer.getBufferIdentifier();
447 InMemoryFS->addFile(
448 InputPath, 0, llvm::MemoryBuffer::getMemBufferCopy(TUBuffer.getBuffer()));
449 IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay = InMemoryFS;
450
451 OverlayFS->pushOverlay(InMemoryOverlay);
452 ModifiedFS = OverlayFS;
453 std::vector<std::string> ModifiedCommandLine(CommandLine);
454 ModifiedCommandLine.emplace_back(InputPath);
455
456 return std::make_pair(ModifiedFS, ModifiedCommandLine);
457}
458
459std::pair<IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>,
460 std::vector<std::string>>
463 ArrayRef<std::string> CommandLine, StringRef WorkingDirectory,
464 StringRef ModuleName) {
465 // Reset what might have been modified in the previous worker invocation.
466 BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
467
468 // If we're scanning based on a module name alone, we don't expect the client
469 // to provide us with an input file. However, the driver really wants to have
470 // one. Let's just make it up to make the driver happy.
471 auto OverlayFS =
472 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
473 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
474 InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
475 SmallString<128> FakeInputPath;
476 // TODO: We should retry the creation if the path already exists.
477 llvm::sys::fs::createUniquePath(ModuleName + "-%%%%%%%%.input", FakeInputPath,
478 /*MakeAbsolute=*/false);
479 InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
480 IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay = InMemoryFS;
481 OverlayFS->pushOverlay(InMemoryOverlay);
482
483 std::vector<std::string> ModifiedCommandLine(CommandLine);
484 ModifiedCommandLine.emplace_back(FakeInputPath);
485
486 return std::make_pair(OverlayFS, ModifiedCommandLine);
487}
488
490 CompilerInstance &ScanInstance,
492 DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service,
494 ScanInstance.setBuildingModule(false);
495
496 ScanInstance.createVirtualFileSystem(FS, DiagConsumer);
497
498 // Create the compiler's actual diagnostics engine.
499 sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
500 ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
501 if (!ScanInstance.hasDiagnostics())
502 return false;
503
505 true;
506
509 Service.getBuildSessionTimestamp();
510
511 ScanInstance.getFrontendOpts().DisableFree = false;
512 ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false;
513 ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false;
514 ScanInstance.getFrontendOpts().GenReducedBMI = false;
515 ScanInstance.getFrontendOpts().ModuleOutputPath.clear();
516 // This will prevent us compiling individual modules asynchronously since
517 // FileManager is not thread-safe, but it does improve performance for now.
518 ScanInstance.getFrontendOpts().ModulesShareFileManager = true;
519 ScanInstance.getHeaderSearchOpts().ModuleFormat = "raw";
522
523 // Create a new FileManager to match the invocation's FileSystemOptions.
524 ScanInstance.createFileManager();
525
526 // Use DepFS for getting the dependency directives if requested to do so.
528 DepFS->resetBypassedPathPrefix();
529 SmallString<256> ModulesCachePath;
532 ModulesCachePath);
533 if (!ModulesCachePath.empty())
534 DepFS->setBypassedPathPrefix(ModulesCachePath);
535
537 std::make_unique<ScanningDependencyDirectivesGetter>(
538 ScanInstance.getFileManager()));
539 }
540
541 ScanInstance.createSourceManager();
542
543 // Consider different header search and diagnostic options to create
544 // different modules. This avoids the unsound aliasing of module PCMs.
545 //
546 // TODO: Implement diagnostic bucketing to reduce the impact of strict
547 // context hashing.
548 ScanInstance.getHeaderSearchOpts().ModulesStrictContextHash = true;
554
555 // Avoid some checks and module map parsing when loading PCM files.
556 ScanInstance.getPreprocessorOpts().ModulesCheckRelocated = false;
557
558 return true;
559}
560
563 // Create a collection of stable directories derived from the ScanInstance
564 // for determining whether module dependencies would fully resolve from
565 // those directories.
567 const StringRef Sysroot = ScanInstance.getHeaderSearchOpts().Sysroot;
568 if (!Sysroot.empty() && (llvm::sys::path::root_directory(Sysroot) != Sysroot))
569 StableDirs = {Sysroot, ScanInstance.getHeaderSearchOpts().ResourceDir};
570 return StableDirs;
571}
572
573std::optional<PrebuiltModulesAttrsMap>
575 CompilerInstance &ScanInstance, llvm::SmallVector<StringRef> &StableDirs) {
576 // Store a mapping of prebuilt module files and their properties like header
577 // search options. This will prevent the implicit build to create duplicate
578 // modules and will force reuse of the existing prebuilt module files
579 // instead.
580 PrebuiltModulesAttrsMap PrebuiltModulesASTMap;
581
582 if (!ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
583 if (visitPrebuiltModule(
584 ScanInstance.getPreprocessorOpts().ImplicitPCHInclude, ScanInstance,
586 PrebuiltModulesASTMap, ScanInstance.getDiagnostics(), StableDirs))
587 return {};
588
589 return PrebuiltModulesASTMap;
590}
591
592std::unique_ptr<DependencyOutputOptions>
594 CompilerInstance &ScanInstance) {
595 // This function moves the existing dependency output options from the
596 // invocation to the collector. The options in the invocation are reset,
597 // which ensures that the compiler won't create new dependency collectors,
598 // and thus won't write out the extra '.d' files to disk.
599 auto Opts = std::make_unique<DependencyOutputOptions>();
600 std::swap(*Opts, ScanInstance.getInvocation().getDependencyOutputOpts());
601 // We need at least one -MT equivalent for the generator of make dependency
602 // files to work.
603 if (Opts->Targets.empty())
604 Opts->Targets = {deduceDepTarget(ScanInstance.getFrontendOpts().OutputFile,
605 ScanInstance.getFrontendOpts().Inputs)};
606 Opts->IncludeSystemHeaders = true;
607
608 return Opts;
609}
610
611std::shared_ptr<ModuleDepCollector>
613 CompilerInstance &ScanInstance,
614 std::unique_ptr<DependencyOutputOptions> DepOutputOpts,
615 StringRef WorkingDirectory, DependencyConsumer &Consumer,
617 DependencyActionController &Controller,
618 PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
619 llvm::SmallVector<StringRef> &StableDirs) {
620 std::shared_ptr<ModuleDepCollector> MDC;
621 switch (Service.getFormat()) {
623 ScanInstance.addDependencyCollector(
624 std::make_shared<DependencyConsumerForwarder>(
625 std::move(DepOutputOpts), WorkingDirectory, Consumer));
626 break;
629 MDC = std::make_shared<ModuleDepCollector>(
630 Service, std::move(DepOutputOpts), ScanInstance, Consumer, Controller,
631 Inv, std::move(PrebuiltModulesASTMap), StableDirs);
632 ScanInstance.addDependencyCollector(MDC);
633 break;
634 }
635
636 return MDC;
637}
638
640 std::string Executable, std::unique_ptr<CompilerInvocation> Invocation,
642 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
643 DiagnosticConsumer *DiagConsumer) {
644 // Making sure that we canonicalize the defines before we create the deep
645 // copy to avoid unnecessary variants in the scanner and in the resulting
646 // explicit command lines.
647 if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros))
648 canonicalizeDefines(Invocation->getPreprocessorOpts());
649
650 // Make a deep copy of the original Clang invocation.
651 CompilerInvocation OriginalInvocation(*Invocation);
652
653 if (Scanned) {
654 // Scanning runs once for the first -cc1 invocation in a chain of driver
655 // jobs. For any dependent jobs, reuse the scanning result and just
656 // update the new invocation.
657 // FIXME: to support multi-arch builds, each arch requires a separate scan
658 if (MDC)
659 MDC->applyDiscoveredDependencies(OriginalInvocation);
660 Consumer.handleBuildCommand(
661 {Executable, OriginalInvocation.getCC1CommandLine()});
662 return true;
663 }
664
665 Scanned = true;
666
667 // Create a compiler instance to handle the actual work.
668 auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries());
669 ScanInstanceStorage.emplace(std::move(Invocation), std::move(PCHContainerOps),
670 ModCache.get());
671 CompilerInstance &ScanInstance = *ScanInstanceStorage;
672
673 assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
674 if (!initializeScanCompilerInstance(ScanInstance, FS, DiagConsumer, Service,
675 DepFS))
676 return false;
677
678 llvm::SmallVector<StringRef> StableDirs = getInitialStableDirs(ScanInstance);
679 auto MaybePrebuiltModulesASTMap =
680 computePrebuiltModulesASTMap(ScanInstance, StableDirs);
681 if (!MaybePrebuiltModulesASTMap)
682 return false;
683
684 auto DepOutputOpts = takeAndUpdateDependencyOutputOptionsFrom(ScanInstance);
685
687 ScanInstance, std::move(DepOutputOpts), WorkingDirectory, Consumer,
688 Service, OriginalInvocation, Controller, *MaybePrebuiltModulesASTMap,
689 StableDirs);
690
691 std::unique_ptr<FrontendAction> Action;
692
693 if (Service.getFormat() == ScanningOutputFormat::P1689)
694 Action = std::make_unique<PreprocessOnlyAction>();
695 else
696 Action = std::make_unique<ReadPCHAndPreprocessAction>();
697
698 if (ScanInstance.getDiagnostics().hasErrorOccurred())
699 return false;
700
701 const bool Result = ScanInstance.ExecuteAction(*Action);
702
703 // ExecuteAction is responsible for calling finish.
704 DiagConsumerFinished = true;
705
706 if (Result) {
707 if (MDC)
708 MDC->applyDiscoveredDependencies(OriginalInvocation);
709 Consumer.handleBuildCommand(
710 {Executable, OriginalInvocation.getCC1CommandLine()});
711 }
712
713 return Result;
714}
715
717 std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithDiagOpts,
719 assert(DiagEngineWithDiagOpts && "Valid diagnostics engine required!");
720 DiagEngineWithCmdAndOpts = std::move(DiagEngineWithDiagOpts);
721 DiagConsumer = DiagEngineWithCmdAndOpts->DiagEngine->getClient();
722
723#ifndef NDEBUG
724 assert(OverlayFS && "OverlayFS required!");
725 bool SawDepFS = false;
726 OverlayFS->visit([&](llvm::vfs::FileSystem &VFS) {
727 SawDepFS |= &VFS == Worker.DepFS.get();
728 });
729 assert(SawDepFS && "OverlayFS not based on DepFS");
730#endif
731
732 OriginalInvocation = createCompilerInvocation(
733 CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine);
734 if (!OriginalInvocation) {
735 DiagEngineWithCmdAndOpts->DiagEngine->Report(
736 diag::err_fe_expected_compiler_job)
737 << llvm::join(CommandLine, " ");
738 return false;
739 }
740
741 if (any(Worker.Service.getOptimizeArgs() & ScanningOptimizations::Macros))
742 canonicalizeDefines(OriginalInvocation->getPreprocessorOpts());
743
744 // Create the CompilerInstance.
746 makeInProcessModuleCache(Worker.Service.getModuleCacheEntries());
747 CIPtr = std::make_unique<CompilerInstance>(
748 std::make_shared<CompilerInvocation>(*OriginalInvocation),
749 Worker.PCHContainerOps, ModCache.get());
750 auto &CI = *CIPtr;
751
753 CI, OverlayFS, DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
754 Worker.Service, Worker.DepFS))
755 return false;
756
757 StableDirs = getInitialStableDirs(CI);
758 auto MaybePrebuiltModulesASTMap =
759 computePrebuiltModulesASTMap(CI, StableDirs);
760 if (!MaybePrebuiltModulesASTMap)
761 return false;
762
763 PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
765
766 // We do not create the target in initializeScanCompilerInstance because
767 // setting it here is unique for by-name lookups. We create the target only
768 // once here, and the information is reused for all computeDependencies calls.
769 // We do not need to call createTarget explicitly if we go through
770 // CompilerInstance::ExecuteAction to perform scanning.
771 CI.createTarget();
772
773 return true;
774}
775
777 StringRef ModuleName, DependencyConsumer &Consumer,
778 DependencyActionController &Controller) {
779 assert(CIPtr && "CIPtr must be initialized before calling this method");
780 auto &CI = *CIPtr;
781
782 // We create this cleanup object because computeDependencies may exit
783 // early with errors.
784 auto CleanUp = llvm::make_scope_exit([&]() {
786 // The preprocessor may not be created at the entry of this method,
787 // but it must have been created when this method returns, whether
788 // there are errors during scanning or not.
790 });
791
793 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts), CWD, Consumer,
794 Worker.Service,
795 /* The MDC's constructor makes a copy of the OriginalInvocation, so
796 we can pass it in without worrying that it might be changed across
797 invocations of computeDependencies. */
798 *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
799
800 if (!SrcLocOffset) {
801 // When SrcLocOffset is zero, we are at the beginning of the fake source
802 // file. In this case, we call BeginSourceFile to initialize.
803 std::unique_ptr<FrontendAction> Action =
804 std::make_unique<PreprocessOnlyAction>();
805 auto *InputFile = CI.getFrontendOpts().Inputs.begin();
806 bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
807 assert(ActionBeginSucceeded && "Action BeginSourceFile must succeed");
808 (void)ActionBeginSucceeded;
809 }
810
811 Preprocessor &PP = CI.getPreprocessor();
813 FileID MainFileID = SM.getMainFileID();
814 SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
815 SourceLocation IDLocation = FileStart.getLocWithOffset(SrcLocOffset);
816 PPCallbacks *CB = nullptr;
817 if (!SrcLocOffset) {
818 // We need to call EnterSourceFile when SrcLocOffset is zero to initialize
819 // the preprocessor.
820 bool PPFailed = PP.EnterSourceFile(MainFileID, nullptr, SourceLocation());
821 assert(!PPFailed && "Preprocess must be able to enter the main file.");
822 (void)PPFailed;
823 CB = MDC->getPPCallbacks();
824 } else {
825 // When SrcLocOffset is non-zero, the preprocessor has already been
826 // initialized through a previous call of computeDependencies. We want to
827 // preserve the PP's state, hence we do not call EnterSourceFile again.
828 MDC->attachToPreprocessor(PP);
829 CB = MDC->getPPCallbacks();
830
831 FileID PrevFID;
832 SrcMgr::CharacteristicKind FileType = SM.getFileCharacteristic(IDLocation);
833 CB->LexedFileChanged(MainFileID,
835 FileType, PrevFID, IDLocation);
836 }
837
838 SrcLocOffset++;
840 IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
841 Path.emplace_back(IDLocation, ModuleID);
842 auto ModResult = CI.loadModule(IDLocation, Path, Module::Hidden, false);
843
844 assert(CB && "Must have PPCallbacks after module loading");
845 CB->moduleImport(SourceLocation(), Path, ModResult);
846 // Note that we are calling the CB's EndOfMainFile function, which
847 // forwards the results to the dependency consumer.
848 // It does not indicate the end of processing the fake file.
849 CB->EndOfMainFile();
850
851 if (!ModResult)
852 return false;
853
854 CompilerInvocation ModuleInvocation(*OriginalInvocation);
855 MDC->applyDiscoveredDependencies(ModuleInvocation);
856 Consumer.handleBuildCommand(
857 {CommandLine[0], ModuleInvocation.getCC1CommandLine()});
858
859 return true;
860}
861
863 DiagConsumer->finish();
864 return true;
865}
#define SM(sm)
Abstract interface for callback invocations by the ASTReader.
Definition ASTReader.h:117
@ ARR_OutOfDate
The client can handle an AST file that cannot load because it is out-of-date relative to its input fi...
Definition ASTReader.h:1835
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 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.
DiagnosticOptions & getDiagnosticOpts()
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...
Definition Utils.h:104
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.
Definition Diagnostic.h:232
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool hasErrorOccurred() const
Definition Diagnostic.h:872
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.
HeaderSearchOptions - Helper class for storing options related to the initialization of the HeaderSea...
unsigned ModulesStrictContextHash
Whether we should include all things that could impact the module in the hash.
unsigned ModulesForceValidateUserHeaders
Whether to force the validation of user input files when a module is loaded (even despite the build s...
std::map< std::string, std::string, std::less<> > PrebuiltModuleFiles
The mapping of module names to prebuilt module files.
uint64_t BuildSessionTimestamp
The time in seconds when the build session started.
unsigned ModulesSkipHeaderSearchPaths
Whether to entirely skip writing header search paths.
std::string ModuleFormat
The module/pch container format.
std::string Sysroot
If non-empty, the directory to use as a "virtual system root" for include paths.
unsigned ModulesSkipDiagnosticOptions
Whether to entirely skip writing diagnostic options.
std::string ModuleCachePath
The directory used for the module cache.
std::vector< std::string > VFSOverlayFiles
The set of user-provided virtual filesystem overlay files.
unsigned ModulesSerializeOnlyPreprocessor
Whether AST files should only contain the preprocessor information.
unsigned ModulesSkipPragmaDiagnosticMappings
Whether to entirely skip writing pragma diagnostic mappings.
unsigned ModulesIncludeVFSUsage
Whether to include ivfsoverlay usage information in written AST files.
std::string ResourceDir
The directory which holds the compiler resource files (builtin includes, etc.).
unsigned ModulesValidateOncePerBuildSession
If true, skip verifying input files used by modules if the module was already verified during this bu...
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.
Definition Module.h:445
This interface provides a way to observe the actions of the preprocessor as it does its thing.
Definition PPCallbacks.h:37
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.
Definition PPCallbacks.h:72
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.
Definition TypeBase.h:1833
bool initialize(std::unique_ptr< DiagnosticsEngineWithDiagOpts > DiagEngineWithDiagOpts, IntrusiveRefCntPtr< llvm::vfs::OverlayFileSystem > OverlayFS)
bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer, DependencyActionController &Controller)
Dependency scanner callbacks that are used during scanning to influence the behaviour of the scan - f...
bool runInvocation(std::string Executable, std::unique_ptr< CompilerInvocation > Invocation, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagConsumer)
The dependency scanning service contains shared configuration and state that is used by the individua...
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...
SmallVector< StringRef > getInitialStableDirs(const CompilerInstance &ScanInstance)
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)
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.
bool initializeScanCompilerInstance(CompilerInstance &ScanInstance, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service, IntrusiveRefCntPtr< DependencyScanningWorkerFilesystem > DepFS)
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)
std::optional< PrebuiltModulesAttrsMap > computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, SmallVector< StringRef > &StableDirs)
std::pair< IntrusiveRefCntPtr< llvm::vfs::OverlayFileSystem >, std::vector< std::string > > initVFSForByNameScanning(IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS, ArrayRef< std::string > CommandLine, StringRef WorkingDirectory, StringRef ModuleName)
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)
std::unique_ptr< DependencyOutputOptions > takeAndUpdateDependencyOutputOptionsFrom(CompilerInstance &ScanInstance)
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.
std::unique_ptr< DiagnosticOptions > createDiagOptions(ArrayRef< std::string > CommandLine)
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.
Definition Driver.cpp:7226
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.
Definition Driver.cpp:7243
bool IsClangCL(StringRef DriverMode)
Checks whether the value produced by getDriverMode is for CL mode.
Definition Driver.cpp:7241
ModuleKind
Specifies the kind of module that has been loaded.
Definition ModuleFile.h:43
@ MK_ExplicitModule
File is an explicitly-loaded module.
Definition ModuleFile.h:48
The JSON file list parser is used to communicate input to InstallAPI.
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Result
The result type of a method or function.
Definition TypeBase.h:905
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.
IntrusiveRefCntPtr< DiagnosticsEngine > DiagEngine
DiagnosticsEngineWithDiagOpts(ArrayRef< std::string > CommandLine, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, DiagnosticConsumer &DC)
This is used to identify a specific module.