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