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