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
12#include "clang/Driver/Driver.h"
15#include "llvm/ADT/ScopeExit.h"
16#include "llvm/TargetParser/Host.h"
17
18using namespace clang;
19using namespace tooling;
20using namespace dependencies;
21
22namespace {
23/// Forwards the gatherered dependencies to the consumer.
24class DependencyConsumerForwarder : public DependencyFileGenerator {
25public:
26 DependencyConsumerForwarder(std::unique_ptr<DependencyOutputOptions> Opts,
27 StringRef WorkingDirectory, DependencyConsumer &C)
28 : DependencyFileGenerator(*Opts), WorkingDirectory(WorkingDirectory),
29 Opts(std::move(Opts)), C(C) {}
30
31 void finishedMainFile(DiagnosticsEngine &Diags) override {
32 C.handleDependencyOutputOpts(*Opts);
33 llvm::SmallString<256> CanonPath;
34 for (const auto &File : getDependencies()) {
35 CanonPath = File;
36 llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true);
37 llvm::sys::path::make_absolute(WorkingDirectory, CanonPath);
38 C.handleFileDependency(CanonPath);
39 }
40 }
41
42private:
43 StringRef WorkingDirectory;
44 std::unique_ptr<DependencyOutputOptions> Opts;
45 DependencyConsumer &C;
46};
47
48static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
49 const HeaderSearchOptions &ExistingHSOpts,
50 DiagnosticsEngine *Diags,
51 const LangOptions &LangOpts) {
52 if (LangOpts.Modules) {
53 if (HSOpts.VFSOverlayFiles != ExistingHSOpts.VFSOverlayFiles) {
54 if (Diags) {
55 Diags->Report(diag::warn_pch_vfsoverlay_mismatch);
56 auto VFSNote = [&](int Type, ArrayRef<std::string> VFSOverlays) {
57 if (VFSOverlays.empty()) {
58 Diags->Report(diag::note_pch_vfsoverlay_empty) << Type;
59 } else {
60 std::string Files = llvm::join(VFSOverlays, "\n");
61 Diags->Report(diag::note_pch_vfsoverlay_files) << Type << Files;
62 }
63 };
64 VFSNote(0, HSOpts.VFSOverlayFiles);
65 VFSNote(1, ExistingHSOpts.VFSOverlayFiles);
66 }
67 }
68 }
69 return false;
70}
71
72using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles);
73
74/// A listener that collects the imported modules and the input
75/// files. While visiting, collect vfsoverlays and file inputs that determine
76/// whether prebuilt modules fully resolve in stable directories.
77class PrebuiltModuleListener : public ASTReaderListener {
78public:
79 PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
80 llvm::SmallVector<std::string> &NewModuleFiles,
81 PrebuiltModulesAttrsMap &PrebuiltModulesASTMap,
82 const HeaderSearchOptions &HSOpts,
83 const LangOptions &LangOpts, DiagnosticsEngine &Diags,
84 const ArrayRef<StringRef> StableDirs)
85 : PrebuiltModuleFiles(PrebuiltModuleFiles),
86 NewModuleFiles(NewModuleFiles),
87 PrebuiltModulesASTMap(PrebuiltModulesASTMap), ExistingHSOpts(HSOpts),
88 ExistingLangOpts(LangOpts), Diags(Diags), StableDirs(StableDirs) {}
89
90 bool needsImportVisitation() const override { return true; }
91 bool needsInputFileVisitation() override { return true; }
92 bool needsSystemInputFileVisitation() override { return true; }
93
94 /// Accumulate the modules are transitively depended on by the initial
95 /// prebuilt module.
96 void visitImport(StringRef ModuleName, StringRef Filename) override {
97 if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second)
98 NewModuleFiles.push_back(Filename.str());
99
100 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(Filename);
101 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
102 if (PrebuiltMapEntry.second)
103 PrebuiltModule.setInStableDir(!StableDirs.empty());
104
105 if (auto It = PrebuiltModulesASTMap.find(CurrentFile);
106 It != PrebuiltModulesASTMap.end() && CurrentFile != Filename)
107 PrebuiltModule.addDependent(It->getKey());
108 }
109
110 /// For each input file discovered, check whether it's external path is in a
111 /// stable directory. Traversal is stopped if the current module is not
112 /// considered stable.
113 bool visitInputFileAsRequested(StringRef FilenameAsRequested,
114 StringRef Filename, bool isSystem,
115 bool isOverridden,
116 bool isExplicitModule) override {
117 if (StableDirs.empty())
118 return false;
119 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
120 if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end()) ||
121 (!PrebuiltEntryIt->second.isInStableDir()))
122 return false;
123
124 PrebuiltEntryIt->second.setInStableDir(
125 isPathInStableDir(StableDirs, Filename));
126 return PrebuiltEntryIt->second.isInStableDir();
127 }
128
129 /// Update which module that is being actively traversed.
130 void visitModuleFile(StringRef Filename,
131 serialization::ModuleKind Kind) override {
132 // If the CurrentFile is not
133 // considered stable, update any of it's transitive dependents.
134 auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
135 if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end()) &&
136 !PrebuiltEntryIt->second.isInStableDir())
137 PrebuiltEntryIt->second.updateDependentsNotInStableDirs(
138 PrebuiltModulesASTMap);
139 CurrentFile = Filename;
140 }
141
142 /// Check the header search options for a given module when considering
143 /// if the module comes from stable directories.
144 bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
145 StringRef ModuleFilename,
146 StringRef SpecificModuleCachePath,
147 bool Complain) override {
148
149 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
150 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
151 if (PrebuiltMapEntry.second)
152 PrebuiltModule.setInStableDir(!StableDirs.empty());
153
154 if (PrebuiltModule.isInStableDir())
155 PrebuiltModule.setInStableDir(areOptionsInStableDir(StableDirs, HSOpts));
156
157 return false;
158 }
159
160 /// Accumulate vfsoverlays used to build these prebuilt modules.
161 bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
162 bool Complain) override {
163
164 auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
165 PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
166 if (PrebuiltMapEntry.second)
167 PrebuiltModule.setInStableDir(!StableDirs.empty());
168
169 PrebuiltModule.setVFS(
170 llvm::StringSet<>(llvm::from_range, HSOpts.VFSOverlayFiles));
171
172 return checkHeaderSearchPaths(
173 HSOpts, ExistingHSOpts, Complain ? &Diags : nullptr, ExistingLangOpts);
174 }
175
176private:
177 PrebuiltModuleFilesT &PrebuiltModuleFiles;
178 llvm::SmallVector<std::string> &NewModuleFiles;
179 PrebuiltModulesAttrsMap &PrebuiltModulesASTMap;
180 const HeaderSearchOptions &ExistingHSOpts;
181 const LangOptions &ExistingLangOpts;
182 DiagnosticsEngine &Diags;
183 std::string CurrentFile;
184 const ArrayRef<StringRef> StableDirs;
185};
186
187/// Visit the given prebuilt module and collect all of the modules it
188/// transitively imports and contributing input files.
189static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
191 PrebuiltModuleFilesT &ModuleFiles,
192 PrebuiltModulesAttrsMap &PrebuiltModulesASTMap,
193 DiagnosticsEngine &Diags,
194 const ArrayRef<StringRef> StableDirs) {
195 // List of module files to be processed.
197
198 PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModulesASTMap,
200 Diags, StableDirs);
201
202 Listener.visitModuleFile(PrebuiltModuleFilename,
205 PrebuiltModuleFilename, CI.getFileManager(), CI.getModuleCache(),
207 /*FindModuleFileExtensions=*/false, Listener,
208 /*ValidateDiagnosticOptions=*/false, ASTReader::ARR_OutOfDate))
209 return true;
210
211 while (!Worklist.empty()) {
212 Listener.visitModuleFile(Worklist.back(), serialization::MK_ExplicitModule);
214 Worklist.pop_back_val(), CI.getFileManager(), CI.getModuleCache(),
216 /*FindModuleFileExtensions=*/false, Listener,
217 /*ValidateDiagnosticOptions=*/false))
218 return true;
219 }
220 return false;
221}
222
223/// Transform arbitrary file name into an object-like file name.
224static std::string makeObjFileName(StringRef FileName) {
225 SmallString<128> ObjFileName(FileName);
226 llvm::sys::path::replace_extension(ObjFileName, "o");
227 return std::string(ObjFileName);
228}
229
230/// Deduce the dependency target based on the output file and input files.
231static std::string
232deduceDepTarget(const std::string &OutputFile,
233 const SmallVectorImpl<FrontendInputFile> &InputFiles) {
234 if (OutputFile != "-")
235 return OutputFile;
236
237 if (InputFiles.empty() || !InputFiles.front().isFile())
238 return "clang-scan-deps\\ dependency";
239
240 return makeObjFileName(InputFiles.front().getFile());
241}
242
243// Clang implements -D and -U by splatting text into a predefines buffer. This
244// allows constructs such as `-DFඞ=3 "-D F\u{0D9E} 4 3 2”` to be accepted and
245// define the same macro, or adding C++ style comments before the macro name.
246//
247// This function checks that the first non-space characters in the macro
248// obviously form an identifier that can be uniqued on without lexing. Failing
249// to do this could lead to changing the final definition of a macro.
250//
251// We could set up a preprocessor and actually lex the name, but that's very
252// heavyweight for a situation that will almost never happen in practice.
253static std::optional<StringRef> getSimpleMacroName(StringRef Macro) {
254 StringRef Name = Macro.split("=").first.ltrim(" \t");
255 std::size_t I = 0;
256
257 auto FinishName = [&]() -> std::optional<StringRef> {
258 StringRef SimpleName = Name.slice(0, I);
259 if (SimpleName.empty())
260 return std::nullopt;
261 return SimpleName;
262 };
263
264 for (; I != Name.size(); ++I) {
265 switch (Name[I]) {
266 case '(': // Start of macro parameter list
267 case ' ': // End of macro name
268 case '\t':
269 return FinishName();
270 case '_':
271 continue;
272 default:
273 if (llvm::isAlnum(Name[I]))
274 continue;
275 return std::nullopt;
276 }
277 }
278 return FinishName();
279}
280
281static void canonicalizeDefines(PreprocessorOptions &PPOpts) {
282 using MacroOpt = std::pair<StringRef, std::size_t>;
283 std::vector<MacroOpt> SimpleNames;
284 SimpleNames.reserve(PPOpts.Macros.size());
285 std::size_t Index = 0;
286 for (const auto &M : PPOpts.Macros) {
287 auto SName = getSimpleMacroName(M.first);
288 // Skip optimizing if we can't guarantee we can preserve relative order.
289 if (!SName)
290 return;
291 SimpleNames.emplace_back(*SName, Index);
292 ++Index;
293 }
294
295 llvm::stable_sort(SimpleNames, llvm::less_first());
296 // Keep the last instance of each macro name by going in reverse
297 auto NewEnd = std::unique(
298 SimpleNames.rbegin(), SimpleNames.rend(),
299 [](const MacroOpt &A, const MacroOpt &B) { return A.first == B.first; });
300 SimpleNames.erase(SimpleNames.begin(), NewEnd.base());
301
302 // Apply permutation.
303 decltype(PPOpts.Macros) NewMacros;
304 NewMacros.reserve(SimpleNames.size());
305 for (std::size_t I = 0, E = SimpleNames.size(); I != E; ++I) {
306 std::size_t OriginalIndex = SimpleNames[I].second;
307 // We still emit undefines here as they may be undefining a predefined macro
308 NewMacros.push_back(std::move(PPOpts.Macros[OriginalIndex]));
309 }
310 std::swap(PPOpts.Macros, NewMacros);
311}
312
313class ScanningDependencyDirectivesGetter : public DependencyDirectivesGetter {
314 DependencyScanningWorkerFilesystem *DepFS;
315
316public:
317 ScanningDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(nullptr) {
318 FileMgr.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) {
319 auto *DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
320 if (DFS) {
321 assert(!DepFS && "Found multiple scanning VFSs");
322 DepFS = DFS;
323 }
324 });
325 assert(DepFS && "Did not find scanning VFS");
326 }
327
328 std::unique_ptr<DependencyDirectivesGetter>
329 cloneFor(FileManager &FileMgr) override {
330 return std::make_unique<ScanningDependencyDirectivesGetter>(FileMgr);
331 }
332
333 std::optional<ArrayRef<dependency_directives_scan::Directive>>
334 operator()(FileEntryRef File) override {
335 return DepFS->getDirectiveTokens(File.getName());
336 }
337};
338
339/// Sanitize diagnostic options for dependency scan.
340void sanitizeDiagOpts(DiagnosticOptions &DiagOpts) {
341 // Don't print 'X warnings and Y errors generated'.
342 DiagOpts.ShowCarets = false;
343 // Don't write out diagnostic file.
344 DiagOpts.DiagnosticSerializationFile.clear();
345 // Don't emit warnings except for scanning specific warnings.
346 // TODO: It would be useful to add a more principled way to ignore all
347 // warnings that come from source code. The issue is that we need to
348 // ignore warnings that could be surpressed by
349 // `#pragma clang diagnostic`, while still allowing some scanning
350 // warnings for things we're not ready to turn into errors yet.
351 // See `test/ClangScanDeps/diagnostic-pragmas.c` for an example.
352 llvm::erase_if(DiagOpts.Warnings, [](StringRef Warning) {
353 return llvm::StringSwitch<bool>(Warning)
354 .Cases({"pch-vfs-diff", "error=pch-vfs-diff"}, false)
355 .StartsWith("no-error=", false)
356 .Default(true);
357 });
358}
359} // namespace
360
362std::unique_ptr<DiagnosticOptions>
364 std::vector<const char *> CLI;
365 for (const std::string &Arg : CommandLine)
366 CLI.push_back(Arg.c_str());
367 auto DiagOpts = CreateAndPopulateDiagOpts(CLI);
368 sanitizeDiagOpts(*DiagOpts);
369 return DiagOpts;
370}
371
373 ArrayRef<std::string> CommandLine,
375 std::vector<const char *> CCommandLine(CommandLine.size(), nullptr);
376 llvm::transform(CommandLine, CCommandLine.begin(),
377 [](const std::string &Str) { return Str.c_str(); });
378 DiagOpts = CreateAndPopulateDiagOpts(CCommandLine);
379 sanitizeDiagOpts(*DiagOpts);
381 /*ShouldOwnClient=*/false);
382}
383
384std::pair<std::unique_ptr<driver::Driver>, std::unique_ptr<driver::Compilation>>
387 llvm::BumpPtrAllocator &Alloc) {
389 Argv.reserve(ArgStrs.size());
390 for (const std::string &Arg : ArgStrs)
391 Argv.push_back(Arg.c_str());
392
393 std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
394 Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
395 "clang LLVM compiler", FS);
396 Driver->setTitle("clang_based_tool");
397
398 bool CLMode = driver::IsClangCL(
399 driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1)));
400
401 if (llvm::Error E =
402 driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) {
403 Diags.Report(diag::err_drv_expand_response_file)
404 << llvm::toString(std::move(E));
405 return std::make_pair(nullptr, nullptr);
406 }
407
408 std::unique_ptr<driver::Compilation> Compilation(
409 Driver->BuildCompilation(Argv));
410 if (!Compilation)
411 return std::make_pair(nullptr, nullptr);
412
413 if (Compilation->containsError())
414 return std::make_pair(nullptr, nullptr);
415
416 return std::make_pair(std::move(Driver), std::move(Compilation));
417}
418
419std::unique_ptr<CompilerInvocation>
421 DiagnosticsEngine &Diags) {
422 llvm::opt::ArgStringList Argv;
423 for (const std::string &Str : ArrayRef(CommandLine).drop_front())
424 Argv.push_back(Str.c_str());
425
426 auto Invocation = std::make_unique<CompilerInvocation>();
427 if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) {
428 // FIXME: Should we just go on like cc1_main does?
429 return nullptr;
430 }
431 return Invocation;
432}
433
434std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::vector<std::string>>
436 ArrayRef<std::string> CommandLine,
437 StringRef WorkingDirectory,
438 llvm::MemoryBufferRef TUBuffer) {
439 // Reset what might have been modified in the previous worker invocation.
440 BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
441
443 auto OverlayFS =
444 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
445 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
446 InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
447 auto InputPath = TUBuffer.getBufferIdentifier();
448 InMemoryFS->addFile(
449 InputPath, 0, llvm::MemoryBuffer::getMemBufferCopy(TUBuffer.getBuffer()));
450 IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay = InMemoryFS;
451
452 OverlayFS->pushOverlay(InMemoryOverlay);
453 ModifiedFS = OverlayFS;
454 std::vector<std::string> ModifiedCommandLine(CommandLine);
455 ModifiedCommandLine.emplace_back(InputPath);
456
457 return std::make_pair(ModifiedFS, ModifiedCommandLine);
458}
459
460std::pair<IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>,
461 std::vector<std::string>>
463 ArrayRef<std::string> CommandLine,
464 StringRef WorkingDirectory, 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 the dependency scanning optimized file system if requested to do so.
527 if (DepFS) {
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 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 // This function moves the existing dependency output options from the
595 // invocation to the collector. The options in the invocation are reset,
596 // which ensures that the compiler won't create new dependency collectors,
597 // and thus won't write out the extra '.d' files to disk.
598 auto Opts = std::make_unique<DependencyOutputOptions>();
599 std::swap(*Opts, ScanInstance.getInvocation().getDependencyOutputOpts());
600 // We need at least one -MT equivalent for the generator of make dependency
601 // files to work.
602 if (Opts->Targets.empty())
603 Opts->Targets = {deduceDepTarget(ScanInstance.getFrontendOpts().OutputFile,
604 ScanInstance.getFrontendOpts().Inputs)};
605 Opts->IncludeSystemHeaders = true;
606
607 return Opts;
608}
609
610std::shared_ptr<ModuleDepCollector> initializeScanInstanceDependencyCollector(
611 CompilerInstance &ScanInstance,
612 std::unique_ptr<DependencyOutputOptions> DepOutputOpts,
613 StringRef WorkingDirectory, DependencyConsumer &Consumer,
615 DependencyActionController &Controller,
616 PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
617 llvm::SmallVector<StringRef> &StableDirs) {
618 std::shared_ptr<ModuleDepCollector> MDC;
619 switch (Service.getFormat()) {
621 ScanInstance.addDependencyCollector(
622 std::make_shared<DependencyConsumerForwarder>(
623 std::move(DepOutputOpts), WorkingDirectory, Consumer));
624 break;
627 MDC = std::make_shared<ModuleDepCollector>(
628 Service, std::move(DepOutputOpts), ScanInstance, Consumer, Controller,
629 Inv, std::move(PrebuiltModulesASTMap), StableDirs);
630 ScanInstance.addDependencyCollector(MDC);
631 break;
632 }
633
634 return MDC;
635}
636} // namespace clang::tooling::dependencies
637
639 std::unique_ptr<CompilerInvocation> Invocation,
641 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
642 DiagnosticConsumer *DiagConsumer) {
643 // Making sure that we canonicalize the defines before we create the deep
644 // copy to avoid unnecessary variants in the scanner and in the resulting
645 // explicit command lines.
646 if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros))
647 canonicalizeDefines(Invocation->getPreprocessorOpts());
648
649 // Make a deep copy of the original Clang invocation.
650 CompilerInvocation OriginalInvocation(*Invocation);
651
652 if (Scanned) {
653 // Scanning runs once for the first -cc1 invocation in a chain of driver
654 // jobs. For any dependent jobs, reuse the scanning result and just
655 // update the LastCC1Arguments to correspond to the new invocation.
656 // FIXME: to support multi-arch builds, each arch requires a separate scan
657 setLastCC1Arguments(std::move(OriginalInvocation));
658 return true;
659 }
660
661 Scanned = true;
662
663 // Create a compiler instance to handle the actual work.
664 auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries());
665 ScanInstanceStorage.emplace(std::move(Invocation), std::move(PCHContainerOps),
666 ModCache.get());
667 CompilerInstance &ScanInstance = *ScanInstanceStorage;
668
669 assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
670 if (!initializeScanCompilerInstance(ScanInstance, FS, DiagConsumer, Service,
671 DepFS))
672 return false;
673
674 llvm::SmallVector<StringRef> StableDirs = getInitialStableDirs(ScanInstance);
675 auto MaybePrebuiltModulesASTMap =
676 computePrebuiltModulesASTMap(ScanInstance, StableDirs);
677 if (!MaybePrebuiltModulesASTMap)
678 return false;
679
680 auto DepOutputOpts = takeAndUpdateDependencyOutputOptionsFrom(ScanInstance);
681
683 ScanInstance, std::move(DepOutputOpts), WorkingDirectory, Consumer,
684 Service, OriginalInvocation, Controller, *MaybePrebuiltModulesASTMap,
685 StableDirs);
686
687 std::unique_ptr<FrontendAction> Action;
688
689 if (Service.getFormat() == ScanningOutputFormat::P1689)
690 Action = std::make_unique<PreprocessOnlyAction>();
691 else
692 Action = std::make_unique<ReadPCHAndPreprocessAction>();
693
694 if (ScanInstance.getDiagnostics().hasErrorOccurred())
695 return false;
696
697 const bool Result = ScanInstance.ExecuteAction(*Action);
698
699 // ExecuteAction is responsible for calling finish.
700 DiagConsumerFinished = true;
701
702 if (Result)
703 setLastCC1Arguments(std::move(OriginalInvocation));
704
705 return Result;
706}
707
709 if (DC) {
710 DiagConsumer = DC;
711 } else {
712 DiagPrinterWithOS =
713 std::make_unique<TextDiagnosticsPrinterWithOutput>(CommandLine);
714 DiagConsumer = &DiagPrinterWithOS->DiagPrinter;
715 }
716
717 std::tie(OverlayFS, CommandLine) = initVFSForByNameScanning(
718 Worker.BaseFS, CommandLine, CWD, "ScanningByName");
719
720 DiagEngineWithCmdAndOpts = std::make_unique<DignosticsEngineWithDiagOpts>(
721 CommandLine, OverlayFS, *DiagConsumer);
722
723 std::tie(Driver, Compilation) = buildCompilation(
724 CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine, OverlayFS, Alloc);
725
726 if (!Compilation)
727 return false;
728
729 assert(Compilation->getJobs().size() &&
730 "Must have a job list of non-zero size");
731 const driver::Command &Command = *(Compilation->getJobs().begin());
732 const auto &CommandArgs = Command.getArguments();
733 assert(!CommandArgs.empty() && "Cannot have a command with 0 args");
734 assert(StringRef(CommandArgs[0]) == "-cc1" && "Requires a cc1 job.");
735 OriginalInvocation = std::make_unique<CompilerInvocation>();
736
737 if (!CompilerInvocation::CreateFromArgs(*OriginalInvocation, CommandArgs,
738 *DiagEngineWithCmdAndOpts->DiagEngine,
739 Command.getExecutable())) {
740 DiagEngineWithCmdAndOpts->DiagEngine->Report(
741 diag::err_fe_expected_compiler_job)
742 << llvm::join(CommandLine, " ");
743 return false;
744 }
745
746 if (any(Worker.Service.getOptimizeArgs() & ScanningOptimizations::Macros))
747 canonicalizeDefines(OriginalInvocation->getPreprocessorOpts());
748
749 // Create the CompilerInstance.
751 makeInProcessModuleCache(Worker.Service.getModuleCacheEntries());
752 CIPtr = std::make_unique<CompilerInstance>(
753 std::make_shared<CompilerInvocation>(*OriginalInvocation),
754 Worker.PCHContainerOps, ModCache.get());
755 auto &CI = *CIPtr;
756
758 CI, OverlayFS, DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
759 Worker.Service, Worker.DepFS))
760 return false;
761
762 StableDirs = getInitialStableDirs(CI);
763 auto MaybePrebuiltModulesASTMap =
764 computePrebuiltModulesASTMap(CI, StableDirs);
765 if (!MaybePrebuiltModulesASTMap)
766 return false;
767
768 PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
770
771 // We do not create the target in initializeScanCompilerInstance because
772 // setting it here is unique for by-name lookups. We create the target only
773 // once here, and the information is reused for all computeDependencies calls.
774 // We do not need to call createTarget explicitly if we go through
775 // CompilerInstance::ExecuteAction to perform scanning.
776 CI.createTarget();
777
778 return true;
779}
780
782 StringRef ModuleName, DependencyConsumer &Consumer,
783 DependencyActionController &Controller) {
784 assert(CIPtr && "CIPtr must be initialized before calling this method");
785 auto &CI = *CIPtr;
786
787 // We create this cleanup object because computeDependencies may exit
788 // early with errors.
789 auto CleanUp = llvm::make_scope_exit([&]() {
791 // The preprocessor may not be created at the entry of this method,
792 // but it must have been created when this method returns, whether
793 // there are errors during scanning or not.
795 });
796
798 CI, std::make_unique<DependencyOutputOptions>(*OutputOpts), CWD, Consumer,
799 Worker.Service,
800 /* The MDC's constructor makes a copy of the OriginalInvocation, so
801 we can pass it in without worrying that it might be changed across
802 invocations of computeDependencies. */
803 *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
804
805 if (!SrcLocOffset) {
806 // When SrcLocOffset is zero, we are at the beginning of the fake source
807 // file. In this case, we call BeginSourceFile to initialize.
808 std::unique_ptr<FrontendAction> Action =
809 std::make_unique<PreprocessOnlyAction>();
810 auto InputFile = CI.getFrontendOpts().Inputs.begin();
811 bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
812 assert(ActionBeginSucceeded && "Action BeginSourceFile must succeed");
813 (void)ActionBeginSucceeded;
814 }
815
816 Preprocessor &PP = CI.getPreprocessor();
818 FileID MainFileID = SM.getMainFileID();
819 SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
820 SourceLocation IDLocation = FileStart.getLocWithOffset(SrcLocOffset);
821 PPCallbacks *CB = nullptr;
822 if (!SrcLocOffset) {
823 // We need to call EnterSourceFile when SrcLocOffset is zero to initialize
824 // the preprocessor.
825 bool PPFailed = PP.EnterSourceFile(MainFileID, nullptr, SourceLocation());
826 assert(!PPFailed && "Preprocess must be able to enter the main file.");
827 (void)PPFailed;
828 CB = MDC->getPPCallbacks();
829 } else {
830 // When SrcLocOffset is non-zero, the preprocessor has already been
831 // initialized through a previous call of computeDependencies. We want to
832 // preserve the PP's state, hence we do not call EnterSourceFile again.
833 MDC->attachToPreprocessor(PP);
834 CB = MDC->getPPCallbacks();
835
836 FileID PrevFID;
837 SrcMgr::CharacteristicKind FileType = SM.getFileCharacteristic(IDLocation);
838 CB->LexedFileChanged(MainFileID,
840 FileType, PrevFID, IDLocation);
841 }
842
843 SrcLocOffset++;
845 IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
846 Path.emplace_back(IDLocation, ModuleID);
847 auto ModResult = CI.loadModule(IDLocation, Path, Module::Hidden, false);
848
849 assert(CB && "Must have PPCallbacks after module loading");
850 CB->moduleImport(SourceLocation(), Path, ModResult);
851 // Note that we are calling the CB's EndOfMainFile function, which
852 // forwards the results to the dependency consumer.
853 // It does not indicate the end of processing the fake file.
854 CB->EndOfMainFile();
855
856 if (!ModResult)
857 return false;
858
859 CompilerInvocation ModuleInvocation(*OriginalInvocation);
860 MDC->applyDiscoveredDependencies(ModuleInvocation);
861 Consumer.handleBuildCommand(
862 {CommandLine[0], ModuleInvocation.getCC1CommandLine()});
863
864 return true;
865}
866
868 DiagConsumer->finish();
869 return true;
870}
871
873 assert(DiagPrinterWithOS && "Must use the default DiagnosticConsumer.");
874 return Success ? llvm::Error::success()
875 : llvm::make_error<llvm::StringError>(
876 DiagPrinterWithOS->DiagnosticsOS.str(),
877 llvm::inconvertibleErrorCode());
878}
#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:1837
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
Command - An executable path/name and argument vector to execute.
Definition Job.h:106
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::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.
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.
bool isInStableDir() const
Read-only access to whether the module is made up of dependencies in stable directories.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
llvm::StringRef getDriverMode(StringRef ProgName, ArrayRef< const char * > Args)
Returns the driver mode option's value, i.e.
Definition Driver.cpp:7174
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:7191
bool IsClangCL(StringRef DriverMode)
Checks whether the value produced by getDriverMode is for CL mode.
Definition Driver.cpp:7189
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
llvm::SmallVector< StringRef > getInitialStableDirs(const CompilerInstance &ScanInstance)
std::unique_ptr< DiagnosticOptions > createDiagOptions(ArrayRef< std::string > CommandLine)
@ 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.
bool initializeScanCompilerInstance(CompilerInstance &ScanInstance, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service, IntrusiveRefCntPtr< DependencyScanningWorkerFilesystem > DepFS)
std::pair< IntrusiveRefCntPtr< llvm::vfs::OverlayFileSystem >, std::vector< std::string > > initVFSForByNameScanning(IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS, ArrayRef< std::string > CommandLine, StringRef WorkingDirectory, StringRef ModuleName)
bool areOptionsInStableDir(const ArrayRef< StringRef > Directories, const HeaderSearchOptions &HSOpts)
Determine if options collected from a module's compilation can safely be considered as stable.
IntrusiveRefCntPtr< ModuleCache > makeInProcessModuleCache(ModuleCacheEntries &Entries)
std::unique_ptr< CompilerInvocation > createCompilerInvocation(ArrayRef< std::string > CommandLine, DiagnosticsEngine &Diags)
bool isPathInStableDir(const ArrayRef< StringRef > Directories, const StringRef Input)
Determine if Input can be resolved within a stable directory.
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< DependencyOutputOptions > takeAndUpdateDependencyOutputOptionsFrom(CompilerInstance &ScanInstance)
std::optional< PrebuiltModulesAttrsMap > computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, llvm::SmallVector< StringRef > &StableDirs)
llvm::StringMap< PrebuiltModuleASTAttrs > PrebuiltModulesAttrsMap
Attributes loaded from AST files of prebuilt modules collected prior to ModuleDepCollector creation.
std::pair< IntrusiveRefCntPtr< llvm::vfs::FileSystem >, std::vector< std::string > > initVFSForTUBuferScanning(IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS, ArrayRef< std::string > CommandLine, StringRef WorkingDirectory, llvm::MemoryBufferRef TUBuffer)
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)
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.
Definition Parser.h:65
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.
A command-line tool invocation that is part of building a TU.
DignosticsEngineWithDiagOpts(ArrayRef< std::string > CommandLine, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, DiagnosticConsumer &DC)
This is used to identify a specific module.