1 //===-- ASTUtils.h ----------------------------------------------*- C++ -*-===// 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 #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H 10 #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H 11 12 #include "clang/Basic/ASTSourceDescriptor.h" 13 #include "clang/Sema/Lookup.h" 14 #include "clang/Sema/MultiplexExternalSemaSource.h" 15 #include "clang/Sema/Sema.h" 16 #include "clang/Sema/SemaConsumer.h" 17 #include "llvm/ADT/IntrusiveRefCntPtr.h" 18 #include "llvm/Support/Casting.h" 19 #include <optional> 20 21 namespace clang { 22 23 class Module; 24 25 } // namespace clang 26 27 namespace lldb_private { 28 29 /// Wraps an ExternalASTSource into an ExternalSemaSource. 30 /// 31 /// Assumes shared ownership of the underlying source. 32 class ExternalASTSourceWrapper : public clang::ExternalSemaSource { 33 llvm::IntrusiveRefCntPtr<ExternalASTSource> m_Source; 34 35 public: 36 explicit ExternalASTSourceWrapper(ExternalASTSource *Source) 37 : m_Source(Source) { 38 assert(m_Source && "Can't wrap nullptr ExternalASTSource"); 39 } 40 41 ~ExternalASTSourceWrapper() override; 42 43 clang::Decl *GetExternalDecl(clang::GlobalDeclID ID) override { 44 return m_Source->GetExternalDecl(ID); 45 } 46 47 clang::Selector GetExternalSelector(uint32_t ID) override { 48 return m_Source->GetExternalSelector(ID); 49 } 50 51 uint32_t GetNumExternalSelectors() override { 52 return m_Source->GetNumExternalSelectors(); 53 } 54 55 clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override { 56 return m_Source->GetExternalDeclStmt(Offset); 57 } 58 59 clang::CXXCtorInitializer ** 60 GetExternalCXXCtorInitializers(uint64_t Offset) override { 61 return m_Source->GetExternalCXXCtorInitializers(Offset); 62 } 63 64 clang::CXXBaseSpecifier * 65 GetExternalCXXBaseSpecifiers(uint64_t Offset) override { 66 return m_Source->GetExternalCXXBaseSpecifiers(Offset); 67 } 68 69 void updateOutOfDateIdentifier(const clang::IdentifierInfo &II) override { 70 m_Source->updateOutOfDateIdentifier(II); 71 } 72 73 bool FindExternalVisibleDeclsByName( 74 const clang::DeclContext *DC, clang::DeclarationName Name, 75 const clang::DeclContext *OriginalDC) override { 76 return m_Source->FindExternalVisibleDeclsByName(DC, Name, OriginalDC); 77 } 78 79 bool LoadExternalSpecializations(const clang::Decl *D, 80 bool OnlyPartial) override { 81 return m_Source->LoadExternalSpecializations(D, OnlyPartial); 82 } 83 84 bool LoadExternalSpecializations( 85 const clang::Decl *D, 86 llvm::ArrayRef<clang::TemplateArgument> TemplateArgs) override { 87 return m_Source->LoadExternalSpecializations(D, TemplateArgs); 88 } 89 90 void completeVisibleDeclsMap(const clang::DeclContext *DC) override { 91 m_Source->completeVisibleDeclsMap(DC); 92 } 93 94 clang::Module *getModule(unsigned ID) override { 95 return m_Source->getModule(ID); 96 } 97 98 std::optional<clang::ASTSourceDescriptor> 99 getSourceDescriptor(unsigned ID) override { 100 return m_Source->getSourceDescriptor(ID); 101 } 102 103 ExtKind hasExternalDefinitions(const clang::Decl *D) override { 104 return m_Source->hasExternalDefinitions(D); 105 } 106 107 void FindExternalLexicalDecls( 108 const clang::DeclContext *DC, 109 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, 110 llvm::SmallVectorImpl<clang::Decl *> &Result) override { 111 m_Source->FindExternalLexicalDecls(DC, IsKindWeWant, Result); 112 } 113 114 void 115 FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length, 116 llvm::SmallVectorImpl<clang::Decl *> &Decls) override { 117 m_Source->FindFileRegionDecls(File, Offset, Length, Decls); 118 } 119 120 void CompleteRedeclChain(const clang::Decl *D) override { 121 m_Source->CompleteRedeclChain(D); 122 } 123 124 void CompleteType(clang::TagDecl *Tag) override { 125 m_Source->CompleteType(Tag); 126 } 127 128 void CompleteType(clang::ObjCInterfaceDecl *Class) override { 129 m_Source->CompleteType(Class); 130 } 131 132 void ReadComments() override { m_Source->ReadComments(); } 133 134 void StartedDeserializing() override { m_Source->StartedDeserializing(); } 135 136 void FinishedDeserializing() override { m_Source->FinishedDeserializing(); } 137 138 void StartTranslationUnit(clang::ASTConsumer *Consumer) override { 139 m_Source->StartTranslationUnit(Consumer); 140 } 141 142 void PrintStats() override; 143 144 bool layoutRecordType( 145 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, 146 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, 147 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 148 &BaseOffsets, 149 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 150 &VirtualBaseOffsets) override { 151 return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets, 152 BaseOffsets, VirtualBaseOffsets); 153 } 154 155 /// This gets called when Sema is reconciling undefined but used decls. 156 /// For LLDB's use-case, we never provide Clang with function definitions, 157 /// instead we rely on linkage names and symbol resolution to call the 158 /// correct funcitons during JITting. So this implementation clears 159 /// any "undefined" FunctionDecls that Clang found while parsing. 160 /// 161 /// \param[in,out] Undefined A set of used decls for which Clang has not 162 /// been provided a definition with. 163 /// 164 void ReadUndefinedButUsed( 165 llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined) 166 override { 167 Undefined.remove_if([](auto const &decl_loc_pair) { 168 const clang::NamedDecl *ND = decl_loc_pair.first; 169 return llvm::isa_and_present<clang::FunctionDecl>(ND); 170 }); 171 } 172 }; 173 174 /// Wraps an ASTConsumer into an SemaConsumer. Doesn't take ownership of the 175 /// provided consumer. If the provided ASTConsumer is also a SemaConsumer, 176 /// the wrapper will also forward SemaConsumer functions. 177 class ASTConsumerForwarder : public clang::SemaConsumer { 178 clang::ASTConsumer *m_c; 179 clang::SemaConsumer *m_sc; 180 181 public: 182 ASTConsumerForwarder(clang::ASTConsumer *c) : m_c(c) { 183 m_sc = llvm::dyn_cast<clang::SemaConsumer>(m_c); 184 } 185 186 ~ASTConsumerForwarder() override; 187 188 void Initialize(clang::ASTContext &Context) override { 189 m_c->Initialize(Context); 190 } 191 192 bool HandleTopLevelDecl(clang::DeclGroupRef D) override { 193 return m_c->HandleTopLevelDecl(D); 194 } 195 196 void HandleInlineFunctionDefinition(clang::FunctionDecl *D) override { 197 m_c->HandleInlineFunctionDefinition(D); 198 } 199 200 void HandleInterestingDecl(clang::DeclGroupRef D) override { 201 m_c->HandleInterestingDecl(D); 202 } 203 204 void HandleTranslationUnit(clang::ASTContext &Ctx) override { 205 m_c->HandleTranslationUnit(Ctx); 206 } 207 208 void HandleTagDeclDefinition(clang::TagDecl *D) override { 209 m_c->HandleTagDeclDefinition(D); 210 } 211 212 void HandleTagDeclRequiredDefinition(const clang::TagDecl *D) override { 213 m_c->HandleTagDeclRequiredDefinition(D); 214 } 215 216 void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl *D) override { 217 m_c->HandleCXXImplicitFunctionInstantiation(D); 218 } 219 220 void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D) override { 221 m_c->HandleTopLevelDeclInObjCContainer(D); 222 } 223 224 void HandleImplicitImportDecl(clang::ImportDecl *D) override { 225 m_c->HandleImplicitImportDecl(D); 226 } 227 228 void CompleteTentativeDefinition(clang::VarDecl *D) override { 229 m_c->CompleteTentativeDefinition(D); 230 } 231 232 void AssignInheritanceModel(clang::CXXRecordDecl *RD) override { 233 m_c->AssignInheritanceModel(RD); 234 } 235 236 void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *D) override { 237 m_c->HandleCXXStaticMemberVarInstantiation(D); 238 } 239 240 void HandleVTable(clang::CXXRecordDecl *RD) override { 241 m_c->HandleVTable(RD); 242 } 243 244 clang::ASTMutationListener *GetASTMutationListener() override { 245 return m_c->GetASTMutationListener(); 246 } 247 248 clang::ASTDeserializationListener *GetASTDeserializationListener() override { 249 return m_c->GetASTDeserializationListener(); 250 } 251 252 void PrintStats() override; 253 254 void InitializeSema(clang::Sema &S) override { 255 if (m_sc) 256 m_sc->InitializeSema(S); 257 } 258 259 /// Inform the semantic consumer that Sema is no longer available. 260 void ForgetSema() override { 261 if (m_sc) 262 m_sc->ForgetSema(); 263 } 264 265 bool shouldSkipFunctionBody(clang::Decl *D) override { 266 return m_c->shouldSkipFunctionBody(D); 267 } 268 }; 269 270 /// A ExternalSemaSource multiplexer that prioritizes its sources. 271 /// 272 /// This ExternalSemaSource will forward all requests to its attached sources. 273 /// However, unlike a normal multiplexer it will not forward a request to all 274 /// sources, but instead give priority to certain sources. If a source with a 275 /// higher priority can fulfill a request, all sources with a lower priority 276 /// will not receive the request. 277 /// 278 /// This class is mostly use to multiplex between sources of different 279 /// 'quality', e.g. a C++ modules and debug information. The C++ module will 280 /// provide more accurate replies to the requests, but might not be able to 281 /// answer all requests. The debug information will be used as a fallback then 282 /// to provide information that is not in the C++ module. 283 class SemaSourceWithPriorities : public clang::ExternalSemaSource { 284 285 private: 286 /// The sources ordered in decreasing priority. 287 llvm::SmallVector<clang::ExternalSemaSource *, 2> Sources; 288 289 public: 290 /// Construct a SemaSourceWithPriorities with a 'high quality' source that 291 /// has the higher priority and a 'low quality' source that will be used 292 /// as a fallback. 293 /// 294 /// This class assumes shared ownership of the sources provided to it. 295 SemaSourceWithPriorities(clang::ExternalSemaSource *high_quality_source, 296 clang::ExternalSemaSource *low_quality_source) { 297 assert(high_quality_source); 298 assert(low_quality_source); 299 300 high_quality_source->Retain(); 301 low_quality_source->Retain(); 302 303 Sources.push_back(high_quality_source); 304 Sources.push_back(low_quality_source); 305 } 306 307 ~SemaSourceWithPriorities() override; 308 309 //===--------------------------------------------------------------------===// 310 // ExternalASTSource. 311 //===--------------------------------------------------------------------===// 312 313 clang::Decl *GetExternalDecl(clang::GlobalDeclID ID) override { 314 for (size_t i = 0; i < Sources.size(); ++i) 315 if (clang::Decl *Result = Sources[i]->GetExternalDecl(ID)) 316 return Result; 317 return nullptr; 318 } 319 320 bool LoadExternalSpecializations(const clang::Decl *D, 321 bool OnlyPartial) override { 322 bool newDeclFound = false; 323 for (size_t i = 0; i < Sources.size(); ++i) 324 newDeclFound |= Sources[i]->LoadExternalSpecializations(D, OnlyPartial); 325 return newDeclFound; 326 } 327 328 bool LoadExternalSpecializations( 329 const clang::Decl *D, 330 llvm::ArrayRef<clang::TemplateArgument> TemplateArgs) override { 331 bool newDeclFound = false; 332 for (size_t i = 0; i < Sources.size(); ++i) 333 newDeclFound |= Sources[i]->LoadExternalSpecializations(D, TemplateArgs); 334 return newDeclFound; 335 } 336 337 void CompleteRedeclChain(const clang::Decl *D) override { 338 for (size_t i = 0; i < Sources.size(); ++i) 339 Sources[i]->CompleteRedeclChain(D); 340 } 341 342 clang::Selector GetExternalSelector(uint32_t ID) override { 343 clang::Selector Sel; 344 for (size_t i = 0; i < Sources.size(); ++i) { 345 Sel = Sources[i]->GetExternalSelector(ID); 346 if (!Sel.isNull()) 347 return Sel; 348 } 349 return Sel; 350 } 351 352 uint32_t GetNumExternalSelectors() override { 353 for (size_t i = 0; i < Sources.size(); ++i) 354 if (uint32_t total = Sources[i]->GetNumExternalSelectors()) 355 return total; 356 return 0; 357 } 358 359 clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override { 360 for (size_t i = 0; i < Sources.size(); ++i) 361 if (clang::Stmt *Result = Sources[i]->GetExternalDeclStmt(Offset)) 362 return Result; 363 return nullptr; 364 } 365 366 clang::CXXBaseSpecifier * 367 GetExternalCXXBaseSpecifiers(uint64_t Offset) override { 368 for (size_t i = 0; i < Sources.size(); ++i) 369 if (clang::CXXBaseSpecifier *R = 370 Sources[i]->GetExternalCXXBaseSpecifiers(Offset)) 371 return R; 372 return nullptr; 373 } 374 375 clang::CXXCtorInitializer ** 376 GetExternalCXXCtorInitializers(uint64_t Offset) override { 377 for (auto *S : Sources) 378 if (auto *R = S->GetExternalCXXCtorInitializers(Offset)) 379 return R; 380 return nullptr; 381 } 382 383 ExtKind hasExternalDefinitions(const clang::Decl *D) override { 384 for (const auto &S : Sources) 385 if (auto EK = S->hasExternalDefinitions(D)) 386 if (EK != EK_ReplyHazy) 387 return EK; 388 return EK_ReplyHazy; 389 } 390 391 bool FindExternalVisibleDeclsByName( 392 const clang::DeclContext *DC, clang::DeclarationName Name, 393 const clang::DeclContext *OriginalDC) override { 394 for (size_t i = 0; i < Sources.size(); ++i) 395 if (Sources[i]->FindExternalVisibleDeclsByName(DC, Name, OriginalDC)) 396 return true; 397 return false; 398 } 399 400 void completeVisibleDeclsMap(const clang::DeclContext *DC) override { 401 // FIXME: Only one source should be able to complete the decls map. 402 for (size_t i = 0; i < Sources.size(); ++i) 403 Sources[i]->completeVisibleDeclsMap(DC); 404 } 405 406 void FindExternalLexicalDecls( 407 const clang::DeclContext *DC, 408 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, 409 llvm::SmallVectorImpl<clang::Decl *> &Result) override { 410 for (size_t i = 0; i < Sources.size(); ++i) { 411 Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result); 412 if (!Result.empty()) 413 return; 414 } 415 } 416 417 void 418 FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length, 419 llvm::SmallVectorImpl<clang::Decl *> &Decls) override { 420 for (size_t i = 0; i < Sources.size(); ++i) 421 Sources[i]->FindFileRegionDecls(File, Offset, Length, Decls); 422 } 423 424 void CompleteType(clang::TagDecl *Tag) override { 425 for (clang::ExternalSemaSource *S : Sources) { 426 S->CompleteType(Tag); 427 // Stop after the first source completed the type. 428 if (Tag->isCompleteDefinition()) 429 break; 430 } 431 } 432 433 void CompleteType(clang::ObjCInterfaceDecl *Class) override { 434 for (size_t i = 0; i < Sources.size(); ++i) 435 Sources[i]->CompleteType(Class); 436 } 437 438 void ReadComments() override { 439 for (size_t i = 0; i < Sources.size(); ++i) 440 Sources[i]->ReadComments(); 441 } 442 443 void StartedDeserializing() override { 444 for (size_t i = 0; i < Sources.size(); ++i) 445 Sources[i]->StartedDeserializing(); 446 } 447 448 void FinishedDeserializing() override { 449 for (size_t i = 0; i < Sources.size(); ++i) 450 Sources[i]->FinishedDeserializing(); 451 } 452 453 void StartTranslationUnit(clang::ASTConsumer *Consumer) override { 454 for (size_t i = 0; i < Sources.size(); ++i) 455 Sources[i]->StartTranslationUnit(Consumer); 456 } 457 458 void PrintStats() override; 459 460 clang::Module *getModule(unsigned ID) override { 461 for (size_t i = 0; i < Sources.size(); ++i) 462 if (auto M = Sources[i]->getModule(ID)) 463 return M; 464 return nullptr; 465 } 466 467 bool layoutRecordType( 468 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, 469 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, 470 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 471 &BaseOffsets, 472 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 473 &VirtualBaseOffsets) override { 474 for (size_t i = 0; i < Sources.size(); ++i) 475 if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets, 476 BaseOffsets, VirtualBaseOffsets)) 477 return true; 478 return false; 479 } 480 481 void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override { 482 for (auto &Source : Sources) 483 Source->getMemoryBufferSizes(sizes); 484 } 485 486 //===--------------------------------------------------------------------===// 487 // ExternalSemaSource. 488 //===--------------------------------------------------------------------===// 489 490 void InitializeSema(clang::Sema &S) override { 491 for (auto &Source : Sources) 492 Source->InitializeSema(S); 493 } 494 495 void ForgetSema() override { 496 for (auto &Source : Sources) 497 Source->ForgetSema(); 498 } 499 500 void ReadMethodPool(clang::Selector Sel) override { 501 for (auto &Source : Sources) 502 Source->ReadMethodPool(Sel); 503 } 504 505 void updateOutOfDateSelector(clang::Selector Sel) override { 506 for (auto &Source : Sources) 507 Source->updateOutOfDateSelector(Sel); 508 } 509 510 void ReadKnownNamespaces( 511 llvm::SmallVectorImpl<clang::NamespaceDecl *> &Namespaces) override { 512 for (auto &Source : Sources) 513 Source->ReadKnownNamespaces(Namespaces); 514 } 515 516 void ReadUndefinedButUsed( 517 llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined) 518 override { 519 for (auto &Source : Sources) 520 Source->ReadUndefinedButUsed(Undefined); 521 } 522 523 void ReadMismatchingDeleteExpressions( 524 llvm::MapVector<clang::FieldDecl *, 525 llvm::SmallVector<std::pair<clang::SourceLocation, bool>, 526 4>> &Exprs) override { 527 for (auto &Source : Sources) 528 Source->ReadMismatchingDeleteExpressions(Exprs); 529 } 530 531 bool LookupUnqualified(clang::LookupResult &R, clang::Scope *S) override { 532 for (auto &Source : Sources) { 533 Source->LookupUnqualified(R, S); 534 if (!R.empty()) 535 break; 536 } 537 538 return !R.empty(); 539 } 540 541 void ReadTentativeDefinitions( 542 llvm::SmallVectorImpl<clang::VarDecl *> &Defs) override { 543 for (auto &Source : Sources) 544 Source->ReadTentativeDefinitions(Defs); 545 } 546 547 void ReadUnusedFileScopedDecls( 548 llvm::SmallVectorImpl<const clang::DeclaratorDecl *> &Decls) override { 549 for (auto &Source : Sources) 550 Source->ReadUnusedFileScopedDecls(Decls); 551 } 552 553 void ReadDelegatingConstructors( 554 llvm::SmallVectorImpl<clang::CXXConstructorDecl *> &Decls) override { 555 for (auto &Source : Sources) 556 Source->ReadDelegatingConstructors(Decls); 557 } 558 559 void ReadExtVectorDecls( 560 llvm::SmallVectorImpl<clang::TypedefNameDecl *> &Decls) override { 561 for (auto &Source : Sources) 562 Source->ReadExtVectorDecls(Decls); 563 } 564 565 void ReadUnusedLocalTypedefNameCandidates( 566 llvm::SmallSetVector<const clang::TypedefNameDecl *, 4> &Decls) override { 567 for (auto &Source : Sources) 568 Source->ReadUnusedLocalTypedefNameCandidates(Decls); 569 } 570 571 void ReadReferencedSelectors( 572 llvm::SmallVectorImpl<std::pair<clang::Selector, clang::SourceLocation>> 573 &Sels) override { 574 for (auto &Source : Sources) 575 Source->ReadReferencedSelectors(Sels); 576 } 577 578 void ReadWeakUndeclaredIdentifiers( 579 llvm::SmallVectorImpl<std::pair<clang::IdentifierInfo *, clang::WeakInfo>> 580 &WI) override { 581 for (auto &Source : Sources) 582 Source->ReadWeakUndeclaredIdentifiers(WI); 583 } 584 585 void ReadUsedVTables( 586 llvm::SmallVectorImpl<clang::ExternalVTableUse> &VTables) override { 587 for (auto &Source : Sources) 588 Source->ReadUsedVTables(VTables); 589 } 590 591 void ReadPendingInstantiations( 592 llvm::SmallVectorImpl< 593 std::pair<clang::ValueDecl *, clang::SourceLocation>> &Pending) 594 override { 595 for (auto &Source : Sources) 596 Source->ReadPendingInstantiations(Pending); 597 } 598 599 void ReadLateParsedTemplates( 600 llvm::MapVector<const clang::FunctionDecl *, 601 std::unique_ptr<clang::LateParsedTemplate>> &LPTMap) 602 override { 603 for (auto &Source : Sources) 604 Source->ReadLateParsedTemplates(LPTMap); 605 } 606 607 clang::TypoCorrection 608 CorrectTypo(const clang::DeclarationNameInfo &Typo, int LookupKind, 609 clang::Scope *S, clang::CXXScopeSpec *SS, 610 clang::CorrectionCandidateCallback &CCC, 611 clang::DeclContext *MemberContext, bool EnteringContext, 612 const clang::ObjCObjectPointerType *OPT) override { 613 for (auto &Source : Sources) { 614 if (clang::TypoCorrection C = 615 Source->CorrectTypo(Typo, LookupKind, S, SS, CCC, 616 MemberContext, EnteringContext, OPT)) 617 return C; 618 } 619 return clang::TypoCorrection(); 620 } 621 622 bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc, 623 clang::QualType T) override { 624 for (auto &Source : Sources) { 625 if (Source->MaybeDiagnoseMissingCompleteType(Loc, T)) 626 return true; 627 } 628 return false; 629 } 630 }; 631 632 } // namespace lldb_private 633 #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H 634