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