Path: blob/main/contrib/llvm-project/clang/lib/Index/IndexDecl.cpp
35233 views
//===- IndexDecl.cpp - Indexing declarations ------------------------------===//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#include "IndexingContext.h"9#include "clang/AST/ASTConcept.h"10#include "clang/AST/Attr.h"11#include "clang/AST/Decl.h"12#include "clang/AST/DeclTemplate.h"13#include "clang/AST/DeclVisitor.h"14#include "clang/Index/IndexDataConsumer.h"15#include "clang/Index/IndexSymbol.h"1617using namespace clang;18using namespace index;1920#define TRY_DECL(D,CALL_EXPR) \21do { \22if (!IndexCtx.shouldIndex(D)) return true; \23if (!CALL_EXPR) \24return false; \25} while (0)2627#define TRY_TO(CALL_EXPR) \28do { \29if (!CALL_EXPR) \30return false; \31} while (0)3233namespace {3435class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {36IndexingContext &IndexCtx;3738public:39explicit IndexingDeclVisitor(IndexingContext &indexCtx)40: IndexCtx(indexCtx) { }4142bool Handled = true;4344bool VisitDecl(const Decl *D) {45Handled = false;46return true;47}4849void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,50const NamedDecl *Parent,51const DeclContext *DC) {52const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();53switch (TALoc.getArgument().getKind()) {54case TemplateArgument::Expression:55IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);56break;57case TemplateArgument::Type:58IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);59break;60case TemplateArgument::Template:61case TemplateArgument::TemplateExpansion:62IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),63Parent, DC);64if (const TemplateDecl *TD = TALoc.getArgument()65.getAsTemplateOrTemplatePattern()66.getAsTemplateDecl()) {67if (const NamedDecl *TTD = TD->getTemplatedDecl())68IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);69}70break;71default:72break;73}74}7576/// Returns true if the given method has been defined explicitly by the77/// user.78static bool hasUserDefined(const ObjCMethodDecl *D,79const ObjCImplDecl *Container) {80const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),81D->isInstanceMethod());82return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition() &&83!MD->isSynthesizedAccessorStub();84}858687void handleDeclarator(const DeclaratorDecl *D,88const NamedDecl *Parent = nullptr,89bool isIBType = false) {90if (!Parent) Parent = D;9192IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,93Parent->getLexicalDeclContext(),94/*isBase=*/false, isIBType);95IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);96auto IndexDefaultParmeterArgument = [&](const ParmVarDecl *Parm,97const NamedDecl *Parent) {98if (Parm->hasDefaultArg() && !Parm->hasUninstantiatedDefaultArg() &&99!Parm->hasUnparsedDefaultArg())100IndexCtx.indexBody(Parm->getDefaultArg(), Parent);101};102if (IndexCtx.shouldIndexFunctionLocalSymbols()) {103if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {104auto *DC = Parm->getDeclContext();105if (auto *FD = dyn_cast<FunctionDecl>(DC)) {106if (IndexCtx.shouldIndexParametersInDeclarations() ||107FD->isThisDeclarationADefinition())108IndexCtx.handleDecl(Parm);109} else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {110if (MD->isThisDeclarationADefinition())111IndexCtx.handleDecl(Parm);112} else {113IndexCtx.handleDecl(Parm);114}115} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {116if (IndexCtx.shouldIndexParametersInDeclarations() ||117FD->isThisDeclarationADefinition()) {118for (const auto *PI : FD->parameters()) {119IndexDefaultParmeterArgument(PI, D);120IndexCtx.handleDecl(PI);121}122}123}124} else {125// Index the default parameter value for function definitions.126if (const auto *FD = dyn_cast<FunctionDecl>(D)) {127if (FD->isThisDeclarationADefinition()) {128for (const auto *PV : FD->parameters()) {129IndexDefaultParmeterArgument(PV, D);130}131}132}133}134if (auto *C = D->getTrailingRequiresClause())135IndexCtx.indexBody(C, Parent);136}137138bool handleObjCMethod(const ObjCMethodDecl *D,139const ObjCPropertyDecl *AssociatedProp = nullptr) {140SmallVector<SymbolRelation, 4> Relations;141SmallVector<const ObjCMethodDecl*, 4> Overriden;142143D->getOverriddenMethods(Overriden);144for(auto overridden: Overriden) {145Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,146overridden);147}148if (AssociatedProp)149Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,150AssociatedProp);151152// getLocation() returns beginning token of a method declaration, but for153// indexing purposes we want to point to the base name.154SourceLocation MethodLoc = D->getSelectorStartLoc();155if (MethodLoc.isInvalid())156MethodLoc = D->getLocation();157158SourceLocation AttrLoc;159160// check for (getter=/setter=)161if (AssociatedProp) {162bool isGetter = !D->param_size();163AttrLoc = isGetter ?164AssociatedProp->getGetterNameLoc():165AssociatedProp->getSetterNameLoc();166}167168SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;169if (D->isImplicit()) {170if (AttrLoc.isValid()) {171MethodLoc = AttrLoc;172} else {173Roles |= (SymbolRoleSet)SymbolRole::Implicit;174}175} else if (AttrLoc.isValid()) {176IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),177D->getDeclContext(), 0);178}179180TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));181IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);182bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();183for (const auto *I : D->parameters()) {184handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);185hasIBActionAndFirst = false;186}187188if (D->isThisDeclarationADefinition()) {189const Stmt *Body = D->getBody();190if (Body) {191IndexCtx.indexBody(Body, D, D);192}193}194return true;195}196197/// Gather the declarations which the given declaration \D overrides in a198/// pseudo-override manner.199///200/// Pseudo-overrides occur when a class template specialization declares201/// a declaration that has the same name as a similar declaration in the202/// non-specialized template.203void204gatherTemplatePseudoOverrides(const NamedDecl *D,205SmallVectorImpl<SymbolRelation> &Relations) {206if (!IndexCtx.getLangOpts().CPlusPlus)207return;208const auto *CTSD =209dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());210if (!CTSD)211return;212llvm::PointerUnion<ClassTemplateDecl *,213ClassTemplatePartialSpecializationDecl *>214Template = CTSD->getSpecializedTemplateOrPartial();215if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {216const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();217bool TypeOverride = isa<TypeDecl>(D);218for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {219if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))220ND = CTD->getTemplatedDecl();221if (ND->isImplicit())222continue;223// Types can override other types.224if (!TypeOverride) {225if (ND->getKind() != D->getKind())226continue;227} else if (!isa<TypeDecl>(ND))228continue;229if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {230const auto *DFD = cast<FunctionDecl>(D);231// Function overrides are approximated using the number of parameters.232if (FD->getStorageClass() != DFD->getStorageClass() ||233FD->getNumParams() != DFD->getNumParams())234continue;235}236Relations.emplace_back(237SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);238}239}240}241242bool VisitFunctionDecl(const FunctionDecl *D) {243SymbolRoleSet Roles{};244SmallVector<SymbolRelation, 4> Relations;245if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {246if (CXXMD->isVirtual())247Roles |= (unsigned)SymbolRole::Dynamic;248for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {249Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);250}251}252gatherTemplatePseudoOverrides(D, Relations);253if (const auto *Base = D->getPrimaryTemplate())254Relations.push_back(255SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),256Base->getTemplatedDecl()));257258TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));259handleDeclarator(D);260261if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {262IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),263Ctor->getParent(), Ctor->getDeclContext(),264(unsigned)SymbolRole::NameReference);265266// Constructor initializers.267for (const auto *Init : Ctor->inits()) {268if (Init->isWritten()) {269IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);270if (const FieldDecl *Member = Init->getAnyMember())271IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,272(unsigned)SymbolRole::Write);273IndexCtx.indexBody(Init->getInit(), D, D);274}275}276} else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {277if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {278IndexCtx.handleReference(Dtor->getParent(),279TypeNameInfo->getTypeLoc().getBeginLoc(),280Dtor->getParent(), Dtor->getDeclContext(),281(unsigned)SymbolRole::NameReference);282}283} else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {284IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),285Guide->getLocation(), Guide,286Guide->getDeclContext());287}288// Template specialization arguments.289if (const ASTTemplateArgumentListInfo *TemplateArgInfo =290D->getTemplateSpecializationArgsAsWritten()) {291for (const auto &Arg : TemplateArgInfo->arguments())292handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());293}294295if (D->isThisDeclarationADefinition()) {296const Stmt *Body = D->getBody();297if (Body) {298IndexCtx.indexBody(Body, D, D);299}300}301return true;302}303304bool VisitVarDecl(const VarDecl *D) {305SmallVector<SymbolRelation, 4> Relations;306gatherTemplatePseudoOverrides(D, Relations);307TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));308handleDeclarator(D);309IndexCtx.indexBody(D->getInit(), D);310return true;311}312313bool VisitDecompositionDecl(const DecompositionDecl *D) {314for (const auto *Binding : D->bindings())315TRY_DECL(Binding, IndexCtx.handleDecl(Binding));316return Base::VisitDecompositionDecl(D);317}318319bool VisitFieldDecl(const FieldDecl *D) {320SmallVector<SymbolRelation, 4> Relations;321gatherTemplatePseudoOverrides(D, Relations);322TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));323handleDeclarator(D);324if (D->isBitField())325IndexCtx.indexBody(D->getBitWidth(), D);326else if (D->hasInClassInitializer())327IndexCtx.indexBody(D->getInClassInitializer(), D);328return true;329}330331bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {332if (D->getSynthesize()) {333// handled in VisitObjCPropertyImplDecl334return true;335}336TRY_DECL(D, IndexCtx.handleDecl(D));337handleDeclarator(D);338return true;339}340341bool VisitMSPropertyDecl(const MSPropertyDecl *D) {342TRY_DECL(D, IndexCtx.handleDecl(D));343handleDeclarator(D);344return true;345}346347bool VisitEnumConstantDecl(const EnumConstantDecl *D) {348TRY_DECL(D, IndexCtx.handleDecl(D));349IndexCtx.indexBody(D->getInitExpr(), D);350return true;351}352353bool VisitTypedefNameDecl(const TypedefNameDecl *D) {354if (!D->isTransparentTag()) {355SmallVector<SymbolRelation, 4> Relations;356gatherTemplatePseudoOverrides(D, Relations);357TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));358IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);359}360return true;361}362363bool VisitTagDecl(const TagDecl *D) {364// Non-free standing tags are handled in indexTypeSourceInfo.365if (D->isFreeStanding()) {366if (D->isThisDeclarationADefinition()) {367SmallVector<SymbolRelation, 4> Relations;368gatherTemplatePseudoOverrides(D, Relations);369IndexCtx.indexTagDecl(D, Relations);370} else {371SmallVector<SymbolRelation, 1> Relations;372gatherTemplatePseudoOverrides(D, Relations);373return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),374Relations, D->getLexicalDeclContext());375}376}377return true;378}379380bool VisitEnumDecl(const EnumDecl *ED) {381TRY_TO(VisitTagDecl(ED));382// Indexing for enumdecl itself is handled inside TagDecl, we just want to383// visit integer-base here, which is different than other TagDecl bases.384if (auto *TSI = ED->getIntegerTypeSourceInfo())385IndexCtx.indexTypeSourceInfo(TSI, ED, ED, /*isBase=*/true);386return true;387}388389bool handleReferencedProtocols(const ObjCProtocolList &ProtList,390const ObjCContainerDecl *ContD,391SourceLocation SuperLoc) {392ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();393for (ObjCInterfaceDecl::protocol_iterator394I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {395SourceLocation Loc = *LI;396ObjCProtocolDecl *PD = *I;397SymbolRoleSet roles{};398if (Loc == SuperLoc)399roles |= (SymbolRoleSet)SymbolRole::Implicit;400TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,401SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));402}403return true;404}405406bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {407if (D->isThisDeclarationADefinition()) {408TRY_DECL(D, IndexCtx.handleDecl(D));409SourceLocation SuperLoc = D->getSuperClassLoc();410if (auto *SuperD = D->getSuperClass()) {411bool hasSuperTypedef = false;412if (auto *TInfo = D->getSuperClassTInfo()) {413if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {414if (auto *TD = TT->getDecl()) {415hasSuperTypedef = true;416TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,417SymbolRoleSet()));418}419}420}421SymbolRoleSet superRoles{};422if (hasSuperTypedef)423superRoles |= (SymbolRoleSet)SymbolRole::Implicit;424TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,425SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));426}427TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,428SuperLoc));429TRY_TO(IndexCtx.indexDeclContext(D));430} else {431return IndexCtx.handleReference(D, D->getLocation(), nullptr,432D->getDeclContext(), SymbolRoleSet());433}434return true;435}436437bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {438if (D->isThisDeclarationADefinition()) {439TRY_DECL(D, IndexCtx.handleDecl(D));440TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,441/*SuperLoc=*/SourceLocation()));442TRY_TO(IndexCtx.indexDeclContext(D));443} else {444return IndexCtx.handleReference(D, D->getLocation(), nullptr,445D->getDeclContext(), SymbolRoleSet());446}447return true;448}449450bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {451const ObjCInterfaceDecl *Class = D->getClassInterface();452if (!Class)453return true;454455if (Class->isImplicitInterfaceDecl())456IndexCtx.handleDecl(Class);457458TRY_DECL(D, IndexCtx.handleDecl(D));459460// Visit implicit @synthesize property implementations first as their461// location is reported at the name of the @implementation block. This462// serves no purpose other than to simplify the FileCheck-based tests.463for (const auto *I : D->property_impls()) {464if (I->getLocation().isInvalid())465IndexCtx.indexDecl(I);466}467for (const auto *I : D->decls()) {468if (!isa<ObjCPropertyImplDecl>(I) ||469cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())470IndexCtx.indexDecl(I);471}472473return true;474}475476bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {477if (!IndexCtx.shouldIndex(D))478return true;479const ObjCInterfaceDecl *C = D->getClassInterface();480if (!C)481return true;482TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),483SymbolRelation{484(unsigned)SymbolRole::RelationExtendedBy, D485}));486SourceLocation CategoryLoc = D->getCategoryNameLoc();487if (!CategoryLoc.isValid())488CategoryLoc = D->getLocation();489TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));490TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,491/*SuperLoc=*/SourceLocation()));492TRY_TO(IndexCtx.indexDeclContext(D));493return true;494}495496bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {497const ObjCCategoryDecl *Cat = D->getCategoryDecl();498if (!Cat)499return true;500const ObjCInterfaceDecl *C = D->getClassInterface();501if (C)502TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,503SymbolRoleSet()));504SourceLocation CategoryLoc = D->getCategoryNameLoc();505if (!CategoryLoc.isValid())506CategoryLoc = D->getLocation();507TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));508IndexCtx.indexDeclContext(D);509return true;510}511512bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {513// Methods associated with a property, even user-declared ones, are514// handled when we handle the property.515if (D->isPropertyAccessor())516return true;517518handleObjCMethod(D);519return true;520}521522bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {523if (ObjCMethodDecl *MD = D->getGetterMethodDecl())524if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())525handleObjCMethod(MD, D);526if (ObjCMethodDecl *MD = D->getSetterMethodDecl())527if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())528handleObjCMethod(MD, D);529TRY_DECL(D, IndexCtx.handleDecl(D));530if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())531IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,532D->getLexicalDeclContext(), false, true);533IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);534return true;535}536537bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {538ObjCPropertyDecl *PD = D->getPropertyDecl();539auto *Container = cast<ObjCImplDecl>(D->getDeclContext());540SourceLocation Loc = D->getLocation();541SymbolRoleSet Roles = 0;542SmallVector<SymbolRelation, 1> Relations;543544if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())545Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});546if (Loc.isInvalid()) {547Loc = Container->getLocation();548Roles |= (SymbolRoleSet)SymbolRole::Implicit;549}550TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));551552if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)553return true;554555assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);556SymbolRoleSet AccessorMethodRoles =557SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);558if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {559if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))560IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);561}562if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {563if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))564IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);565}566if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {567if (IvarD->getSynthesize()) {568// For synthesized ivars, use the location of its name in the569// corresponding @synthesize. If there isn't one, use the containing570// @implementation's location, rather than the property's location,571// otherwise the header file containing the @interface will have different572// indexing contents based on whether the @implementation was present or573// not in the translation unit.574SymbolRoleSet IvarRoles = 0;575SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();576if (D->getLocation().isInvalid()) {577IvarLoc = Container->getLocation();578IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;579} else if (D->getLocation() == IvarLoc) {580IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;581}582TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));583} else {584IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,585D->getDeclContext(), SymbolRoleSet());586}587}588return true;589}590591bool VisitNamespaceDecl(const NamespaceDecl *D) {592TRY_DECL(D, IndexCtx.handleDecl(D));593IndexCtx.indexDeclContext(D);594return true;595}596597bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {598TRY_DECL(D, IndexCtx.handleDecl(D));599IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);600IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,601D->getLexicalDeclContext());602return true;603}604605bool VisitUsingDecl(const UsingDecl *D) {606IndexCtx.handleDecl(D);607608const DeclContext *DC = D->getDeclContext()->getRedeclContext();609const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);610IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,611D->getLexicalDeclContext());612for (const auto *I : D->shadows()) {613// Skip unresolved using decls - we already have a decl for the using614// itself, so there's not much point adding another decl or reference to615// refer to the same location.616if (isa<UnresolvedUsingIfExistsDecl>(I->getUnderlyingDecl()))617continue;618619IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,620D->getLexicalDeclContext(), SymbolRoleSet());621}622return true;623}624625bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {626const DeclContext *DC = D->getDeclContext()->getRedeclContext();627const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);628629// NNS for the local 'using namespace' directives is visited by the body630// visitor.631if (!D->getParentFunctionOrMethod())632IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,633D->getLexicalDeclContext());634635return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),636D->getLocation(), Parent,637D->getLexicalDeclContext(),638SymbolRoleSet());639}640641bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {642TRY_DECL(D, IndexCtx.handleDecl(D));643const DeclContext *DC = D->getDeclContext()->getRedeclContext();644const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);645IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,646D->getLexicalDeclContext());647return true;648}649650bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {651TRY_DECL(D, IndexCtx.handleDecl(D));652const DeclContext *DC = D->getDeclContext()->getRedeclContext();653const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);654IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,655D->getLexicalDeclContext());656return true;657}658659bool VisitClassTemplateSpecializationDecl(const660ClassTemplateSpecializationDecl *D) {661// FIXME: Notify subsequent callbacks if info comes from implicit662// instantiation.663llvm::PointerUnion<ClassTemplateDecl *,664ClassTemplatePartialSpecializationDecl *>665Template = D->getSpecializedTemplateOrPartial();666const Decl *SpecializationOf =667Template.is<ClassTemplateDecl *>()668? (Decl *)Template.get<ClassTemplateDecl *>()669: Template.get<ClassTemplatePartialSpecializationDecl *>();670if (!D->isThisDeclarationADefinition())671IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);672IndexCtx.indexTagDecl(673D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),674SpecializationOf));675// Template specialization arguments.676if (const ASTTemplateArgumentListInfo *TemplateArgInfo =677D->getTemplateArgsAsWritten()) {678for (const auto &Arg : TemplateArgInfo->arguments())679handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());680}681return true;682}683684static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {685// We want to index the template parameters only once when indexing the686// canonical declaration.687if (!D)688return false;689if (const auto *FD = dyn_cast<FunctionDecl>(D))690return FD->getCanonicalDecl() == FD;691else if (const auto *TD = dyn_cast<TagDecl>(D))692return TD->getCanonicalDecl() == TD;693else if (const auto *VD = dyn_cast<VarDecl>(D))694return VD->getCanonicalDecl() == VD;695return true;696}697698void indexTemplateParameters(TemplateParameterList *Params,699const NamedDecl *Parent) {700for (const NamedDecl *TP : *Params) {701if (IndexCtx.shouldIndexTemplateParameters())702IndexCtx.handleDecl(TP);703if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {704if (TTP->hasDefaultArgument())705handleTemplateArgumentLoc(TTP->getDefaultArgument(), Parent,706TP->getLexicalDeclContext());707if (auto *C = TTP->getTypeConstraint())708IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),709Parent, TTP->getLexicalDeclContext());710} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {711IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent);712if (NTTP->hasDefaultArgument())713handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent,714TP->getLexicalDeclContext());715} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {716if (TTPD->hasDefaultArgument())717handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,718TP->getLexicalDeclContext());719}720}721if (auto *R = Params->getRequiresClause())722IndexCtx.indexBody(R, Parent);723}724725bool VisitTemplateDecl(const TemplateDecl *D) {726const NamedDecl *Parent = D->getTemplatedDecl();727if (!Parent)728return true;729730// Index the default values for the template parameters.731auto *Params = D->getTemplateParameters();732if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) {733indexTemplateParameters(Params, Parent);734}735736return Visit(Parent);737}738739bool VisitConceptDecl(const ConceptDecl *D) {740if (auto *Params = D->getTemplateParameters())741indexTemplateParameters(Params, D);742if (auto *E = D->getConstraintExpr())743IndexCtx.indexBody(E, D);744return IndexCtx.handleDecl(D);745}746747bool VisitFriendDecl(const FriendDecl *D) {748if (auto ND = D->getFriendDecl()) {749// FIXME: Ignore a class template in a dependent context, these are not750// linked properly with their redeclarations, ending up with duplicate751// USRs.752// See comment "Friend templates are visible in fairly strange ways." in753// SemaTemplate.cpp which precedes code that prevents the friend template754// from becoming visible from the enclosing context.755if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())756return true;757return Visit(ND);758}759if (auto Ty = D->getFriendType()) {760IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));761}762return true;763}764765bool VisitImportDecl(const ImportDecl *D) {766return IndexCtx.importedModule(D);767}768769bool VisitStaticAssertDecl(const StaticAssertDecl *D) {770IndexCtx.indexBody(D->getAssertExpr(),771dyn_cast<NamedDecl>(D->getDeclContext()),772D->getLexicalDeclContext());773return true;774}775};776777} // anonymous namespace778779bool IndexingContext::indexDecl(const Decl *D) {780if (D->isImplicit() && shouldIgnoreIfImplicit(D))781return true;782783if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())784return true;785786IndexingDeclVisitor Visitor(*this);787bool ShouldContinue = Visitor.Visit(D);788if (!ShouldContinue)789return false;790791if (!Visitor.Handled && isa<DeclContext>(D))792return indexDeclContext(cast<DeclContext>(D));793794return true;795}796797bool IndexingContext::indexDeclContext(const DeclContext *DC) {798for (const auto *I : DC->decls())799if (!indexDecl(I))800return false;801return true;802}803804bool IndexingContext::indexTopLevelDecl(const Decl *D) {805if (!D || D->getLocation().isInvalid())806return true;807808if (isa<ObjCMethodDecl>(D))809return true; // Wait for the objc container.810811if (IndexOpts.ShouldTraverseDecl && !IndexOpts.ShouldTraverseDecl(D))812return true; // skip813814return indexDecl(D);815}816817bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {818for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)819if (!indexTopLevelDecl(*I))820return false;821return true;822}823824825