Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
39654 views
//===-- ASTUtils.h ----------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H9#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H1011#include "clang/Basic/ASTSourceDescriptor.h"12#include "clang/Sema/Lookup.h"13#include "clang/Sema/MultiplexExternalSemaSource.h"14#include "clang/Sema/Sema.h"15#include "clang/Sema/SemaConsumer.h"16#include <optional>1718namespace clang {1920class Module;2122} // namespace clang2324namespace lldb_private {2526/// Wraps an ExternalASTSource into an ExternalSemaSource. Doesn't take27/// ownership of the provided source.28class ExternalASTSourceWrapper : public clang::ExternalSemaSource {29ExternalASTSource *m_Source;3031public:32ExternalASTSourceWrapper(ExternalASTSource *Source) : m_Source(Source) {33assert(m_Source && "Can't wrap nullptr ExternalASTSource");34}3536~ExternalASTSourceWrapper() override;3738clang::Decl *GetExternalDecl(clang::GlobalDeclID ID) override {39return m_Source->GetExternalDecl(ID);40}4142clang::Selector GetExternalSelector(uint32_t ID) override {43return m_Source->GetExternalSelector(ID);44}4546uint32_t GetNumExternalSelectors() override {47return m_Source->GetNumExternalSelectors();48}4950clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {51return m_Source->GetExternalDeclStmt(Offset);52}5354clang::CXXCtorInitializer **55GetExternalCXXCtorInitializers(uint64_t Offset) override {56return m_Source->GetExternalCXXCtorInitializers(Offset);57}5859clang::CXXBaseSpecifier *60GetExternalCXXBaseSpecifiers(uint64_t Offset) override {61return m_Source->GetExternalCXXBaseSpecifiers(Offset);62}6364void updateOutOfDateIdentifier(const clang::IdentifierInfo &II) override {65m_Source->updateOutOfDateIdentifier(II);66}6768bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,69clang::DeclarationName Name) override {70return m_Source->FindExternalVisibleDeclsByName(DC, Name);71}7273void completeVisibleDeclsMap(const clang::DeclContext *DC) override {74m_Source->completeVisibleDeclsMap(DC);75}7677clang::Module *getModule(unsigned ID) override {78return m_Source->getModule(ID);79}8081std::optional<clang::ASTSourceDescriptor>82getSourceDescriptor(unsigned ID) override {83return m_Source->getSourceDescriptor(ID);84}8586ExtKind hasExternalDefinitions(const clang::Decl *D) override {87return m_Source->hasExternalDefinitions(D);88}8990void FindExternalLexicalDecls(91const clang::DeclContext *DC,92llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,93llvm::SmallVectorImpl<clang::Decl *> &Result) override {94m_Source->FindExternalLexicalDecls(DC, IsKindWeWant, Result);95}9697void98FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,99llvm::SmallVectorImpl<clang::Decl *> &Decls) override {100m_Source->FindFileRegionDecls(File, Offset, Length, Decls);101}102103void CompleteRedeclChain(const clang::Decl *D) override {104m_Source->CompleteRedeclChain(D);105}106107void CompleteType(clang::TagDecl *Tag) override {108m_Source->CompleteType(Tag);109}110111void CompleteType(clang::ObjCInterfaceDecl *Class) override {112m_Source->CompleteType(Class);113}114115void ReadComments() override { m_Source->ReadComments(); }116117void StartedDeserializing() override { m_Source->StartedDeserializing(); }118119void FinishedDeserializing() override { m_Source->FinishedDeserializing(); }120121void StartTranslationUnit(clang::ASTConsumer *Consumer) override {122m_Source->StartTranslationUnit(Consumer);123}124125void PrintStats() override;126127bool layoutRecordType(128const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,129llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,130llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>131&BaseOffsets,132llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>133&VirtualBaseOffsets) override {134return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets,135BaseOffsets, VirtualBaseOffsets);136}137};138139/// Wraps an ASTConsumer into an SemaConsumer. Doesn't take ownership of the140/// provided consumer. If the provided ASTConsumer is also a SemaConsumer,141/// the wrapper will also forward SemaConsumer functions.142class ASTConsumerForwarder : public clang::SemaConsumer {143clang::ASTConsumer *m_c;144clang::SemaConsumer *m_sc;145146public:147ASTConsumerForwarder(clang::ASTConsumer *c) : m_c(c) {148m_sc = llvm::dyn_cast<clang::SemaConsumer>(m_c);149}150151~ASTConsumerForwarder() override;152153void Initialize(clang::ASTContext &Context) override {154m_c->Initialize(Context);155}156157bool HandleTopLevelDecl(clang::DeclGroupRef D) override {158return m_c->HandleTopLevelDecl(D);159}160161void HandleInlineFunctionDefinition(clang::FunctionDecl *D) override {162m_c->HandleInlineFunctionDefinition(D);163}164165void HandleInterestingDecl(clang::DeclGroupRef D) override {166m_c->HandleInterestingDecl(D);167}168169void HandleTranslationUnit(clang::ASTContext &Ctx) override {170m_c->HandleTranslationUnit(Ctx);171}172173void HandleTagDeclDefinition(clang::TagDecl *D) override {174m_c->HandleTagDeclDefinition(D);175}176177void HandleTagDeclRequiredDefinition(const clang::TagDecl *D) override {178m_c->HandleTagDeclRequiredDefinition(D);179}180181void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl *D) override {182m_c->HandleCXXImplicitFunctionInstantiation(D);183}184185void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D) override {186m_c->HandleTopLevelDeclInObjCContainer(D);187}188189void HandleImplicitImportDecl(clang::ImportDecl *D) override {190m_c->HandleImplicitImportDecl(D);191}192193void CompleteTentativeDefinition(clang::VarDecl *D) override {194m_c->CompleteTentativeDefinition(D);195}196197void AssignInheritanceModel(clang::CXXRecordDecl *RD) override {198m_c->AssignInheritanceModel(RD);199}200201void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *D) override {202m_c->HandleCXXStaticMemberVarInstantiation(D);203}204205void HandleVTable(clang::CXXRecordDecl *RD) override {206m_c->HandleVTable(RD);207}208209clang::ASTMutationListener *GetASTMutationListener() override {210return m_c->GetASTMutationListener();211}212213clang::ASTDeserializationListener *GetASTDeserializationListener() override {214return m_c->GetASTDeserializationListener();215}216217void PrintStats() override;218219void InitializeSema(clang::Sema &S) override {220if (m_sc)221m_sc->InitializeSema(S);222}223224/// Inform the semantic consumer that Sema is no longer available.225void ForgetSema() override {226if (m_sc)227m_sc->ForgetSema();228}229230bool shouldSkipFunctionBody(clang::Decl *D) override {231return m_c->shouldSkipFunctionBody(D);232}233};234235/// A ExternalSemaSource multiplexer that prioritizes its sources.236///237/// This ExternalSemaSource will forward all requests to its attached sources.238/// However, unlike a normal multiplexer it will not forward a request to all239/// sources, but instead give priority to certain sources. If a source with a240/// higher priority can fulfill a request, all sources with a lower priority241/// will not receive the request.242///243/// This class is mostly use to multiplex between sources of different244/// 'quality', e.g. a C++ modules and debug information. The C++ module will245/// provide more accurate replies to the requests, but might not be able to246/// answer all requests. The debug information will be used as a fallback then247/// to provide information that is not in the C++ module.248class SemaSourceWithPriorities : public clang::ExternalSemaSource {249250private:251/// The sources ordered in decreasing priority.252llvm::SmallVector<clang::ExternalSemaSource *, 2> Sources;253254public:255/// Construct a SemaSourceWithPriorities with a 'high quality' source that256/// has the higher priority and a 'low quality' source that will be used257/// as a fallback.258SemaSourceWithPriorities(clang::ExternalSemaSource &high_quality_source,259clang::ExternalSemaSource &low_quality_source) {260Sources.push_back(&high_quality_source);261Sources.push_back(&low_quality_source);262}263264~SemaSourceWithPriorities() override;265266void addSource(clang::ExternalSemaSource &source) {267Sources.push_back(&source);268}269270//===--------------------------------------------------------------------===//271// ExternalASTSource.272//===--------------------------------------------------------------------===//273274clang::Decl *GetExternalDecl(clang::GlobalDeclID ID) override {275for (size_t i = 0; i < Sources.size(); ++i)276if (clang::Decl *Result = Sources[i]->GetExternalDecl(ID))277return Result;278return nullptr;279}280281void CompleteRedeclChain(const clang::Decl *D) override {282for (size_t i = 0; i < Sources.size(); ++i)283Sources[i]->CompleteRedeclChain(D);284}285286clang::Selector GetExternalSelector(uint32_t ID) override {287clang::Selector Sel;288for (size_t i = 0; i < Sources.size(); ++i) {289Sel = Sources[i]->GetExternalSelector(ID);290if (!Sel.isNull())291return Sel;292}293return Sel;294}295296uint32_t GetNumExternalSelectors() override {297for (size_t i = 0; i < Sources.size(); ++i)298if (uint32_t total = Sources[i]->GetNumExternalSelectors())299return total;300return 0;301}302303clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {304for (size_t i = 0; i < Sources.size(); ++i)305if (clang::Stmt *Result = Sources[i]->GetExternalDeclStmt(Offset))306return Result;307return nullptr;308}309310clang::CXXBaseSpecifier *311GetExternalCXXBaseSpecifiers(uint64_t Offset) override {312for (size_t i = 0; i < Sources.size(); ++i)313if (clang::CXXBaseSpecifier *R =314Sources[i]->GetExternalCXXBaseSpecifiers(Offset))315return R;316return nullptr;317}318319clang::CXXCtorInitializer **320GetExternalCXXCtorInitializers(uint64_t Offset) override {321for (auto *S : Sources)322if (auto *R = S->GetExternalCXXCtorInitializers(Offset))323return R;324return nullptr;325}326327ExtKind hasExternalDefinitions(const clang::Decl *D) override {328for (const auto &S : Sources)329if (auto EK = S->hasExternalDefinitions(D))330if (EK != EK_ReplyHazy)331return EK;332return EK_ReplyHazy;333}334335bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,336clang::DeclarationName Name) override {337for (size_t i = 0; i < Sources.size(); ++i)338if (Sources[i]->FindExternalVisibleDeclsByName(DC, Name))339return true;340return false;341}342343void completeVisibleDeclsMap(const clang::DeclContext *DC) override {344// FIXME: Only one source should be able to complete the decls map.345for (size_t i = 0; i < Sources.size(); ++i)346Sources[i]->completeVisibleDeclsMap(DC);347}348349void FindExternalLexicalDecls(350const clang::DeclContext *DC,351llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,352llvm::SmallVectorImpl<clang::Decl *> &Result) override {353for (size_t i = 0; i < Sources.size(); ++i) {354Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result);355if (!Result.empty())356return;357}358}359360void361FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,362llvm::SmallVectorImpl<clang::Decl *> &Decls) override {363for (size_t i = 0; i < Sources.size(); ++i)364Sources[i]->FindFileRegionDecls(File, Offset, Length, Decls);365}366367void CompleteType(clang::TagDecl *Tag) override {368for (clang::ExternalSemaSource *S : Sources) {369S->CompleteType(Tag);370// Stop after the first source completed the type.371if (Tag->isCompleteDefinition())372break;373}374}375376void CompleteType(clang::ObjCInterfaceDecl *Class) override {377for (size_t i = 0; i < Sources.size(); ++i)378Sources[i]->CompleteType(Class);379}380381void ReadComments() override {382for (size_t i = 0; i < Sources.size(); ++i)383Sources[i]->ReadComments();384}385386void StartedDeserializing() override {387for (size_t i = 0; i < Sources.size(); ++i)388Sources[i]->StartedDeserializing();389}390391void FinishedDeserializing() override {392for (size_t i = 0; i < Sources.size(); ++i)393Sources[i]->FinishedDeserializing();394}395396void StartTranslationUnit(clang::ASTConsumer *Consumer) override {397for (size_t i = 0; i < Sources.size(); ++i)398Sources[i]->StartTranslationUnit(Consumer);399}400401void PrintStats() override;402403clang::Module *getModule(unsigned ID) override {404for (size_t i = 0; i < Sources.size(); ++i)405if (auto M = Sources[i]->getModule(ID))406return M;407return nullptr;408}409410bool layoutRecordType(411const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,412llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,413llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>414&BaseOffsets,415llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>416&VirtualBaseOffsets) override {417for (size_t i = 0; i < Sources.size(); ++i)418if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets,419BaseOffsets, VirtualBaseOffsets))420return true;421return false;422}423424void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override {425for (auto &Source : Sources)426Source->getMemoryBufferSizes(sizes);427}428429//===--------------------------------------------------------------------===//430// ExternalSemaSource.431//===--------------------------------------------------------------------===//432433void InitializeSema(clang::Sema &S) override {434for (auto &Source : Sources)435Source->InitializeSema(S);436}437438void ForgetSema() override {439for (auto &Source : Sources)440Source->ForgetSema();441}442443void ReadMethodPool(clang::Selector Sel) override {444for (auto &Source : Sources)445Source->ReadMethodPool(Sel);446}447448void updateOutOfDateSelector(clang::Selector Sel) override {449for (auto &Source : Sources)450Source->updateOutOfDateSelector(Sel);451}452453void ReadKnownNamespaces(454llvm::SmallVectorImpl<clang::NamespaceDecl *> &Namespaces) override {455for (auto &Source : Sources)456Source->ReadKnownNamespaces(Namespaces);457}458459void ReadUndefinedButUsed(460llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined)461override {462for (auto &Source : Sources)463Source->ReadUndefinedButUsed(Undefined);464}465466void ReadMismatchingDeleteExpressions(467llvm::MapVector<clang::FieldDecl *,468llvm::SmallVector<std::pair<clang::SourceLocation, bool>,4694>> &Exprs) override {470for (auto &Source : Sources)471Source->ReadMismatchingDeleteExpressions(Exprs);472}473474bool LookupUnqualified(clang::LookupResult &R, clang::Scope *S) override {475for (auto &Source : Sources) {476Source->LookupUnqualified(R, S);477if (!R.empty())478break;479}480481return !R.empty();482}483484void ReadTentativeDefinitions(485llvm::SmallVectorImpl<clang::VarDecl *> &Defs) override {486for (auto &Source : Sources)487Source->ReadTentativeDefinitions(Defs);488}489490void ReadUnusedFileScopedDecls(491llvm::SmallVectorImpl<const clang::DeclaratorDecl *> &Decls) override {492for (auto &Source : Sources)493Source->ReadUnusedFileScopedDecls(Decls);494}495496void ReadDelegatingConstructors(497llvm::SmallVectorImpl<clang::CXXConstructorDecl *> &Decls) override {498for (auto &Source : Sources)499Source->ReadDelegatingConstructors(Decls);500}501502void ReadExtVectorDecls(503llvm::SmallVectorImpl<clang::TypedefNameDecl *> &Decls) override {504for (auto &Source : Sources)505Source->ReadExtVectorDecls(Decls);506}507508void ReadUnusedLocalTypedefNameCandidates(509llvm::SmallSetVector<const clang::TypedefNameDecl *, 4> &Decls) override {510for (auto &Source : Sources)511Source->ReadUnusedLocalTypedefNameCandidates(Decls);512}513514void ReadReferencedSelectors(515llvm::SmallVectorImpl<std::pair<clang::Selector, clang::SourceLocation>>516&Sels) override {517for (auto &Source : Sources)518Source->ReadReferencedSelectors(Sels);519}520521void ReadWeakUndeclaredIdentifiers(522llvm::SmallVectorImpl<std::pair<clang::IdentifierInfo *, clang::WeakInfo>>523&WI) override {524for (auto &Source : Sources)525Source->ReadWeakUndeclaredIdentifiers(WI);526}527528void ReadUsedVTables(529llvm::SmallVectorImpl<clang::ExternalVTableUse> &VTables) override {530for (auto &Source : Sources)531Source->ReadUsedVTables(VTables);532}533534void ReadPendingInstantiations(535llvm::SmallVectorImpl<536std::pair<clang::ValueDecl *, clang::SourceLocation>> &Pending)537override {538for (auto &Source : Sources)539Source->ReadPendingInstantiations(Pending);540}541542void ReadLateParsedTemplates(543llvm::MapVector<const clang::FunctionDecl *,544std::unique_ptr<clang::LateParsedTemplate>> &LPTMap)545override {546for (auto &Source : Sources)547Source->ReadLateParsedTemplates(LPTMap);548}549550clang::TypoCorrection551CorrectTypo(const clang::DeclarationNameInfo &Typo, int LookupKind,552clang::Scope *S, clang::CXXScopeSpec *SS,553clang::CorrectionCandidateCallback &CCC,554clang::DeclContext *MemberContext, bool EnteringContext,555const clang::ObjCObjectPointerType *OPT) override {556for (auto &Source : Sources) {557if (clang::TypoCorrection C =558Source->CorrectTypo(Typo, LookupKind, S, SS, CCC,559MemberContext, EnteringContext, OPT))560return C;561}562return clang::TypoCorrection();563}564565bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc,566clang::QualType T) override {567for (auto &Source : Sources) {568if (Source->MaybeDiagnoseMissingCompleteType(Loc, T))569return true;570}571return false;572}573};574575} // namespace lldb_private576#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H577578579