1 //===-- ClangModulesDeclVendor.cpp ----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/Basic/Diagnostic.h"
10 #include "clang/Basic/DiagnosticFrontend.h"
11 #include "clang/Basic/DiagnosticSerialization.h"
12 #include "clang/Basic/TargetInfo.h"
13 #include "clang/Frontend/CompilerInstance.h"
14 #include "clang/Frontend/FrontendActions.h"
15 #include "clang/Frontend/TextDiagnosticPrinter.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "clang/Lex/PreprocessorOptions.h"
18 #include "clang/Parse/Parser.h"
19 #include "clang/Sema/Lookup.h"
20 #include "clang/Serialization/ASTReader.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/FormatVariadic.h"
24 #include "llvm/Support/Path.h"
25 #include "llvm/Support/Threading.h"
27 #include "ClangHost.h"
28 #include "ClangModulesDeclVendor.h"
29 #include "ModuleDependencyCollector.h"
31 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
32 #include "lldb/Core/ModuleList.h"
33 #include "lldb/Core/Progress.h"
34 #include "lldb/Host/Host.h"
35 #include "lldb/Host/HostInfo.h"
36 #include "lldb/Symbol/CompileUnit.h"
37 #include "lldb/Symbol/SourceModule.h"
38 #include "lldb/Target/Target.h"
39 #include "lldb/Utility/FileSpec.h"
40 #include "lldb/Utility/LLDBAssert.h"
41 #include "lldb/Utility/LLDBLog.h"
42 #include "lldb/Utility/Log.h"
43 #include "lldb/Utility/StreamString.h"
48 using namespace lldb_private
;
51 /// Any Clang compiler requires a consumer for diagnostics. This one stores
52 /// them as strings so we can provide them to the user in case a module failed
54 class StoringDiagnosticConsumer
: public clang::DiagnosticConsumer
{
56 StoringDiagnosticConsumer();
58 void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel
,
59 const clang::Diagnostic
&info
) override
;
61 void ClearDiagnostics();
63 void DumpDiagnostics(Stream
&error_stream
);
65 void BeginSourceFile(const clang::LangOptions
&LangOpts
,
66 const clang::Preprocessor
*PP
= nullptr) override
;
67 void EndSourceFile() override
;
70 bool HandleModuleRemark(const clang::Diagnostic
&info
);
71 void SetCurrentModuleProgress(std::string module_name
);
73 typedef std::pair
<clang::DiagnosticsEngine::Level
, std::string
>
75 std::vector
<IDAndDiagnostic
> m_diagnostics
;
76 /// The DiagnosticPrinter used for creating the full diagnostic messages
77 /// that are stored in m_diagnostics.
78 std::shared_ptr
<clang::TextDiagnosticPrinter
> m_diag_printer
;
79 /// Output stream of m_diag_printer.
80 std::shared_ptr
<llvm::raw_string_ostream
> m_os
;
81 /// Output string filled by m_os. Will be reused for different diagnostics.
84 /// A Progress with explicitly managed lifetime.
85 std::unique_ptr
<Progress
> m_current_progress_up
;
86 std::vector
<std::string
> m_module_build_stack
;
89 /// The private implementation of our ClangModulesDeclVendor. Contains all the
90 /// Clang state required to load modules.
91 class ClangModulesDeclVendorImpl
: public ClangModulesDeclVendor
{
93 ClangModulesDeclVendorImpl(
94 llvm::IntrusiveRefCntPtr
<clang::DiagnosticsEngine
> diagnostics_engine
,
95 std::shared_ptr
<clang::CompilerInvocation
> compiler_invocation
,
96 std::unique_ptr
<clang::CompilerInstance
> compiler_instance
,
97 std::unique_ptr
<clang::Parser
> parser
);
99 ~ClangModulesDeclVendorImpl() override
= default;
101 bool AddModule(const SourceModule
&module
, ModuleVector
*exported_modules
,
102 Stream
&error_stream
) override
;
104 bool AddModulesForCompileUnit(CompileUnit
&cu
, ModuleVector
&exported_modules
,
105 Stream
&error_stream
) override
;
107 uint32_t FindDecls(ConstString name
, bool append
, uint32_t max_matches
,
108 std::vector
<CompilerDecl
> &decls
) override
;
111 const ModuleVector
&modules
,
112 std::function
<bool(llvm::StringRef
, llvm::StringRef
)> handler
) override
;
115 typedef llvm::DenseSet
<ModuleID
> ExportedModuleSet
;
116 void ReportModuleExportsHelper(ExportedModuleSet
&exports
,
117 clang::Module
*module
);
119 void ReportModuleExports(ModuleVector
&exports
, clang::Module
*module
);
121 clang::ModuleLoadResult
DoGetModule(clang::ModuleIdPath path
,
124 bool m_enabled
= false;
126 llvm::IntrusiveRefCntPtr
<clang::DiagnosticsEngine
> m_diagnostics_engine
;
127 std::shared_ptr
<clang::CompilerInvocation
> m_compiler_invocation
;
128 std::unique_ptr
<clang::CompilerInstance
> m_compiler_instance
;
129 std::unique_ptr
<clang::Parser
> m_parser
;
130 size_t m_source_location_index
=
131 0; // used to give name components fake SourceLocations
133 typedef std::vector
<ConstString
> ImportedModule
;
134 typedef std::map
<ImportedModule
, clang::Module
*> ImportedModuleMap
;
135 typedef llvm::DenseSet
<ModuleID
> ImportedModuleSet
;
136 ImportedModuleMap m_imported_modules
;
137 ImportedModuleSet m_user_imported_modules
;
138 // We assume that every ASTContext has an TypeSystemClang, so we also store
139 // a custom TypeSystemClang for our internal ASTContext.
140 std::shared_ptr
<TypeSystemClang
> m_ast_context
;
142 } // anonymous namespace
144 StoringDiagnosticConsumer::StoringDiagnosticConsumer() {
145 m_log
= GetLog(LLDBLog::Expressions
);
147 clang::DiagnosticOptions
*m_options
= new clang::DiagnosticOptions();
148 m_os
= std::make_shared
<llvm::raw_string_ostream
>(m_output
);
150 std::make_shared
<clang::TextDiagnosticPrinter
>(*m_os
, m_options
);
153 void StoringDiagnosticConsumer::HandleDiagnostic(
154 clang::DiagnosticsEngine::Level DiagLevel
, const clang::Diagnostic
&info
) {
155 if (HandleModuleRemark(info
))
158 // Print the diagnostic to m_output.
160 m_diag_printer
->HandleDiagnostic(DiagLevel
, info
);
163 // Store the diagnostic for later.
164 m_diagnostics
.push_back(IDAndDiagnostic(DiagLevel
, m_output
));
167 void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics
.clear(); }
169 void StoringDiagnosticConsumer::DumpDiagnostics(Stream
&error_stream
) {
170 for (IDAndDiagnostic
&diag
: m_diagnostics
) {
171 switch (diag
.first
) {
173 error_stream
.PutCString(diag
.second
);
174 error_stream
.PutChar('\n');
176 case clang::DiagnosticsEngine::Level::Ignored
:
182 void StoringDiagnosticConsumer::BeginSourceFile(
183 const clang::LangOptions
&LangOpts
, const clang::Preprocessor
*PP
) {
184 m_diag_printer
->BeginSourceFile(LangOpts
, PP
);
187 void StoringDiagnosticConsumer::EndSourceFile() {
188 m_current_progress_up
= nullptr;
189 m_diag_printer
->EndSourceFile();
192 bool StoringDiagnosticConsumer::HandleModuleRemark(
193 const clang::Diagnostic
&info
) {
194 Log
*log
= GetLog(LLDBLog::Expressions
);
195 switch (info
.getID()) {
196 case clang::diag::remark_module_build
: {
197 const auto &module_name
= info
.getArgStdStr(0);
198 SetCurrentModuleProgress(module_name
);
199 m_module_build_stack
.push_back(module_name
);
201 const auto &module_path
= info
.getArgStdStr(1);
202 LLDB_LOG(log
, "Building Clang module {0} as {1}", module_name
, module_path
);
205 case clang::diag::remark_module_build_done
: {
206 // The current module is done.
207 m_module_build_stack
.pop_back();
208 if (m_module_build_stack
.empty()) {
209 m_current_progress_up
= nullptr;
211 // When the just completed module began building, a module that depends on
212 // it ("module A") was effectively paused. Update the progress to re-show
213 // "module A" as continuing to be built.
214 const auto &resumed_module_name
= m_module_build_stack
.back();
215 SetCurrentModuleProgress(resumed_module_name
);
218 const auto &module_name
= info
.getArgStdStr(0);
219 LLDB_LOG(log
, "Finished building Clang module {0}", module_name
);
227 void StoringDiagnosticConsumer::SetCurrentModuleProgress(
228 std::string module_name
) {
229 if (!m_current_progress_up
)
230 m_current_progress_up
=
231 std::make_unique
<Progress
>("Building Clang modules");
233 m_current_progress_up
->Increment(1, std::move(module_name
));
236 ClangModulesDeclVendor::ClangModulesDeclVendor()
237 : ClangDeclVendor(eClangModuleDeclVendor
) {}
239 ClangModulesDeclVendor::~ClangModulesDeclVendor() = default;
241 ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
242 llvm::IntrusiveRefCntPtr
<clang::DiagnosticsEngine
> diagnostics_engine
,
243 std::shared_ptr
<clang::CompilerInvocation
> compiler_invocation
,
244 std::unique_ptr
<clang::CompilerInstance
> compiler_instance
,
245 std::unique_ptr
<clang::Parser
> parser
)
246 : m_diagnostics_engine(std::move(diagnostics_engine
)),
247 m_compiler_invocation(std::move(compiler_invocation
)),
248 m_compiler_instance(std::move(compiler_instance
)),
249 m_parser(std::move(parser
)) {
251 // Initialize our TypeSystemClang.
253 std::make_shared
<TypeSystemClang
>("ClangModulesDeclVendor ASTContext",
254 m_compiler_instance
->getASTContext());
257 void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
258 ExportedModuleSet
&exports
, clang::Module
*module
) {
259 if (exports
.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID
>(module
)))
262 exports
.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID
>(module
));
264 llvm::SmallVector
<clang::Module
*, 2> sub_exports
;
266 module
->getExportedModules(sub_exports
);
268 for (clang::Module
*module
: sub_exports
)
269 ReportModuleExportsHelper(exports
, module
);
272 void ClangModulesDeclVendorImpl::ReportModuleExports(
273 ClangModulesDeclVendor::ModuleVector
&exports
, clang::Module
*module
) {
274 ExportedModuleSet exports_set
;
276 ReportModuleExportsHelper(exports_set
, module
);
278 for (ModuleID module
: exports_set
)
279 exports
.push_back(module
);
282 bool ClangModulesDeclVendorImpl::AddModule(const SourceModule
&module
,
283 ModuleVector
*exported_modules
,
284 Stream
&error_stream
) {
287 if (m_compiler_instance
->hadModuleLoaderFatalFailure()) {
288 error_stream
.PutCString("error: Couldn't load a module because the module "
289 "loader is in a fatal state.\n");
293 // Check if we've already imported this module.
295 std::vector
<ConstString
> imported_module
;
297 for (ConstString path_component
: module
.path
)
298 imported_module
.push_back(path_component
);
301 ImportedModuleMap::iterator mi
= m_imported_modules
.find(imported_module
);
303 if (mi
!= m_imported_modules
.end()) {
304 if (exported_modules
)
305 ReportModuleExports(*exported_modules
, mi
->second
);
310 clang::HeaderSearch
&HS
=
311 m_compiler_instance
->getPreprocessor().getHeaderSearchInfo();
313 if (module
.search_path
) {
314 auto path_begin
= llvm::sys::path::begin(module
.search_path
.GetStringRef());
315 auto path_end
= llvm::sys::path::end(module
.search_path
.GetStringRef());
316 auto sysroot_begin
= llvm::sys::path::begin(module
.sysroot
.GetStringRef());
317 auto sysroot_end
= llvm::sys::path::end(module
.sysroot
.GetStringRef());
318 // FIXME: Use C++14 std::equal(it, it, it, it) variant once it's available.
319 bool is_system_module
= (std::distance(path_begin
, path_end
) >=
320 std::distance(sysroot_begin
, sysroot_end
)) &&
321 std::equal(sysroot_begin
, sysroot_end
, path_begin
);
322 // No need to inject search paths to modules in the sysroot.
323 if (!is_system_module
) {
325 error_stream
.Printf("error: No module map file in %s\n",
326 module
.search_path
.AsCString());
330 bool is_system
= true;
331 bool is_framework
= false;
332 auto dir
= HS
.getFileMgr().getOptionalDirectoryRef(
333 module
.search_path
.GetStringRef());
336 auto file
= HS
.lookupModuleMapFile(*dir
, is_framework
);
339 if (!HS
.loadModuleMapFile(*file
, is_system
))
343 if (!HS
.lookupModule(module
.path
.front().GetStringRef())) {
344 error_stream
.Printf("error: Header search couldn't locate module %s\n",
345 module
.path
.front().AsCString());
349 llvm::SmallVector
<std::pair
<clang::IdentifierInfo
*, clang::SourceLocation
>,
354 clang::SourceManager
&source_manager
=
355 m_compiler_instance
->getASTContext().getSourceManager();
357 for (ConstString path_component
: module
.path
) {
358 clang_path
.push_back(std::make_pair(
359 &m_compiler_instance
->getASTContext().Idents
.get(
360 path_component
.GetStringRef()),
361 source_manager
.getLocForStartOfFile(source_manager
.getMainFileID())
362 .getLocWithOffset(m_source_location_index
++)));
366 StoringDiagnosticConsumer
*diagnostic_consumer
=
367 static_cast<StoringDiagnosticConsumer
*>(
368 m_compiler_instance
->getDiagnostics().getClient());
370 diagnostic_consumer
->ClearDiagnostics();
372 clang::Module
*top_level_module
= DoGetModule(clang_path
.front(), false);
374 if (!top_level_module
) {
375 diagnostic_consumer
->DumpDiagnostics(error_stream
);
376 error_stream
.Printf("error: Couldn't load top-level module %s\n",
377 module
.path
.front().AsCString());
381 clang::Module
*submodule
= top_level_module
;
383 for (auto &component
: llvm::ArrayRef
<ConstString
>(module
.path
).drop_front()) {
384 submodule
= submodule
->findSubmodule(component
.GetStringRef());
386 diagnostic_consumer
->DumpDiagnostics(error_stream
);
387 error_stream
.Printf("error: Couldn't load submodule %s\n",
388 component
.GetCString());
393 clang::Module
*requested_module
= DoGetModule(clang_path
, true);
395 if (requested_module
!= nullptr) {
396 if (exported_modules
)
397 ReportModuleExports(*exported_modules
, requested_module
);
399 m_imported_modules
[imported_module
] = requested_module
;
409 bool ClangModulesDeclVendor::LanguageSupportsClangModules(
410 lldb::LanguageType language
) {
414 case lldb::LanguageType::eLanguageTypeC
:
415 case lldb::LanguageType::eLanguageTypeC11
:
416 case lldb::LanguageType::eLanguageTypeC89
:
417 case lldb::LanguageType::eLanguageTypeC99
:
418 case lldb::LanguageType::eLanguageTypeC_plus_plus
:
419 case lldb::LanguageType::eLanguageTypeC_plus_plus_03
:
420 case lldb::LanguageType::eLanguageTypeC_plus_plus_11
:
421 case lldb::LanguageType::eLanguageTypeC_plus_plus_14
:
422 case lldb::LanguageType::eLanguageTypeObjC
:
423 case lldb::LanguageType::eLanguageTypeObjC_plus_plus
:
428 bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
429 CompileUnit
&cu
, ClangModulesDeclVendor::ModuleVector
&exported_modules
,
430 Stream
&error_stream
) {
431 if (LanguageSupportsClangModules(cu
.GetLanguage())) {
432 for (auto &imported_module
: cu
.GetImportedModules())
433 if (!AddModule(imported_module
, &exported_modules
, error_stream
))
439 // ClangImporter::lookupValue
442 ClangModulesDeclVendorImpl::FindDecls(ConstString name
, bool append
,
443 uint32_t max_matches
,
444 std::vector
<CompilerDecl
> &decls
) {
451 clang::IdentifierInfo
&ident
=
452 m_compiler_instance
->getASTContext().Idents
.get(name
.GetStringRef());
454 clang::LookupResult
lookup_result(
455 m_compiler_instance
->getSema(), clang::DeclarationName(&ident
),
456 clang::SourceLocation(), clang::Sema::LookupOrdinaryName
);
458 m_compiler_instance
->getSema().LookupName(
460 m_compiler_instance
->getSema().getScopeForContext(
461 m_compiler_instance
->getASTContext().getTranslationUnitDecl()));
463 uint32_t num_matches
= 0;
465 for (clang::NamedDecl
*named_decl
: lookup_result
) {
466 if (num_matches
>= max_matches
)
469 decls
.push_back(m_ast_context
->GetCompilerDecl(named_decl
));
476 void ClangModulesDeclVendorImpl::ForEachMacro(
477 const ClangModulesDeclVendor::ModuleVector
&modules
,
478 std::function
<bool(llvm::StringRef
, llvm::StringRef
)> handler
) {
482 typedef std::map
<ModuleID
, ssize_t
> ModulePriorityMap
;
483 ModulePriorityMap module_priorities
;
485 ssize_t priority
= 0;
487 for (ModuleID module
: modules
)
488 module_priorities
[module
] = priority
++;
490 if (m_compiler_instance
->getPreprocessor().getExternalSource()) {
491 m_compiler_instance
->getPreprocessor()
493 ->ReadDefinedMacros();
496 for (clang::Preprocessor::macro_iterator
497 mi
= m_compiler_instance
->getPreprocessor().macro_begin(),
498 me
= m_compiler_instance
->getPreprocessor().macro_end();
500 const clang::IdentifierInfo
*ii
= nullptr;
503 if (clang::IdentifierInfoLookup
*lookup
=
504 m_compiler_instance
->getPreprocessor()
505 .getIdentifierTable()
506 .getExternalIdentifierLookup()) {
507 lookup
->get(mi
->first
->getName());
513 ssize_t found_priority
= -1;
514 clang::MacroInfo
*macro_info
= nullptr;
516 for (clang::ModuleMacro
*module_macro
:
517 m_compiler_instance
->getPreprocessor().getLeafModuleMacros(ii
)) {
518 clang::Module
*module
= module_macro
->getOwningModule();
521 ModulePriorityMap::iterator pi
=
522 module_priorities
.find(reinterpret_cast<ModuleID
>(module
));
524 if (pi
!= module_priorities
.end() && pi
->second
> found_priority
) {
525 macro_info
= module_macro
->getMacroInfo();
526 found_priority
= pi
->second
;
530 clang::Module
*top_level_module
= module
->getTopLevelModule();
532 if (top_level_module
!= module
) {
533 ModulePriorityMap::iterator pi
= module_priorities
.find(
534 reinterpret_cast<ModuleID
>(top_level_module
));
536 if ((pi
!= module_priorities
.end()) && pi
->second
> found_priority
) {
537 macro_info
= module_macro
->getMacroInfo();
538 found_priority
= pi
->second
;
544 std::string macro_expansion
= "#define ";
545 llvm::StringRef macro_identifier
= mi
->first
->getName();
546 macro_expansion
.append(macro_identifier
.str());
549 if (macro_info
->isFunctionLike()) {
550 macro_expansion
.append("(");
552 bool first_arg
= true;
554 for (auto pi
= macro_info
->param_begin(),
555 pe
= macro_info
->param_end();
558 macro_expansion
.append(", ");
562 macro_expansion
.append((*pi
)->getName().str());
565 if (macro_info
->isC99Varargs()) {
567 macro_expansion
.append("...");
569 macro_expansion
.append(", ...");
570 } else if (macro_info
->isGNUVarargs())
571 macro_expansion
.append("...");
573 macro_expansion
.append(")");
576 macro_expansion
.append(" ");
578 bool first_token
= true;
580 for (clang::MacroInfo::const_tokens_iterator
581 ti
= macro_info
->tokens_begin(),
582 te
= macro_info
->tokens_end();
585 macro_expansion
.append(" ");
589 if (ti
->isLiteral()) {
590 if (const char *literal_data
= ti
->getLiteralData()) {
591 std::string
token_str(literal_data
, ti
->getLength());
592 macro_expansion
.append(token_str
);
594 bool invalid
= false;
595 const char *literal_source
=
596 m_compiler_instance
->getSourceManager().getCharacterData(
597 ti
->getLocation(), &invalid
);
600 lldbassert(0 && "Unhandled token kind");
601 macro_expansion
.append("<unknown literal value>");
603 macro_expansion
.append(
604 std::string(literal_source
, ti
->getLength()));
607 } else if (const char *punctuator_spelling
=
608 clang::tok::getPunctuatorSpelling(ti
->getKind())) {
609 macro_expansion
.append(punctuator_spelling
);
610 } else if (const char *keyword_spelling
=
611 clang::tok::getKeywordSpelling(ti
->getKind())) {
612 macro_expansion
.append(keyword_spelling
);
614 switch (ti
->getKind()) {
615 case clang::tok::TokenKind::identifier
:
616 macro_expansion
.append(ti
->getIdentifierInfo()->getName().str());
618 case clang::tok::TokenKind::raw_identifier
:
619 macro_expansion
.append(ti
->getRawIdentifier().str());
622 macro_expansion
.append(ti
->getName());
628 if (handler(macro_identifier
, macro_expansion
)) {
636 clang::ModuleLoadResult
637 ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path
,
639 clang::Module::NameVisibilityKind visibility
=
640 make_visible
? clang::Module::AllVisible
: clang::Module::Hidden
;
642 const bool is_inclusion_directive
= false;
644 return m_compiler_instance
->loadModule(path
.front().second
, path
, visibility
,
645 is_inclusion_directive
);
648 static const char *ModuleImportBufferName
= "LLDBModulesMemoryBuffer";
650 lldb_private::ClangModulesDeclVendor
*
651 ClangModulesDeclVendor::Create(Target
&target
) {
652 // FIXME we should insure programmatically that the expression parser's
653 // compiler and the modules runtime's
654 // compiler are both initialized in the same way – preferably by the same
657 if (!target
.GetPlatform()->SupportsModules())
660 const ArchSpec
&arch
= target
.GetArchitecture();
662 std::vector
<std::string
> compiler_invocation_arguments
= {
665 "-fimplicit-module-maps",
670 arch
.GetTriple().str(),
671 "-fmodules-validate-system-headers",
672 "-Werror=non-modular-include-in-framework-module",
673 "-Xclang=-fincremental-extensions",
676 target
.GetPlatform()->AddClangModuleCompilationOptions(
677 &target
, compiler_invocation_arguments
);
679 compiler_invocation_arguments
.push_back(ModuleImportBufferName
);
681 // Add additional search paths with { "-I", path } or { "-F", path } here.
684 llvm::SmallString
<128> path
;
685 const auto &props
= ModuleList::GetGlobalModuleListProperties();
686 props
.GetClangModulesCachePath().GetPath(path
);
687 std::string
module_cache_argument("-fmodules-cache-path=");
688 module_cache_argument
.append(std::string(path
.str()));
689 compiler_invocation_arguments
.push_back(module_cache_argument
);
692 FileSpecList module_search_paths
= target
.GetClangModuleSearchPaths();
694 for (size_t spi
= 0, spe
= module_search_paths
.GetSize(); spi
< spe
; ++spi
) {
695 const FileSpec
&search_path
= module_search_paths
.GetFileSpecAtIndex(spi
);
697 std::string search_path_argument
= "-I";
698 search_path_argument
.append(search_path
.GetPath());
700 compiler_invocation_arguments
.push_back(search_path_argument
);
704 FileSpec clang_resource_dir
= GetClangResourceDir();
706 if (FileSystem::Instance().IsDirectory(clang_resource_dir
.GetPath())) {
707 compiler_invocation_arguments
.push_back("-resource-dir");
708 compiler_invocation_arguments
.push_back(clang_resource_dir
.GetPath());
712 std::vector
<const char *> compiler_invocation_argument_cstrs
;
713 compiler_invocation_argument_cstrs
.reserve(
714 compiler_invocation_arguments
.size());
715 for (const std::string
&arg
: compiler_invocation_arguments
)
716 compiler_invocation_argument_cstrs
.push_back(arg
.c_str());
718 auto diag_options_up
=
719 clang::CreateAndPopulateDiagOpts(compiler_invocation_argument_cstrs
);
720 llvm::IntrusiveRefCntPtr
<clang::DiagnosticsEngine
> diagnostics_engine
=
721 clang::CompilerInstance::createDiagnostics(diag_options_up
.release(),
722 new StoringDiagnosticConsumer
);
724 Log
*log
= GetLog(LLDBLog::Expressions
);
725 LLDB_LOG(log
, "ClangModulesDeclVendor's compiler flags {0:$[ ]}",
726 llvm::make_range(compiler_invocation_arguments
.begin(),
727 compiler_invocation_arguments
.end()));
729 clang::CreateInvocationOptions CIOpts
;
730 CIOpts
.Diags
= diagnostics_engine
;
731 std::shared_ptr
<clang::CompilerInvocation
> invocation
=
732 clang::createInvocation(compiler_invocation_argument_cstrs
,
738 std::unique_ptr
<llvm::MemoryBuffer
> source_buffer
=
739 llvm::MemoryBuffer::getMemBuffer(
740 "extern int __lldb __attribute__((unavailable));",
741 ModuleImportBufferName
);
743 invocation
->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName
,
744 source_buffer
.release());
746 std::unique_ptr
<clang::CompilerInstance
> instance(
747 new clang::CompilerInstance
);
749 // Make sure clang uses the same VFS as LLDB.
750 instance
->createFileManager(FileSystem::Instance().GetVirtualFileSystem());
751 instance
->setDiagnostics(diagnostics_engine
.get());
752 instance
->setInvocation(invocation
);
754 std::unique_ptr
<clang::FrontendAction
> action(new clang::SyntaxOnlyAction
);
756 instance
->setTarget(clang::TargetInfo::CreateTargetInfo(
757 *diagnostics_engine
, instance
->getInvocation().TargetOpts
));
759 if (!instance
->hasTarget())
762 instance
->getTarget().adjust(*diagnostics_engine
, instance
->getLangOpts());
764 if (!action
->BeginSourceFile(*instance
,
765 instance
->getFrontendOpts().Inputs
[0]))
768 instance
->createASTReader();
770 instance
->createSema(action
->getTranslationUnitKind(), nullptr);
772 const bool skipFunctionBodies
= false;
773 std::unique_ptr
<clang::Parser
> parser(new clang::Parser(
774 instance
->getPreprocessor(), instance
->getSema(), skipFunctionBodies
));
776 instance
->getPreprocessor().EnterMainSourceFile();
777 parser
->Initialize();
779 clang::Parser::DeclGroupPtrTy parsed
;
780 auto ImportState
= clang::Sema::ModuleImportState::NotACXX20Module
;
781 while (!parser
->ParseTopLevelDecl(parsed
, ImportState
))
784 return new ClangModulesDeclVendorImpl(std::move(diagnostics_engine
),
785 std::move(invocation
),
786 std::move(instance
), std::move(parser
));