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/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" 26 27 #include "ClangHost.h" 28 #include "ClangModulesDeclVendor.h" 29 #include "ModuleDependencyCollector.h" 30 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" 44 45 #include <memory> 46 #include <mutex> 47 48 using namespace lldb_private; 49 50 namespace { 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 53 /// to load. 54 class StoringDiagnosticConsumer : public clang::DiagnosticConsumer { 55 public: 56 StoringDiagnosticConsumer(); 57 58 void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, 59 const clang::Diagnostic &info) override; 60 61 void ClearDiagnostics(); 62 63 void DumpDiagnostics(Stream &error_stream); 64 65 void BeginSourceFile(const clang::LangOptions &LangOpts, 66 const clang::Preprocessor *PP = nullptr) override; 67 void EndSourceFile() override; 68 69 private: 70 bool HandleModuleRemark(const clang::Diagnostic &info); 71 void SetCurrentModuleProgress(std::string module_name); 72 73 typedef std::pair<clang::DiagnosticsEngine::Level, std::string> 74 IDAndDiagnostic; 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. 82 std::string m_output; 83 Log *m_log; 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; 87 }; 88 89 /// The private implementation of our ClangModulesDeclVendor. Contains all the 90 /// Clang state required to load modules. 91 class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor { 92 public: 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); 98 99 ~ClangModulesDeclVendorImpl() override = default; 100 101 bool AddModule(const SourceModule &module, ModuleVector *exported_modules, 102 Stream &error_stream) override; 103 104 bool AddModulesForCompileUnit(CompileUnit &cu, ModuleVector &exported_modules, 105 Stream &error_stream) override; 106 107 uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, 108 std::vector<CompilerDecl> &decls) override; 109 110 void ForEachMacro( 111 const ModuleVector &modules, 112 std::function<bool(llvm::StringRef, llvm::StringRef)> handler) override; 113 114 private: 115 typedef llvm::DenseSet<ModuleID> ExportedModuleSet; 116 void ReportModuleExportsHelper(ExportedModuleSet &exports, 117 clang::Module *module); 118 119 void ReportModuleExports(ModuleVector &exports, clang::Module *module); 120 121 clang::ModuleLoadResult DoGetModule(clang::ModuleIdPath path, 122 bool make_visible); 123 124 bool m_enabled = false; 125 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 132 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; 141 }; 142 } // anonymous namespace 143 144 StoringDiagnosticConsumer::StoringDiagnosticConsumer() { 145 m_log = GetLog(LLDBLog::Expressions); 146 147 clang::DiagnosticOptions *m_options = new clang::DiagnosticOptions(); 148 m_os = std::make_shared<llvm::raw_string_ostream>(m_output); 149 m_diag_printer = 150 std::make_shared<clang::TextDiagnosticPrinter>(*m_os, m_options); 151 } 152 153 void StoringDiagnosticConsumer::HandleDiagnostic( 154 clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) { 155 if (HandleModuleRemark(info)) 156 return; 157 158 // Print the diagnostic to m_output. 159 m_output.clear(); 160 m_diag_printer->HandleDiagnostic(DiagLevel, info); 161 m_os->flush(); 162 163 // Store the diagnostic for later. 164 m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, m_output)); 165 } 166 167 void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); } 168 169 void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) { 170 for (IDAndDiagnostic &diag : m_diagnostics) { 171 switch (diag.first) { 172 default: 173 error_stream.PutCString(diag.second); 174 error_stream.PutChar('\n'); 175 break; 176 case clang::DiagnosticsEngine::Level::Ignored: 177 break; 178 } 179 } 180 } 181 182 void StoringDiagnosticConsumer::BeginSourceFile( 183 const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) { 184 m_diag_printer->BeginSourceFile(LangOpts, PP); 185 } 186 187 void StoringDiagnosticConsumer::EndSourceFile() { 188 m_current_progress_up = nullptr; 189 m_diag_printer->EndSourceFile(); 190 } 191 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); 200 201 const auto &module_path = info.getArgStdStr(1); 202 LLDB_LOG(log, "Building Clang module {0} as {1}", module_name, module_path); 203 return true; 204 } 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; 210 } else { 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); 216 } 217 218 const auto &module_name = info.getArgStdStr(0); 219 LLDB_LOG(log, "Finished building Clang module {0}", module_name); 220 return true; 221 } 222 default: 223 return false; 224 } 225 } 226 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"); 232 233 m_current_progress_up->Increment(1, std::move(module_name)); 234 } 235 236 ClangModulesDeclVendor::ClangModulesDeclVendor() 237 : ClangDeclVendor(eClangModuleDeclVendor) {} 238 239 ClangModulesDeclVendor::~ClangModulesDeclVendor() = default; 240 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)) { 250 251 // Initialize our TypeSystemClang. 252 m_ast_context = 253 std::make_shared<TypeSystemClang>("ClangModulesDeclVendor ASTContext", 254 m_compiler_instance->getASTContext()); 255 } 256 257 void ClangModulesDeclVendorImpl::ReportModuleExportsHelper( 258 ExportedModuleSet &exports, clang::Module *module) { 259 if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module))) 260 return; 261 262 exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)); 263 264 llvm::SmallVector<clang::Module *, 2> sub_exports; 265 266 module->getExportedModules(sub_exports); 267 268 for (clang::Module *module : sub_exports) 269 ReportModuleExportsHelper(exports, module); 270 } 271 272 void ClangModulesDeclVendorImpl::ReportModuleExports( 273 ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) { 274 ExportedModuleSet exports_set; 275 276 ReportModuleExportsHelper(exports_set, module); 277 278 for (ModuleID module : exports_set) 279 exports.push_back(module); 280 } 281 282 bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module, 283 ModuleVector *exported_modules, 284 Stream &error_stream) { 285 // Fail early. 286 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"); 290 return false; 291 } 292 293 // Check if we've already imported this module. 294 295 std::vector<ConstString> imported_module; 296 297 for (ConstString path_component : module.path) 298 imported_module.push_back(path_component); 299 300 { 301 ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module); 302 303 if (mi != m_imported_modules.end()) { 304 if (exported_modules) 305 ReportModuleExports(*exported_modules, mi->second); 306 return true; 307 } 308 } 309 310 clang::HeaderSearch &HS = 311 m_compiler_instance->getPreprocessor().getHeaderSearchInfo(); 312 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) { 324 auto error = [&]() { 325 error_stream.Printf("error: No module map file in %s\n", 326 module.search_path.AsCString()); 327 return false; 328 }; 329 330 bool is_system = true; 331 bool is_framework = false; 332 auto dir = HS.getFileMgr().getOptionalDirectoryRef( 333 module.search_path.GetStringRef()); 334 if (!dir) 335 return error(); 336 auto file = HS.lookupModuleMapFile(*dir, is_framework); 337 if (!file) 338 return error(); 339 if (!HS.loadModuleMapFile(*file, is_system)) 340 return error(); 341 } 342 } 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()); 346 return false; 347 } 348 349 llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>, 350 4> 351 clang_path; 352 353 { 354 clang::SourceManager &source_manager = 355 m_compiler_instance->getASTContext().getSourceManager(); 356 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++))); 363 } 364 } 365 366 StoringDiagnosticConsumer *diagnostic_consumer = 367 static_cast<StoringDiagnosticConsumer *>( 368 m_compiler_instance->getDiagnostics().getClient()); 369 370 diagnostic_consumer->ClearDiagnostics(); 371 372 clang::Module *top_level_module = DoGetModule(clang_path.front(), false); 373 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()); 378 return false; 379 } 380 381 clang::Module *submodule = top_level_module; 382 383 for (auto &component : llvm::ArrayRef<ConstString>(module.path).drop_front()) { 384 submodule = submodule->findSubmodule(component.GetStringRef()); 385 if (!submodule) { 386 diagnostic_consumer->DumpDiagnostics(error_stream); 387 error_stream.Printf("error: Couldn't load submodule %s\n", 388 component.GetCString()); 389 return false; 390 } 391 } 392 393 clang::Module *requested_module = DoGetModule(clang_path, true); 394 395 if (requested_module != nullptr) { 396 if (exported_modules) 397 ReportModuleExports(*exported_modules, requested_module); 398 399 m_imported_modules[imported_module] = requested_module; 400 401 m_enabled = true; 402 403 return true; 404 } 405 406 return false; 407 } 408 409 bool ClangModulesDeclVendor::LanguageSupportsClangModules( 410 lldb::LanguageType language) { 411 switch (language) { 412 default: 413 return false; 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: 424 return true; 425 } 426 } 427 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)) 434 return false; 435 } 436 return true; 437 } 438 439 // ClangImporter::lookupValue 440 441 uint32_t 442 ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append, 443 uint32_t max_matches, 444 std::vector<CompilerDecl> &decls) { 445 if (!m_enabled) 446 return 0; 447 448 if (!append) 449 decls.clear(); 450 451 clang::IdentifierInfo &ident = 452 m_compiler_instance->getASTContext().Idents.get(name.GetStringRef()); 453 454 clang::LookupResult lookup_result( 455 m_compiler_instance->getSema(), clang::DeclarationName(&ident), 456 clang::SourceLocation(), clang::Sema::LookupOrdinaryName); 457 458 m_compiler_instance->getSema().LookupName( 459 lookup_result, 460 m_compiler_instance->getSema().getScopeForContext( 461 m_compiler_instance->getASTContext().getTranslationUnitDecl())); 462 463 uint32_t num_matches = 0; 464 465 for (clang::NamedDecl *named_decl : lookup_result) { 466 if (num_matches >= max_matches) 467 return num_matches; 468 469 decls.push_back(m_ast_context->GetCompilerDecl(named_decl)); 470 ++num_matches; 471 } 472 473 return num_matches; 474 } 475 476 void ClangModulesDeclVendorImpl::ForEachMacro( 477 const ClangModulesDeclVendor::ModuleVector &modules, 478 std::function<bool(llvm::StringRef, llvm::StringRef)> handler) { 479 if (!m_enabled) 480 return; 481 482 typedef std::map<ModuleID, ssize_t> ModulePriorityMap; 483 ModulePriorityMap module_priorities; 484 485 ssize_t priority = 0; 486 487 for (ModuleID module : modules) 488 module_priorities[module] = priority++; 489 490 if (m_compiler_instance->getPreprocessor().getExternalSource()) { 491 m_compiler_instance->getPreprocessor() 492 .getExternalSource() 493 ->ReadDefinedMacros(); 494 } 495 496 for (clang::Preprocessor::macro_iterator 497 mi = m_compiler_instance->getPreprocessor().macro_begin(), 498 me = m_compiler_instance->getPreprocessor().macro_end(); 499 mi != me; ++mi) { 500 const clang::IdentifierInfo *ii = nullptr; 501 502 { 503 if (clang::IdentifierInfoLookup *lookup = 504 m_compiler_instance->getPreprocessor() 505 .getIdentifierTable() 506 .getExternalIdentifierLookup()) { 507 lookup->get(mi->first->getName()); 508 } 509 if (!ii) 510 ii = mi->first; 511 } 512 513 ssize_t found_priority = -1; 514 clang::MacroInfo *macro_info = nullptr; 515 516 for (clang::ModuleMacro *module_macro : 517 m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) { 518 clang::Module *module = module_macro->getOwningModule(); 519 520 { 521 ModulePriorityMap::iterator pi = 522 module_priorities.find(reinterpret_cast<ModuleID>(module)); 523 524 if (pi != module_priorities.end() && pi->second > found_priority) { 525 macro_info = module_macro->getMacroInfo(); 526 found_priority = pi->second; 527 } 528 } 529 530 clang::Module *top_level_module = module->getTopLevelModule(); 531 532 if (top_level_module != module) { 533 ModulePriorityMap::iterator pi = module_priorities.find( 534 reinterpret_cast<ModuleID>(top_level_module)); 535 536 if ((pi != module_priorities.end()) && pi->second > found_priority) { 537 macro_info = module_macro->getMacroInfo(); 538 found_priority = pi->second; 539 } 540 } 541 } 542 543 if (macro_info) { 544 std::string macro_expansion = "#define "; 545 llvm::StringRef macro_identifier = mi->first->getName(); 546 macro_expansion.append(macro_identifier.str()); 547 548 { 549 if (macro_info->isFunctionLike()) { 550 macro_expansion.append("("); 551 552 bool first_arg = true; 553 554 for (auto pi = macro_info->param_begin(), 555 pe = macro_info->param_end(); 556 pi != pe; ++pi) { 557 if (!first_arg) 558 macro_expansion.append(", "); 559 else 560 first_arg = false; 561 562 macro_expansion.append((*pi)->getName().str()); 563 } 564 565 if (macro_info->isC99Varargs()) { 566 if (first_arg) 567 macro_expansion.append("..."); 568 else 569 macro_expansion.append(", ..."); 570 } else if (macro_info->isGNUVarargs()) 571 macro_expansion.append("..."); 572 573 macro_expansion.append(")"); 574 } 575 576 macro_expansion.append(" "); 577 578 bool first_token = true; 579 580 for (clang::MacroInfo::const_tokens_iterator 581 ti = macro_info->tokens_begin(), 582 te = macro_info->tokens_end(); 583 ti != te; ++ti) { 584 if (!first_token) 585 macro_expansion.append(" "); 586 else 587 first_token = false; 588 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); 593 } else { 594 bool invalid = false; 595 const char *literal_source = 596 m_compiler_instance->getSourceManager().getCharacterData( 597 ti->getLocation(), &invalid); 598 599 if (invalid) { 600 lldbassert(0 && "Unhandled token kind"); 601 macro_expansion.append("<unknown literal value>"); 602 } else { 603 macro_expansion.append( 604 std::string(literal_source, ti->getLength())); 605 } 606 } 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); 613 } else { 614 switch (ti->getKind()) { 615 case clang::tok::TokenKind::identifier: 616 macro_expansion.append(ti->getIdentifierInfo()->getName().str()); 617 break; 618 case clang::tok::TokenKind::raw_identifier: 619 macro_expansion.append(ti->getRawIdentifier().str()); 620 break; 621 default: 622 macro_expansion.append(ti->getName()); 623 break; 624 } 625 } 626 } 627 628 if (handler(macro_identifier, macro_expansion)) { 629 return; 630 } 631 } 632 } 633 } 634 } 635 636 clang::ModuleLoadResult 637 ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, 638 bool make_visible) { 639 clang::Module::NameVisibilityKind visibility = 640 make_visible ? clang::Module::AllVisible : clang::Module::Hidden; 641 642 const bool is_inclusion_directive = false; 643 644 return m_compiler_instance->loadModule(path.front().second, path, visibility, 645 is_inclusion_directive); 646 } 647 648 static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; 649 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 655 // code. 656 657 if (!target.GetPlatform()->SupportsModules()) 658 return nullptr; 659 660 const ArchSpec &arch = target.GetArchitecture(); 661 662 std::vector<std::string> compiler_invocation_arguments = { 663 "clang", 664 "-fmodules", 665 "-fimplicit-module-maps", 666 "-fcxx-modules", 667 "-fsyntax-only", 668 "-femit-all-decls", 669 "-target", 670 arch.GetTriple().str(), 671 "-fmodules-validate-system-headers", 672 "-Werror=non-modular-include-in-framework-module", 673 "-Xclang=-fincremental-extensions", 674 "-Rmodule-build"}; 675 676 target.GetPlatform()->AddClangModuleCompilationOptions( 677 &target, compiler_invocation_arguments); 678 679 compiler_invocation_arguments.push_back(ModuleImportBufferName); 680 681 // Add additional search paths with { "-I", path } or { "-F", path } here. 682 683 { 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); 690 } 691 692 FileSpecList module_search_paths = target.GetClangModuleSearchPaths(); 693 694 for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) { 695 const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi); 696 697 std::string search_path_argument = "-I"; 698 search_path_argument.append(search_path.GetPath()); 699 700 compiler_invocation_arguments.push_back(search_path_argument); 701 } 702 703 { 704 FileSpec clang_resource_dir = GetClangResourceDir(); 705 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()); 709 } 710 } 711 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()); 717 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); 723 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())); 728 729 clang::CreateInvocationOptions CIOpts; 730 CIOpts.Diags = diagnostics_engine; 731 std::shared_ptr<clang::CompilerInvocation> invocation = 732 clang::createInvocation(compiler_invocation_argument_cstrs, 733 std::move(CIOpts)); 734 735 if (!invocation) 736 return nullptr; 737 738 std::unique_ptr<llvm::MemoryBuffer> source_buffer = 739 llvm::MemoryBuffer::getMemBuffer( 740 "extern int __lldb __attribute__((unavailable));", 741 ModuleImportBufferName); 742 743 invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, 744 source_buffer.release()); 745 746 std::unique_ptr<clang::CompilerInstance> instance( 747 new clang::CompilerInstance); 748 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); 753 754 std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction); 755 756 instance->setTarget(clang::TargetInfo::CreateTargetInfo( 757 *diagnostics_engine, instance->getInvocation().TargetOpts)); 758 759 if (!instance->hasTarget()) 760 return nullptr; 761 762 instance->getTarget().adjust(*diagnostics_engine, instance->getLangOpts()); 763 764 if (!action->BeginSourceFile(*instance, 765 instance->getFrontendOpts().Inputs[0])) 766 return nullptr; 767 768 instance->createASTReader(); 769 770 instance->createSema(action->getTranslationUnitKind(), nullptr); 771 772 const bool skipFunctionBodies = false; 773 std::unique_ptr<clang::Parser> parser(new clang::Parser( 774 instance->getPreprocessor(), instance->getSema(), skipFunctionBodies)); 775 776 instance->getPreprocessor().EnterMainSourceFile(); 777 parser->Initialize(); 778 779 clang::Parser::DeclGroupPtrTy parsed; 780 auto ImportState = clang::Sema::ModuleImportState::NotACXX20Module; 781 while (!parser->ParseTopLevelDecl(parsed, ImportState)) 782 ; 783 784 return new ClangModulesDeclVendorImpl(std::move(diagnostics_engine), 785 std::move(invocation), 786 std::move(instance), std::move(parser)); 787 } 788