1 //===-- ClangModulesDeclVendor.cpp ----------------------------------------===//
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
9 #include "clang/Basic/TargetInfo.h"
10 #include "clang/Frontend/CompilerInstance.h"
11 #include "clang/Frontend/FrontendActions.h"
12 #include "clang/Frontend/TextDiagnosticPrinter.h"
13 #include "clang/Lex/Preprocessor.h"
14 #include "clang/Lex/PreprocessorOptions.h"
15 #include "clang/Parse/Parser.h"
16 #include "clang/Sema/Lookup.h"
17 #include "clang/Serialization/ASTReader.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/Threading.h"
21
22 #include "ClangHost.h"
23 #include "ClangModulesDeclVendor.h"
24 #include "ModuleDependencyCollector.h"
25
26 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
27 #include "lldb/Core/ModuleList.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Host/HostInfo.h"
30 #include "lldb/Symbol/CompileUnit.h"
31 #include "lldb/Symbol/SourceModule.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Utility/FileSpec.h"
34 #include "lldb/Utility/LLDBAssert.h"
35 #include "lldb/Utility/LLDBLog.h"
36 #include "lldb/Utility/Log.h"
37 #include "lldb/Utility/ReproducerProvider.h"
38 #include "lldb/Utility/StreamString.h"
39
40 #include <memory>
41 #include <mutex>
42
43 using namespace lldb_private;
44
45 namespace {
46 /// Any Clang compiler requires a consumer for diagnostics. This one stores
47 /// them as strings so we can provide them to the user in case a module failed
48 /// to load.
49 class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
50 public:
51 StoringDiagnosticConsumer();
52
53 void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
54 const clang::Diagnostic &info) override;
55
56 void ClearDiagnostics();
57
58 void DumpDiagnostics(Stream &error_stream);
59
60 void BeginSourceFile(const clang::LangOptions &LangOpts,
61 const clang::Preprocessor *PP = nullptr) override;
62 void EndSourceFile() override;
63
64 private:
65 typedef std::pair<clang::DiagnosticsEngine::Level, std::string>
66 IDAndDiagnostic;
67 std::vector<IDAndDiagnostic> m_diagnostics;
68 /// The DiagnosticPrinter used for creating the full diagnostic messages
69 /// that are stored in m_diagnostics.
70 std::shared_ptr<clang::TextDiagnosticPrinter> m_diag_printer;
71 /// Output stream of m_diag_printer.
72 std::shared_ptr<llvm::raw_string_ostream> m_os;
73 /// Output string filled by m_os. Will be reused for different diagnostics.
74 std::string m_output;
75 Log *m_log;
76 };
77
78 /// The private implementation of our ClangModulesDeclVendor. Contains all the
79 /// Clang state required to load modules.
80 class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
81 public:
82 ClangModulesDeclVendorImpl(
83 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
84 std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
85 std::unique_ptr<clang::CompilerInstance> compiler_instance,
86 std::unique_ptr<clang::Parser> parser);
87
88 ~ClangModulesDeclVendorImpl() override = default;
89
90 bool AddModule(const SourceModule &module, ModuleVector *exported_modules,
91 Stream &error_stream) override;
92
93 bool AddModulesForCompileUnit(CompileUnit &cu, ModuleVector &exported_modules,
94 Stream &error_stream) override;
95
96 uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
97 std::vector<CompilerDecl> &decls) override;
98
99 void ForEachMacro(
100 const ModuleVector &modules,
101 std::function<bool(llvm::StringRef, llvm::StringRef)> handler) override;
102
103 private:
104 typedef llvm::DenseSet<ModuleID> ExportedModuleSet;
105 void ReportModuleExportsHelper(ExportedModuleSet &exports,
106 clang::Module *module);
107
108 void ReportModuleExports(ModuleVector &exports, clang::Module *module);
109
110 clang::ModuleLoadResult DoGetModule(clang::ModuleIdPath path,
111 bool make_visible);
112
113 bool m_enabled = false;
114
115 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
116 std::shared_ptr<clang::CompilerInvocation> m_compiler_invocation;
117 std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
118 std::unique_ptr<clang::Parser> m_parser;
119 size_t m_source_location_index =
120 0; // used to give name components fake SourceLocations
121
122 typedef std::vector<ConstString> ImportedModule;
123 typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
124 typedef llvm::DenseSet<ModuleID> ImportedModuleSet;
125 ImportedModuleMap m_imported_modules;
126 ImportedModuleSet m_user_imported_modules;
127 // We assume that every ASTContext has an TypeSystemClang, so we also store
128 // a custom TypeSystemClang for our internal ASTContext.
129 std::unique_ptr<TypeSystemClang> m_ast_context;
130 };
131 } // anonymous namespace
132
StoringDiagnosticConsumer()133 StoringDiagnosticConsumer::StoringDiagnosticConsumer() {
134 m_log = GetLog(LLDBLog::Expressions);
135
136 clang::DiagnosticOptions *m_options = new clang::DiagnosticOptions();
137 m_os = std::make_shared<llvm::raw_string_ostream>(m_output);
138 m_diag_printer =
139 std::make_shared<clang::TextDiagnosticPrinter>(*m_os, m_options);
140 }
141
HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,const clang::Diagnostic & info)142 void StoringDiagnosticConsumer::HandleDiagnostic(
143 clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) {
144 // Print the diagnostic to m_output.
145 m_output.clear();
146 m_diag_printer->HandleDiagnostic(DiagLevel, info);
147 m_os->flush();
148
149 // Store the diagnostic for later.
150 m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, m_output));
151 }
152
ClearDiagnostics()153 void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); }
154
DumpDiagnostics(Stream & error_stream)155 void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) {
156 for (IDAndDiagnostic &diag : m_diagnostics) {
157 switch (diag.first) {
158 default:
159 error_stream.PutCString(diag.second);
160 error_stream.PutChar('\n');
161 break;
162 case clang::DiagnosticsEngine::Level::Ignored:
163 break;
164 }
165 }
166 }
167
BeginSourceFile(const clang::LangOptions & LangOpts,const clang::Preprocessor * PP)168 void StoringDiagnosticConsumer::BeginSourceFile(
169 const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) {
170 m_diag_printer->BeginSourceFile(LangOpts, PP);
171 }
172
EndSourceFile()173 void StoringDiagnosticConsumer::EndSourceFile() {
174 m_diag_printer->EndSourceFile();
175 }
176
ClangModulesDeclVendor()177 ClangModulesDeclVendor::ClangModulesDeclVendor()
178 : ClangDeclVendor(eClangModuleDeclVendor) {}
179
180 ClangModulesDeclVendor::~ClangModulesDeclVendor() = default;
181
ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,std::shared_ptr<clang::CompilerInvocation> compiler_invocation,std::unique_ptr<clang::CompilerInstance> compiler_instance,std::unique_ptr<clang::Parser> parser)182 ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
183 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
184 std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
185 std::unique_ptr<clang::CompilerInstance> compiler_instance,
186 std::unique_ptr<clang::Parser> parser)
187 : m_diagnostics_engine(std::move(diagnostics_engine)),
188 m_compiler_invocation(std::move(compiler_invocation)),
189 m_compiler_instance(std::move(compiler_instance)),
190 m_parser(std::move(parser)) {
191
192 // Initialize our TypeSystemClang.
193 m_ast_context =
194 std::make_unique<TypeSystemClang>("ClangModulesDeclVendor ASTContext",
195 m_compiler_instance->getASTContext());
196 }
197
ReportModuleExportsHelper(ExportedModuleSet & exports,clang::Module * module)198 void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
199 ExportedModuleSet &exports, clang::Module *module) {
200 if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
201 return;
202
203 exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module));
204
205 llvm::SmallVector<clang::Module *, 2> sub_exports;
206
207 module->getExportedModules(sub_exports);
208
209 for (clang::Module *module : sub_exports)
210 ReportModuleExportsHelper(exports, module);
211 }
212
ReportModuleExports(ClangModulesDeclVendor::ModuleVector & exports,clang::Module * module)213 void ClangModulesDeclVendorImpl::ReportModuleExports(
214 ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) {
215 ExportedModuleSet exports_set;
216
217 ReportModuleExportsHelper(exports_set, module);
218
219 for (ModuleID module : exports_set)
220 exports.push_back(module);
221 }
222
AddModule(const SourceModule & module,ModuleVector * exported_modules,Stream & error_stream)223 bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module,
224 ModuleVector *exported_modules,
225 Stream &error_stream) {
226 // Fail early.
227
228 if (m_compiler_instance->hadModuleLoaderFatalFailure()) {
229 error_stream.PutCString("error: Couldn't load a module because the module "
230 "loader is in a fatal state.\n");
231 return false;
232 }
233
234 // Check if we've already imported this module.
235
236 std::vector<ConstString> imported_module;
237
238 for (ConstString path_component : module.path)
239 imported_module.push_back(path_component);
240
241 {
242 ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
243
244 if (mi != m_imported_modules.end()) {
245 if (exported_modules)
246 ReportModuleExports(*exported_modules, mi->second);
247 return true;
248 }
249 }
250
251 clang::HeaderSearch &HS =
252 m_compiler_instance->getPreprocessor().getHeaderSearchInfo();
253
254 if (module.search_path) {
255 auto path_begin = llvm::sys::path::begin(module.search_path.GetStringRef());
256 auto path_end = llvm::sys::path::end(module.search_path.GetStringRef());
257 auto sysroot_begin = llvm::sys::path::begin(module.sysroot.GetStringRef());
258 auto sysroot_end = llvm::sys::path::end(module.sysroot.GetStringRef());
259 // FIXME: Use C++14 std::equal(it, it, it, it) variant once it's available.
260 bool is_system_module = (std::distance(path_begin, path_end) >=
261 std::distance(sysroot_begin, sysroot_end)) &&
262 std::equal(sysroot_begin, sysroot_end, path_begin);
263 // No need to inject search paths to modules in the sysroot.
264 if (!is_system_module) {
265 auto error = [&]() {
266 error_stream.Printf("error: No module map file in %s\n",
267 module.search_path.AsCString());
268 return false;
269 };
270
271 bool is_system = true;
272 bool is_framework = false;
273 auto dir =
274 HS.getFileMgr().getDirectory(module.search_path.GetStringRef());
275 if (!dir)
276 return error();
277 auto *file = HS.lookupModuleMapFile(*dir, is_framework);
278 if (!file)
279 return error();
280 if (!HS.loadModuleMapFile(file, is_system))
281 return error();
282 }
283 }
284 if (!HS.lookupModule(module.path.front().GetStringRef())) {
285 error_stream.Printf("error: Header search couldn't locate module %s\n",
286 module.path.front().AsCString());
287 return false;
288 }
289
290 llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>,
291 4>
292 clang_path;
293
294 {
295 clang::SourceManager &source_manager =
296 m_compiler_instance->getASTContext().getSourceManager();
297
298 for (ConstString path_component : module.path) {
299 clang_path.push_back(std::make_pair(
300 &m_compiler_instance->getASTContext().Idents.get(
301 path_component.GetStringRef()),
302 source_manager.getLocForStartOfFile(source_manager.getMainFileID())
303 .getLocWithOffset(m_source_location_index++)));
304 }
305 }
306
307 StoringDiagnosticConsumer *diagnostic_consumer =
308 static_cast<StoringDiagnosticConsumer *>(
309 m_compiler_instance->getDiagnostics().getClient());
310
311 diagnostic_consumer->ClearDiagnostics();
312
313 clang::Module *top_level_module = DoGetModule(clang_path.front(), false);
314
315 if (!top_level_module) {
316 diagnostic_consumer->DumpDiagnostics(error_stream);
317 error_stream.Printf("error: Couldn't load top-level module %s\n",
318 module.path.front().AsCString());
319 return false;
320 }
321
322 clang::Module *submodule = top_level_module;
323
324 for (auto &component : llvm::ArrayRef<ConstString>(module.path).drop_front()) {
325 submodule = submodule->findSubmodule(component.GetStringRef());
326 if (!submodule) {
327 diagnostic_consumer->DumpDiagnostics(error_stream);
328 error_stream.Printf("error: Couldn't load submodule %s\n",
329 component.GetCString());
330 return false;
331 }
332 }
333
334 clang::Module *requested_module = DoGetModule(clang_path, true);
335
336 if (requested_module != nullptr) {
337 if (exported_modules)
338 ReportModuleExports(*exported_modules, requested_module);
339
340 m_imported_modules[imported_module] = requested_module;
341
342 m_enabled = true;
343
344 return true;
345 }
346
347 return false;
348 }
349
LanguageSupportsClangModules(lldb::LanguageType language)350 bool ClangModulesDeclVendor::LanguageSupportsClangModules(
351 lldb::LanguageType language) {
352 switch (language) {
353 default:
354 return false;
355 case lldb::LanguageType::eLanguageTypeC:
356 case lldb::LanguageType::eLanguageTypeC11:
357 case lldb::LanguageType::eLanguageTypeC89:
358 case lldb::LanguageType::eLanguageTypeC99:
359 case lldb::LanguageType::eLanguageTypeC_plus_plus:
360 case lldb::LanguageType::eLanguageTypeC_plus_plus_03:
361 case lldb::LanguageType::eLanguageTypeC_plus_plus_11:
362 case lldb::LanguageType::eLanguageTypeC_plus_plus_14:
363 case lldb::LanguageType::eLanguageTypeObjC:
364 case lldb::LanguageType::eLanguageTypeObjC_plus_plus:
365 return true;
366 }
367 }
368
AddModulesForCompileUnit(CompileUnit & cu,ClangModulesDeclVendor::ModuleVector & exported_modules,Stream & error_stream)369 bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
370 CompileUnit &cu, ClangModulesDeclVendor::ModuleVector &exported_modules,
371 Stream &error_stream) {
372 if (LanguageSupportsClangModules(cu.GetLanguage())) {
373 for (auto &imported_module : cu.GetImportedModules())
374 if (!AddModule(imported_module, &exported_modules, error_stream))
375 return false;
376 }
377 return true;
378 }
379
380 // ClangImporter::lookupValue
381
382 uint32_t
FindDecls(ConstString name,bool append,uint32_t max_matches,std::vector<CompilerDecl> & decls)383 ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
384 uint32_t max_matches,
385 std::vector<CompilerDecl> &decls) {
386 if (!m_enabled)
387 return 0;
388
389 if (!append)
390 decls.clear();
391
392 clang::IdentifierInfo &ident =
393 m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());
394
395 clang::LookupResult lookup_result(
396 m_compiler_instance->getSema(), clang::DeclarationName(&ident),
397 clang::SourceLocation(), clang::Sema::LookupOrdinaryName);
398
399 m_compiler_instance->getSema().LookupName(
400 lookup_result,
401 m_compiler_instance->getSema().getScopeForContext(
402 m_compiler_instance->getASTContext().getTranslationUnitDecl()));
403
404 uint32_t num_matches = 0;
405
406 for (clang::NamedDecl *named_decl : lookup_result) {
407 if (num_matches >= max_matches)
408 return num_matches;
409
410 decls.push_back(m_ast_context->GetCompilerDecl(named_decl));
411 ++num_matches;
412 }
413
414 return num_matches;
415 }
416
ForEachMacro(const ClangModulesDeclVendor::ModuleVector & modules,std::function<bool (llvm::StringRef,llvm::StringRef)> handler)417 void ClangModulesDeclVendorImpl::ForEachMacro(
418 const ClangModulesDeclVendor::ModuleVector &modules,
419 std::function<bool(llvm::StringRef, llvm::StringRef)> handler) {
420 if (!m_enabled)
421 return;
422
423 typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
424 ModulePriorityMap module_priorities;
425
426 ssize_t priority = 0;
427
428 for (ModuleID module : modules)
429 module_priorities[module] = priority++;
430
431 if (m_compiler_instance->getPreprocessor().getExternalSource()) {
432 m_compiler_instance->getPreprocessor()
433 .getExternalSource()
434 ->ReadDefinedMacros();
435 }
436
437 for (clang::Preprocessor::macro_iterator
438 mi = m_compiler_instance->getPreprocessor().macro_begin(),
439 me = m_compiler_instance->getPreprocessor().macro_end();
440 mi != me; ++mi) {
441 const clang::IdentifierInfo *ii = nullptr;
442
443 {
444 if (clang::IdentifierInfoLookup *lookup =
445 m_compiler_instance->getPreprocessor()
446 .getIdentifierTable()
447 .getExternalIdentifierLookup()) {
448 lookup->get(mi->first->getName());
449 }
450 if (!ii)
451 ii = mi->first;
452 }
453
454 ssize_t found_priority = -1;
455 clang::MacroInfo *macro_info = nullptr;
456
457 for (clang::ModuleMacro *module_macro :
458 m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) {
459 clang::Module *module = module_macro->getOwningModule();
460
461 {
462 ModulePriorityMap::iterator pi =
463 module_priorities.find(reinterpret_cast<ModuleID>(module));
464
465 if (pi != module_priorities.end() && pi->second > found_priority) {
466 macro_info = module_macro->getMacroInfo();
467 found_priority = pi->second;
468 }
469 }
470
471 clang::Module *top_level_module = module->getTopLevelModule();
472
473 if (top_level_module != module) {
474 ModulePriorityMap::iterator pi = module_priorities.find(
475 reinterpret_cast<ModuleID>(top_level_module));
476
477 if ((pi != module_priorities.end()) && pi->second > found_priority) {
478 macro_info = module_macro->getMacroInfo();
479 found_priority = pi->second;
480 }
481 }
482 }
483
484 if (macro_info) {
485 std::string macro_expansion = "#define ";
486 llvm::StringRef macro_identifier = mi->first->getName();
487 macro_expansion.append(macro_identifier.str());
488
489 {
490 if (macro_info->isFunctionLike()) {
491 macro_expansion.append("(");
492
493 bool first_arg = true;
494
495 for (auto pi = macro_info->param_begin(),
496 pe = macro_info->param_end();
497 pi != pe; ++pi) {
498 if (!first_arg)
499 macro_expansion.append(", ");
500 else
501 first_arg = false;
502
503 macro_expansion.append((*pi)->getName().str());
504 }
505
506 if (macro_info->isC99Varargs()) {
507 if (first_arg)
508 macro_expansion.append("...");
509 else
510 macro_expansion.append(", ...");
511 } else if (macro_info->isGNUVarargs())
512 macro_expansion.append("...");
513
514 macro_expansion.append(")");
515 }
516
517 macro_expansion.append(" ");
518
519 bool first_token = true;
520
521 for (clang::MacroInfo::const_tokens_iterator
522 ti = macro_info->tokens_begin(),
523 te = macro_info->tokens_end();
524 ti != te; ++ti) {
525 if (!first_token)
526 macro_expansion.append(" ");
527 else
528 first_token = false;
529
530 if (ti->isLiteral()) {
531 if (const char *literal_data = ti->getLiteralData()) {
532 std::string token_str(literal_data, ti->getLength());
533 macro_expansion.append(token_str);
534 } else {
535 bool invalid = false;
536 const char *literal_source =
537 m_compiler_instance->getSourceManager().getCharacterData(
538 ti->getLocation(), &invalid);
539
540 if (invalid) {
541 lldbassert(0 && "Unhandled token kind");
542 macro_expansion.append("<unknown literal value>");
543 } else {
544 macro_expansion.append(
545 std::string(literal_source, ti->getLength()));
546 }
547 }
548 } else if (const char *punctuator_spelling =
549 clang::tok::getPunctuatorSpelling(ti->getKind())) {
550 macro_expansion.append(punctuator_spelling);
551 } else if (const char *keyword_spelling =
552 clang::tok::getKeywordSpelling(ti->getKind())) {
553 macro_expansion.append(keyword_spelling);
554 } else {
555 switch (ti->getKind()) {
556 case clang::tok::TokenKind::identifier:
557 macro_expansion.append(ti->getIdentifierInfo()->getName().str());
558 break;
559 case clang::tok::TokenKind::raw_identifier:
560 macro_expansion.append(ti->getRawIdentifier().str());
561 break;
562 default:
563 macro_expansion.append(ti->getName());
564 break;
565 }
566 }
567 }
568
569 if (handler(macro_identifier, macro_expansion)) {
570 return;
571 }
572 }
573 }
574 }
575 }
576
577 clang::ModuleLoadResult
DoGetModule(clang::ModuleIdPath path,bool make_visible)578 ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
579 bool make_visible) {
580 clang::Module::NameVisibilityKind visibility =
581 make_visible ? clang::Module::AllVisible : clang::Module::Hidden;
582
583 const bool is_inclusion_directive = false;
584
585 return m_compiler_instance->loadModule(path.front().second, path, visibility,
586 is_inclusion_directive);
587 }
588
589 static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
590
591 lldb_private::ClangModulesDeclVendor *
Create(Target & target)592 ClangModulesDeclVendor::Create(Target &target) {
593 // FIXME we should insure programmatically that the expression parser's
594 // compiler and the modules runtime's
595 // compiler are both initialized in the same way – preferably by the same
596 // code.
597
598 if (!target.GetPlatform()->SupportsModules())
599 return nullptr;
600
601 const ArchSpec &arch = target.GetArchitecture();
602
603 std::vector<std::string> compiler_invocation_arguments = {
604 "clang",
605 "-fmodules",
606 "-fimplicit-module-maps",
607 "-fcxx-modules",
608 "-fsyntax-only",
609 "-femit-all-decls",
610 "-target",
611 arch.GetTriple().str(),
612 "-fmodules-validate-system-headers",
613 "-Werror=non-modular-include-in-framework-module"};
614
615 target.GetPlatform()->AddClangModuleCompilationOptions(
616 &target, compiler_invocation_arguments);
617
618 compiler_invocation_arguments.push_back(ModuleImportBufferName);
619
620 // Add additional search paths with { "-I", path } or { "-F", path } here.
621
622 {
623 llvm::SmallString<128> path;
624 const auto &props = ModuleList::GetGlobalModuleListProperties();
625 props.GetClangModulesCachePath().GetPath(path);
626 std::string module_cache_argument("-fmodules-cache-path=");
627 module_cache_argument.append(std::string(path.str()));
628 compiler_invocation_arguments.push_back(module_cache_argument);
629 }
630
631 FileSpecList module_search_paths = target.GetClangModuleSearchPaths();
632
633 for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) {
634 const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi);
635
636 std::string search_path_argument = "-I";
637 search_path_argument.append(search_path.GetPath());
638
639 compiler_invocation_arguments.push_back(search_path_argument);
640 }
641
642 {
643 FileSpec clang_resource_dir = GetClangResourceDir();
644
645 if (FileSystem::Instance().IsDirectory(clang_resource_dir.GetPath())) {
646 compiler_invocation_arguments.push_back("-resource-dir");
647 compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
648 }
649 }
650
651 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine =
652 clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions,
653 new StoringDiagnosticConsumer);
654
655 std::vector<const char *> compiler_invocation_argument_cstrs;
656 compiler_invocation_argument_cstrs.reserve(
657 compiler_invocation_arguments.size());
658 for (const std::string &arg : compiler_invocation_arguments)
659 compiler_invocation_argument_cstrs.push_back(arg.c_str());
660
661 Log *log = GetLog(LLDBLog::Expressions);
662 LLDB_LOG(log, "ClangModulesDeclVendor's compiler flags {0:$[ ]}",
663 llvm::make_range(compiler_invocation_arguments.begin(),
664 compiler_invocation_arguments.end()));
665
666 clang::CreateInvocationOptions CIOpts;
667 CIOpts.Diags = diagnostics_engine;
668 std::shared_ptr<clang::CompilerInvocation> invocation =
669 clang::createInvocation(compiler_invocation_argument_cstrs,
670 std::move(CIOpts));
671
672 if (!invocation)
673 return nullptr;
674
675 std::unique_ptr<llvm::MemoryBuffer> source_buffer =
676 llvm::MemoryBuffer::getMemBuffer(
677 "extern int __lldb __attribute__((unavailable));",
678 ModuleImportBufferName);
679
680 invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName,
681 source_buffer.release());
682
683 std::unique_ptr<clang::CompilerInstance> instance(
684 new clang::CompilerInstance);
685
686 // When capturing a reproducer, hook up the file collector with clang to
687 // collector modules and headers.
688 if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) {
689 repro::FileProvider &fp = g->GetOrCreate<repro::FileProvider>();
690 instance->setModuleDepCollector(
691 std::make_shared<ModuleDependencyCollectorAdaptor>(
692 fp.GetFileCollector()));
693 clang::DependencyOutputOptions &opts = instance->getDependencyOutputOpts();
694 opts.IncludeSystemHeaders = true;
695 opts.IncludeModuleFiles = true;
696 }
697
698 // Make sure clang uses the same VFS as LLDB.
699 instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem());
700 instance->setDiagnostics(diagnostics_engine.get());
701 instance->setInvocation(invocation);
702
703 std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
704
705 instance->setTarget(clang::TargetInfo::CreateTargetInfo(
706 *diagnostics_engine, instance->getInvocation().TargetOpts));
707
708 if (!instance->hasTarget())
709 return nullptr;
710
711 instance->getTarget().adjust(*diagnostics_engine, instance->getLangOpts());
712
713 if (!action->BeginSourceFile(*instance,
714 instance->getFrontendOpts().Inputs[0]))
715 return nullptr;
716
717 instance->getPreprocessor().enableIncrementalProcessing();
718
719 instance->createASTReader();
720
721 instance->createSema(action->getTranslationUnitKind(), nullptr);
722
723 const bool skipFunctionBodies = false;
724 std::unique_ptr<clang::Parser> parser(new clang::Parser(
725 instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));
726
727 instance->getPreprocessor().EnterMainSourceFile();
728 parser->Initialize();
729
730 clang::Parser::DeclGroupPtrTy parsed;
731 auto ImportState = clang::Sema::ModuleImportState::NotACXX20Module;
732 while (!parser->ParseTopLevelDecl(parsed, ImportState))
733 ;
734
735 return new ClangModulesDeclVendorImpl(std::move(diagnostics_engine),
736 std::move(invocation),
737 std::move(instance), std::move(parser));
738 }
739