brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.3 KiB · 61ca63c Raw
634 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H10#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H11 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 21namespace clang {22 23class Module;24 25} // namespace clang26 27namespace lldb_private {28 29/// Wraps an ExternalASTSource into an ExternalSemaSource.30///31/// Assumes shared ownership of the underlying source.32class ExternalASTSourceWrapper : public clang::ExternalSemaSource {33  llvm::IntrusiveRefCntPtr<ExternalASTSource> m_Source;34 35public:36  explicit ExternalASTSourceWrapper(37      llvm::IntrusiveRefCntPtr<ExternalASTSource> Source)38      : m_Source(std::move(Source)) {39    assert(m_Source && "Can't wrap nullptr ExternalASTSource");40  }41 42  ~ExternalASTSourceWrapper() override;43 44  clang::Decl *GetExternalDecl(clang::GlobalDeclID ID) override {45    return m_Source->GetExternalDecl(ID);46  }47 48  clang::Selector GetExternalSelector(uint32_t ID) override {49    return m_Source->GetExternalSelector(ID);50  }51 52  uint32_t GetNumExternalSelectors() override {53    return m_Source->GetNumExternalSelectors();54  }55 56  clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {57    return m_Source->GetExternalDeclStmt(Offset);58  }59 60  clang::CXXCtorInitializer **61  GetExternalCXXCtorInitializers(uint64_t Offset) override {62    return m_Source->GetExternalCXXCtorInitializers(Offset);63  }64 65  clang::CXXBaseSpecifier *66  GetExternalCXXBaseSpecifiers(uint64_t Offset) override {67    return m_Source->GetExternalCXXBaseSpecifiers(Offset);68  }69 70  void updateOutOfDateIdentifier(const clang::IdentifierInfo &II) override {71    m_Source->updateOutOfDateIdentifier(II);72  }73 74  bool FindExternalVisibleDeclsByName(75      const clang::DeclContext *DC, clang::DeclarationName Name,76      const clang::DeclContext *OriginalDC) override {77    return m_Source->FindExternalVisibleDeclsByName(DC, Name, OriginalDC);78  }79 80  bool LoadExternalSpecializations(const clang::Decl *D,81                                   bool OnlyPartial) override {82    return m_Source->LoadExternalSpecializations(D, OnlyPartial);83  }84 85  bool LoadExternalSpecializations(86      const clang::Decl *D,87      llvm::ArrayRef<clang::TemplateArgument> TemplateArgs) override {88    return m_Source->LoadExternalSpecializations(D, TemplateArgs);89  }90 91  void completeVisibleDeclsMap(const clang::DeclContext *DC) override {92    m_Source->completeVisibleDeclsMap(DC);93  }94 95  clang::Module *getModule(unsigned ID) override {96    return m_Source->getModule(ID);97  }98 99  std::optional<clang::ASTSourceDescriptor>100  getSourceDescriptor(unsigned ID) override {101    return m_Source->getSourceDescriptor(ID);102  }103 104  ExtKind hasExternalDefinitions(const clang::Decl *D) override {105    return m_Source->hasExternalDefinitions(D);106  }107 108  void FindExternalLexicalDecls(109      const clang::DeclContext *DC,110      llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,111      llvm::SmallVectorImpl<clang::Decl *> &Result) override {112    m_Source->FindExternalLexicalDecls(DC, IsKindWeWant, Result);113  }114 115  void116  FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,117                      llvm::SmallVectorImpl<clang::Decl *> &Decls) override {118    m_Source->FindFileRegionDecls(File, Offset, Length, Decls);119  }120 121  void CompleteRedeclChain(const clang::Decl *D) override {122    m_Source->CompleteRedeclChain(D);123  }124 125  void CompleteType(clang::TagDecl *Tag) override {126    m_Source->CompleteType(Tag);127  }128 129  void CompleteType(clang::ObjCInterfaceDecl *Class) override {130    m_Source->CompleteType(Class);131  }132 133  void ReadComments() override { m_Source->ReadComments(); }134 135  void StartedDeserializing() override { m_Source->StartedDeserializing(); }136 137  void FinishedDeserializing() override { m_Source->FinishedDeserializing(); }138 139  void StartTranslationUnit(clang::ASTConsumer *Consumer) override {140    m_Source->StartTranslationUnit(Consumer);141  }142 143  void PrintStats() override;144 145  bool layoutRecordType(146      const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,147      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,148      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>149          &BaseOffsets,150      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>151          &VirtualBaseOffsets) override {152    return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets,153                                      BaseOffsets, VirtualBaseOffsets);154  }155 156  /// This gets called when Sema is reconciling undefined but used decls.157  /// For LLDB's use-case, we never provide Clang with function definitions,158  /// instead we rely on linkage names and symbol resolution to call the159  /// correct funcitons during JITting. So this implementation clears160  /// any "undefined" FunctionDecls that Clang found while parsing.161  ///162  /// \param[in,out] Undefined A set of used decls for which Clang has not163  ///                          been provided a definition with.164  ///165  void ReadUndefinedButUsed(166      llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined)167      override {168    Undefined.remove_if([](auto const &decl_loc_pair) {169      const clang::NamedDecl *ND = decl_loc_pair.first;170      return llvm::isa_and_present<clang::FunctionDecl>(ND);171    });172  }173};174 175/// Wraps an ASTConsumer into an SemaConsumer. Doesn't take ownership of the176/// provided consumer. If the provided ASTConsumer is also a SemaConsumer,177/// the wrapper will also forward SemaConsumer functions.178class ASTConsumerForwarder : public clang::SemaConsumer {179  clang::ASTConsumer *m_c;180  clang::SemaConsumer *m_sc;181 182public:183  ASTConsumerForwarder(clang::ASTConsumer *c) : m_c(c) {184    m_sc = llvm::dyn_cast<clang::SemaConsumer>(m_c);185  }186 187  ~ASTConsumerForwarder() override;188 189  void Initialize(clang::ASTContext &Context) override {190    m_c->Initialize(Context);191  }192 193  bool HandleTopLevelDecl(clang::DeclGroupRef D) override {194    return m_c->HandleTopLevelDecl(D);195  }196 197  void HandleInlineFunctionDefinition(clang::FunctionDecl *D) override {198    m_c->HandleInlineFunctionDefinition(D);199  }200 201  void HandleInterestingDecl(clang::DeclGroupRef D) override {202    m_c->HandleInterestingDecl(D);203  }204 205  void HandleTranslationUnit(clang::ASTContext &Ctx) override {206    m_c->HandleTranslationUnit(Ctx);207  }208 209  void HandleTagDeclDefinition(clang::TagDecl *D) override {210    m_c->HandleTagDeclDefinition(D);211  }212 213  void HandleTagDeclRequiredDefinition(const clang::TagDecl *D) override {214    m_c->HandleTagDeclRequiredDefinition(D);215  }216 217  void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl *D) override {218    m_c->HandleCXXImplicitFunctionInstantiation(D);219  }220 221  void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D) override {222    m_c->HandleTopLevelDeclInObjCContainer(D);223  }224 225  void HandleImplicitImportDecl(clang::ImportDecl *D) override {226    m_c->HandleImplicitImportDecl(D);227  }228 229  void CompleteTentativeDefinition(clang::VarDecl *D) override {230    m_c->CompleteTentativeDefinition(D);231  }232 233  void AssignInheritanceModel(clang::CXXRecordDecl *RD) override {234    m_c->AssignInheritanceModel(RD);235  }236 237  void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *D) override {238    m_c->HandleCXXStaticMemberVarInstantiation(D);239  }240 241  void HandleVTable(clang::CXXRecordDecl *RD) override {242    m_c->HandleVTable(RD);243  }244 245  clang::ASTMutationListener *GetASTMutationListener() override {246    return m_c->GetASTMutationListener();247  }248 249  clang::ASTDeserializationListener *GetASTDeserializationListener() override {250    return m_c->GetASTDeserializationListener();251  }252 253  void PrintStats() override;254 255  void InitializeSema(clang::Sema &S) override {256    if (m_sc)257      m_sc->InitializeSema(S);258  }259 260  /// Inform the semantic consumer that Sema is no longer available.261  void ForgetSema() override {262    if (m_sc)263      m_sc->ForgetSema();264  }265 266  bool shouldSkipFunctionBody(clang::Decl *D) override {267    return m_c->shouldSkipFunctionBody(D);268  }269};270 271/// A ExternalSemaSource multiplexer that prioritizes its sources.272///273/// This ExternalSemaSource will forward all requests to its attached sources.274/// However, unlike a normal multiplexer it will not forward a request to all275/// sources, but instead give priority to certain sources. If a source with a276/// higher priority can fulfill a request, all sources with a lower priority277/// will not receive the request.278///279/// This class is mostly use to multiplex between sources of different280/// 'quality', e.g. a C++ modules and debug information. The C++ module will281/// provide more accurate replies to the requests, but might not be able to282/// answer all requests. The debug information will be used as a fallback then283/// to provide information that is not in the C++ module.284class SemaSourceWithPriorities : public clang::ExternalSemaSource {285 286private:287  /// The sources ordered in decreasing priority.288  llvm::SmallVector<llvm::IntrusiveRefCntPtr<clang::ExternalSemaSource>, 2>289      Sources;290 291public:292  /// Construct a SemaSourceWithPriorities with a 'high quality' source that293  /// has the higher priority and a 'low quality' source that will be used294  /// as a fallback.295  ///296  /// This class assumes shared ownership of the sources provided to it.297  SemaSourceWithPriorities(298      llvm::IntrusiveRefCntPtr<clang::ExternalSemaSource> high_quality_source,299      llvm::IntrusiveRefCntPtr<clang::ExternalSemaSource> low_quality_source) {300    assert(high_quality_source);301    assert(low_quality_source);302 303    Sources.push_back(std::move(high_quality_source));304    Sources.push_back(std::move(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 (const 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  void418  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 (const auto &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::TypoCorrection608  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_private633#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H634