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