123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- //===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "IndexingContext.h"
- #include "clang/AST/RecursiveASTVisitor.h"
- using namespace clang;
- using namespace index;
- namespace {
- class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
- IndexingContext &IndexCtx;
- const NamedDecl *Parent;
- const DeclContext *ParentDC;
- bool IsBase;
- SmallVector<SymbolRelation, 3> Relations;
- typedef RecursiveASTVisitor<TypeIndexer> base;
- public:
- TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
- const DeclContext *DC, bool isBase, bool isIBType)
- : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
- if (IsBase) {
- assert(Parent);
- Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
- }
- if (isIBType) {
- assert(Parent);
- Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
- }
- }
- bool shouldWalkTypesOfTypeLocs() const { return false; }
- #define TRY_TO(CALL_EXPR) \
- do { \
- if (!CALL_EXPR) \
- return false; \
- } while (0)
- bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) {
- SourceLocation Loc = TTPL.getNameLoc();
- TemplateTypeParmDecl *TTPD = TTPL.getDecl();
- return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC,
- SymbolRoleSet());
- }
- bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- SourceLocation Loc = TL.getNameLoc();
- TypedefNameDecl *ND = TL.getTypedefNameDecl();
- if (ND->isTransparentTag()) {
- TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl();
- return IndexCtx.handleReference(Underlying, Loc, Parent,
- ParentDC, SymbolRoleSet(), Relations);
- }
- if (IsBase) {
- TRY_TO(IndexCtx.handleReference(ND, Loc,
- Parent, ParentDC, SymbolRoleSet()));
- if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {
- TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC,
- (unsigned)SymbolRole::Implicit,
- Relations));
- }
- } else {
- TRY_TO(IndexCtx.handleReference(ND, Loc,
- Parent, ParentDC, SymbolRoleSet(),
- Relations));
- }
- return true;
- }
- bool traverseParamVarHelper(ParmVarDecl *D) {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- if (D->getTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- return true;
- }
- bool TraverseParmVarDecl(ParmVarDecl *D) {
- // Avoid visiting default arguments from the definition that were already
- // visited in the declaration.
- // FIXME: A free function definition can have default arguments.
- // Avoiding double visitaiton of default arguments should be handled by the
- // visitor probably with a bit in the AST to indicate if the attached
- // default argument was 'inherited' or written in source.
- if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
- if (FD->isThisDeclarationADefinition()) {
- return traverseParamVarHelper(D);
- }
- }
- return base::TraverseParmVarDecl(D);
- }
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
- IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
- return true;
- }
- bool VisitTagTypeLoc(TagTypeLoc TL) {
- TagDecl *D = TL.getDecl();
- if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&
- D->getParentFunctionOrMethod())
- return true;
- if (TL.isDefinition()) {
- IndexCtx.indexTagDecl(D);
- return true;
- }
- return IndexCtx.handleReference(D, TL.getNameLoc(),
- Parent, ParentDC, SymbolRoleSet(),
- Relations);
- }
- bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
- return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
- Parent, ParentDC, SymbolRoleSet(), Relations);
- }
- bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
- for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
- IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
- Parent, ParentDC, SymbolRoleSet(), Relations);
- }
- return true;
- }
- template<typename TypeLocType>
- bool HandleTemplateSpecializationTypeLoc(TypeLocType TL) {
- if (const auto *T = TL.getTypePtr()) {
- if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
- if (!RD->isImplicit() || IndexCtx.shouldIndexImplicitInstantiation()) {
- IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), Parent,
- ParentDC, SymbolRoleSet(), Relations);
- return true;
- }
- }
- if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
- IndexCtx.handleReference(D, TL.getTemplateNameLoc(), Parent, ParentDC,
- SymbolRoleSet(), Relations);
- }
- return true;
- }
- bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
- return HandleTemplateSpecializationTypeLoc(TL);
- }
- bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {
- return HandleTemplateSpecializationTypeLoc(TL);
- }
- bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
- const DependentNameType *DNT = TL.getTypePtr();
- const NestedNameSpecifier *NNS = DNT->getQualifier();
- const Type *T = NNS->getAsType();
- if (!T)
- return true;
- const TemplateSpecializationType *TST =
- T->getAs<TemplateSpecializationType>();
- if (!TST)
- return true;
- TemplateName TN = TST->getTemplateName();
- const ClassTemplateDecl *TD =
- dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
- if (!TD)
- return true;
- CXXRecordDecl *RD = TD->getTemplatedDecl();
- if (!RD->hasDefinition())
- return true;
- RD = RD->getDefinition();
- DeclarationName Name(DNT->getIdentifier());
- std::vector<const NamedDecl *> Symbols = RD->lookupDependentName(
- Name, [](const NamedDecl *ND) { return isa<TypeDecl>(ND); });
- if (Symbols.size() != 1)
- return true;
- return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent,
- ParentDC, SymbolRoleSet(), Relations);
- }
- bool TraverseStmt(Stmt *S) {
- IndexCtx.indexBody(S, Parent, ParentDC);
- return true;
- }
- };
- } // anonymous namespace
- void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
- const NamedDecl *Parent,
- const DeclContext *DC,
- bool isBase,
- bool isIBType) {
- if (!TInfo || TInfo->getTypeLoc().isNull())
- return;
- indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
- }
- void IndexingContext::indexTypeLoc(TypeLoc TL,
- const NamedDecl *Parent,
- const DeclContext *DC,
- bool isBase,
- bool isIBType) {
- if (TL.isNull())
- return;
- if (!DC)
- DC = Parent->getLexicalDeclContext();
- TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
- }
- void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
- const NamedDecl *Parent,
- const DeclContext *DC) {
- if (!NNS)
- return;
- if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
- indexNestedNameSpecifierLoc(Prefix, Parent, DC);
- if (!DC)
- DC = Parent->getLexicalDeclContext();
- SourceLocation Loc = NNS.getLocalBeginLoc();
- switch (NNS.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- break;
- case NestedNameSpecifier::Namespace:
- handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
- Loc, Parent, DC, SymbolRoleSet());
- break;
- case NestedNameSpecifier::NamespaceAlias:
- handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
- Loc, Parent, DC, SymbolRoleSet());
- break;
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
- break;
- }
- }
- void IndexingContext::indexTagDecl(const TagDecl *D,
- ArrayRef<SymbolRelation> Relations) {
- if (!shouldIndex(D))
- return;
- if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
- return;
- if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {
- if (D->isThisDeclarationADefinition()) {
- indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
- if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
- for (const auto &I : CXXRD->bases()) {
- indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
- }
- }
- indexDeclContext(D);
- }
- }
- }
|