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