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