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