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