1*0b57cec5SDimitry Andric //===- IndexDecl.cpp - Indexing declarations ------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "IndexingContext.h" 10*0b57cec5SDimitry Andric #include "clang/Index/IndexDataConsumer.h" 11*0b57cec5SDimitry Andric #include "clang/AST/DeclVisitor.h" 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric using namespace clang; 14*0b57cec5SDimitry Andric using namespace index; 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #define TRY_DECL(D,CALL_EXPR) \ 17*0b57cec5SDimitry Andric do { \ 18*0b57cec5SDimitry Andric if (!IndexCtx.shouldIndex(D)) return true; \ 19*0b57cec5SDimitry Andric if (!CALL_EXPR) \ 20*0b57cec5SDimitry Andric return false; \ 21*0b57cec5SDimitry Andric } while (0) 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric #define TRY_TO(CALL_EXPR) \ 24*0b57cec5SDimitry Andric do { \ 25*0b57cec5SDimitry Andric if (!CALL_EXPR) \ 26*0b57cec5SDimitry Andric return false; \ 27*0b57cec5SDimitry Andric } while (0) 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric namespace { 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { 32*0b57cec5SDimitry Andric IndexingContext &IndexCtx; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric public: 35*0b57cec5SDimitry Andric explicit IndexingDeclVisitor(IndexingContext &indexCtx) 36*0b57cec5SDimitry Andric : IndexCtx(indexCtx) { } 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric bool Handled = true; 39*0b57cec5SDimitry Andric 40*0b57cec5SDimitry Andric bool VisitDecl(const Decl *D) { 41*0b57cec5SDimitry Andric Handled = false; 42*0b57cec5SDimitry Andric return true; 43*0b57cec5SDimitry Andric } 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric /// Returns true if the given method has been defined explicitly by the 46*0b57cec5SDimitry Andric /// user. 47*0b57cec5SDimitry Andric static bool hasUserDefined(const ObjCMethodDecl *D, 48*0b57cec5SDimitry Andric const ObjCImplDecl *Container) { 49*0b57cec5SDimitry Andric const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), 50*0b57cec5SDimitry Andric D->isInstanceMethod()); 51*0b57cec5SDimitry Andric return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); 52*0b57cec5SDimitry Andric } 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc, 55*0b57cec5SDimitry Andric const NamedDecl *Parent, 56*0b57cec5SDimitry Andric const DeclContext *DC) { 57*0b57cec5SDimitry Andric const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo(); 58*0b57cec5SDimitry Andric switch (TALoc.getArgument().getKind()) { 59*0b57cec5SDimitry Andric case TemplateArgument::Expression: 60*0b57cec5SDimitry Andric IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC); 61*0b57cec5SDimitry Andric break; 62*0b57cec5SDimitry Andric case TemplateArgument::Type: 63*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC); 64*0b57cec5SDimitry Andric break; 65*0b57cec5SDimitry Andric case TemplateArgument::Template: 66*0b57cec5SDimitry Andric case TemplateArgument::TemplateExpansion: 67*0b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(), 68*0b57cec5SDimitry Andric Parent, DC); 69*0b57cec5SDimitry Andric if (const TemplateDecl *TD = TALoc.getArgument() 70*0b57cec5SDimitry Andric .getAsTemplateOrTemplatePattern() 71*0b57cec5SDimitry Andric .getAsTemplateDecl()) { 72*0b57cec5SDimitry Andric if (const NamedDecl *TTD = TD->getTemplatedDecl()) 73*0b57cec5SDimitry Andric IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC); 74*0b57cec5SDimitry Andric } 75*0b57cec5SDimitry Andric break; 76*0b57cec5SDimitry Andric default: 77*0b57cec5SDimitry Andric break; 78*0b57cec5SDimitry Andric } 79*0b57cec5SDimitry Andric } 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric void handleDeclarator(const DeclaratorDecl *D, 82*0b57cec5SDimitry Andric const NamedDecl *Parent = nullptr, 83*0b57cec5SDimitry Andric bool isIBType = false) { 84*0b57cec5SDimitry Andric if (!Parent) Parent = D; 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent, 87*0b57cec5SDimitry Andric Parent->getLexicalDeclContext(), 88*0b57cec5SDimitry Andric /*isBase=*/false, isIBType); 89*0b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); 90*0b57cec5SDimitry Andric if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 91*0b57cec5SDimitry Andric if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { 92*0b57cec5SDimitry Andric auto *DC = Parm->getDeclContext(); 93*0b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(DC)) { 94*0b57cec5SDimitry Andric if (IndexCtx.shouldIndexParametersInDeclarations() || 95*0b57cec5SDimitry Andric FD->isThisDeclarationADefinition()) 96*0b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 97*0b57cec5SDimitry Andric } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) { 98*0b57cec5SDimitry Andric if (MD->isThisDeclarationADefinition()) 99*0b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 100*0b57cec5SDimitry Andric } else { 101*0b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 104*0b57cec5SDimitry Andric if (IndexCtx.shouldIndexParametersInDeclarations() || 105*0b57cec5SDimitry Andric FD->isThisDeclarationADefinition()) { 106*0b57cec5SDimitry Andric for (auto PI : FD->parameters()) { 107*0b57cec5SDimitry Andric IndexCtx.handleDecl(PI); 108*0b57cec5SDimitry Andric } 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric } 111*0b57cec5SDimitry Andric } else { 112*0b57cec5SDimitry Andric // Index the default parameter value for function definitions. 113*0b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 114*0b57cec5SDimitry Andric if (FD->isThisDeclarationADefinition()) { 115*0b57cec5SDimitry Andric for (const auto *PV : FD->parameters()) { 116*0b57cec5SDimitry Andric if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() && 117*0b57cec5SDimitry Andric !PV->hasUnparsedDefaultArg()) 118*0b57cec5SDimitry Andric IndexCtx.indexBody(PV->getDefaultArg(), D); 119*0b57cec5SDimitry Andric } 120*0b57cec5SDimitry Andric } 121*0b57cec5SDimitry Andric } 122*0b57cec5SDimitry Andric } 123*0b57cec5SDimitry Andric } 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric bool handleObjCMethod(const ObjCMethodDecl *D, 126*0b57cec5SDimitry Andric const ObjCPropertyDecl *AssociatedProp = nullptr) { 127*0b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 128*0b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl*, 4> Overriden; 129*0b57cec5SDimitry Andric 130*0b57cec5SDimitry Andric D->getOverriddenMethods(Overriden); 131*0b57cec5SDimitry Andric for(auto overridden: Overriden) { 132*0b57cec5SDimitry Andric Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf, 133*0b57cec5SDimitry Andric overridden); 134*0b57cec5SDimitry Andric } 135*0b57cec5SDimitry Andric if (AssociatedProp) 136*0b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf, 137*0b57cec5SDimitry Andric AssociatedProp); 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric // getLocation() returns beginning token of a method declaration, but for 140*0b57cec5SDimitry Andric // indexing purposes we want to point to the base name. 141*0b57cec5SDimitry Andric SourceLocation MethodLoc = D->getSelectorStartLoc(); 142*0b57cec5SDimitry Andric if (MethodLoc.isInvalid()) 143*0b57cec5SDimitry Andric MethodLoc = D->getLocation(); 144*0b57cec5SDimitry Andric 145*0b57cec5SDimitry Andric SourceLocation AttrLoc; 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric // check for (getter=/setter=) 148*0b57cec5SDimitry Andric if (AssociatedProp) { 149*0b57cec5SDimitry Andric bool isGetter = !D->param_size(); 150*0b57cec5SDimitry Andric AttrLoc = isGetter ? 151*0b57cec5SDimitry Andric AssociatedProp->getGetterNameLoc(): 152*0b57cec5SDimitry Andric AssociatedProp->getSetterNameLoc(); 153*0b57cec5SDimitry Andric } 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic; 156*0b57cec5SDimitry Andric if (D->isImplicit()) { 157*0b57cec5SDimitry Andric if (AttrLoc.isValid()) { 158*0b57cec5SDimitry Andric MethodLoc = AttrLoc; 159*0b57cec5SDimitry Andric } else { 160*0b57cec5SDimitry Andric Roles |= (SymbolRoleSet)SymbolRole::Implicit; 161*0b57cec5SDimitry Andric } 162*0b57cec5SDimitry Andric } else if (AttrLoc.isValid()) { 163*0b57cec5SDimitry Andric IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()), 164*0b57cec5SDimitry Andric D->getDeclContext(), 0); 165*0b57cec5SDimitry Andric } 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); 168*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); 169*0b57cec5SDimitry Andric bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); 170*0b57cec5SDimitry Andric for (const auto *I : D->parameters()) { 171*0b57cec5SDimitry Andric handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst); 172*0b57cec5SDimitry Andric hasIBActionAndFirst = false; 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 176*0b57cec5SDimitry Andric const Stmt *Body = D->getBody(); 177*0b57cec5SDimitry Andric if (Body) { 178*0b57cec5SDimitry Andric IndexCtx.indexBody(Body, D, D); 179*0b57cec5SDimitry Andric } 180*0b57cec5SDimitry Andric } 181*0b57cec5SDimitry Andric return true; 182*0b57cec5SDimitry Andric } 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric /// Gather the declarations which the given declaration \D overrides in a 185*0b57cec5SDimitry Andric /// pseudo-override manner. 186*0b57cec5SDimitry Andric /// 187*0b57cec5SDimitry Andric /// Pseudo-overrides occur when a class template specialization declares 188*0b57cec5SDimitry Andric /// a declaration that has the same name as a similar declaration in the 189*0b57cec5SDimitry Andric /// non-specialized template. 190*0b57cec5SDimitry Andric void 191*0b57cec5SDimitry Andric gatherTemplatePseudoOverrides(const NamedDecl *D, 192*0b57cec5SDimitry Andric SmallVectorImpl<SymbolRelation> &Relations) { 193*0b57cec5SDimitry Andric if (!IndexCtx.getLangOpts().CPlusPlus) 194*0b57cec5SDimitry Andric return; 195*0b57cec5SDimitry Andric const auto *CTSD = 196*0b57cec5SDimitry Andric dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext()); 197*0b57cec5SDimitry Andric if (!CTSD) 198*0b57cec5SDimitry Andric return; 199*0b57cec5SDimitry Andric llvm::PointerUnion<ClassTemplateDecl *, 200*0b57cec5SDimitry Andric ClassTemplatePartialSpecializationDecl *> 201*0b57cec5SDimitry Andric Template = CTSD->getSpecializedTemplateOrPartial(); 202*0b57cec5SDimitry Andric if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) { 203*0b57cec5SDimitry Andric const CXXRecordDecl *Pattern = CTD->getTemplatedDecl(); 204*0b57cec5SDimitry Andric bool TypeOverride = isa<TypeDecl>(D); 205*0b57cec5SDimitry Andric for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) { 206*0b57cec5SDimitry Andric if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) 207*0b57cec5SDimitry Andric ND = CTD->getTemplatedDecl(); 208*0b57cec5SDimitry Andric if (ND->isImplicit()) 209*0b57cec5SDimitry Andric continue; 210*0b57cec5SDimitry Andric // Types can override other types. 211*0b57cec5SDimitry Andric if (!TypeOverride) { 212*0b57cec5SDimitry Andric if (ND->getKind() != D->getKind()) 213*0b57cec5SDimitry Andric continue; 214*0b57cec5SDimitry Andric } else if (!isa<TypeDecl>(ND)) 215*0b57cec5SDimitry Andric continue; 216*0b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { 217*0b57cec5SDimitry Andric const auto *DFD = cast<FunctionDecl>(D); 218*0b57cec5SDimitry Andric // Function overrides are approximated using the number of parameters. 219*0b57cec5SDimitry Andric if (FD->getStorageClass() != DFD->getStorageClass() || 220*0b57cec5SDimitry Andric FD->getNumParams() != DFD->getNumParams()) 221*0b57cec5SDimitry Andric continue; 222*0b57cec5SDimitry Andric } 223*0b57cec5SDimitry Andric Relations.emplace_back( 224*0b57cec5SDimitry Andric SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND); 225*0b57cec5SDimitry Andric } 226*0b57cec5SDimitry Andric } 227*0b57cec5SDimitry Andric } 228*0b57cec5SDimitry Andric 229*0b57cec5SDimitry Andric bool VisitFunctionDecl(const FunctionDecl *D) { 230*0b57cec5SDimitry Andric SymbolRoleSet Roles{}; 231*0b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 232*0b57cec5SDimitry Andric if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) { 233*0b57cec5SDimitry Andric if (CXXMD->isVirtual()) 234*0b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Dynamic; 235*0b57cec5SDimitry Andric for (const CXXMethodDecl *O : CXXMD->overridden_methods()) { 236*0b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O); 237*0b57cec5SDimitry Andric } 238*0b57cec5SDimitry Andric } 239*0b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 240*0b57cec5SDimitry Andric if (const auto *Base = D->getPrimaryTemplate()) 241*0b57cec5SDimitry Andric Relations.push_back( 242*0b57cec5SDimitry Andric SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 243*0b57cec5SDimitry Andric Base->getTemplatedDecl())); 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations)); 246*0b57cec5SDimitry Andric handleDeclarator(D); 247*0b57cec5SDimitry Andric 248*0b57cec5SDimitry Andric if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 249*0b57cec5SDimitry Andric IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(), 250*0b57cec5SDimitry Andric Ctor->getParent(), Ctor->getDeclContext(), 251*0b57cec5SDimitry Andric (unsigned)SymbolRole::NameReference); 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric // Constructor initializers. 254*0b57cec5SDimitry Andric for (const auto *Init : Ctor->inits()) { 255*0b57cec5SDimitry Andric if (Init->isWritten()) { 256*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 257*0b57cec5SDimitry Andric if (const FieldDecl *Member = Init->getAnyMember()) 258*0b57cec5SDimitry Andric IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, 259*0b57cec5SDimitry Andric (unsigned)SymbolRole::Write); 260*0b57cec5SDimitry Andric IndexCtx.indexBody(Init->getInit(), D, D); 261*0b57cec5SDimitry Andric } 262*0b57cec5SDimitry Andric } 263*0b57cec5SDimitry Andric } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) { 264*0b57cec5SDimitry Andric if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { 265*0b57cec5SDimitry Andric IndexCtx.handleReference(Dtor->getParent(), 266*0b57cec5SDimitry Andric TypeNameInfo->getTypeLoc().getBeginLoc(), 267*0b57cec5SDimitry Andric Dtor->getParent(), Dtor->getDeclContext(), 268*0b57cec5SDimitry Andric (unsigned)SymbolRole::NameReference); 269*0b57cec5SDimitry Andric } 270*0b57cec5SDimitry Andric } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) { 271*0b57cec5SDimitry Andric IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(), 272*0b57cec5SDimitry Andric Guide->getLocation(), Guide, 273*0b57cec5SDimitry Andric Guide->getDeclContext()); 274*0b57cec5SDimitry Andric } 275*0b57cec5SDimitry Andric // Template specialization arguments. 276*0b57cec5SDimitry Andric if (const ASTTemplateArgumentListInfo *TemplateArgInfo = 277*0b57cec5SDimitry Andric D->getTemplateSpecializationArgsAsWritten()) { 278*0b57cec5SDimitry Andric for (const auto &Arg : TemplateArgInfo->arguments()) 279*0b57cec5SDimitry Andric handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); 280*0b57cec5SDimitry Andric } 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 283*0b57cec5SDimitry Andric const Stmt *Body = D->getBody(); 284*0b57cec5SDimitry Andric if (Body) { 285*0b57cec5SDimitry Andric IndexCtx.indexBody(Body, D, D); 286*0b57cec5SDimitry Andric } 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric return true; 289*0b57cec5SDimitry Andric } 290*0b57cec5SDimitry Andric 291*0b57cec5SDimitry Andric bool VisitVarDecl(const VarDecl *D) { 292*0b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 293*0b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 294*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 295*0b57cec5SDimitry Andric handleDeclarator(D); 296*0b57cec5SDimitry Andric IndexCtx.indexBody(D->getInit(), D); 297*0b57cec5SDimitry Andric return true; 298*0b57cec5SDimitry Andric } 299*0b57cec5SDimitry Andric 300*0b57cec5SDimitry Andric bool VisitDecompositionDecl(const DecompositionDecl *D) { 301*0b57cec5SDimitry Andric for (const auto *Binding : D->bindings()) 302*0b57cec5SDimitry Andric TRY_DECL(Binding, IndexCtx.handleDecl(Binding)); 303*0b57cec5SDimitry Andric return Base::VisitDecompositionDecl(D); 304*0b57cec5SDimitry Andric } 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric bool VisitFieldDecl(const FieldDecl *D) { 307*0b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 308*0b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 309*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 310*0b57cec5SDimitry Andric handleDeclarator(D); 311*0b57cec5SDimitry Andric if (D->isBitField()) 312*0b57cec5SDimitry Andric IndexCtx.indexBody(D->getBitWidth(), D); 313*0b57cec5SDimitry Andric else if (D->hasInClassInitializer()) 314*0b57cec5SDimitry Andric IndexCtx.indexBody(D->getInClassInitializer(), D); 315*0b57cec5SDimitry Andric return true; 316*0b57cec5SDimitry Andric } 317*0b57cec5SDimitry Andric 318*0b57cec5SDimitry Andric bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { 319*0b57cec5SDimitry Andric if (D->getSynthesize()) { 320*0b57cec5SDimitry Andric // handled in VisitObjCPropertyImplDecl 321*0b57cec5SDimitry Andric return true; 322*0b57cec5SDimitry Andric } 323*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 324*0b57cec5SDimitry Andric handleDeclarator(D); 325*0b57cec5SDimitry Andric return true; 326*0b57cec5SDimitry Andric } 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 329*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 330*0b57cec5SDimitry Andric handleDeclarator(D); 331*0b57cec5SDimitry Andric return true; 332*0b57cec5SDimitry Andric } 333*0b57cec5SDimitry Andric 334*0b57cec5SDimitry Andric bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 335*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 336*0b57cec5SDimitry Andric IndexCtx.indexBody(D->getInitExpr(), D); 337*0b57cec5SDimitry Andric return true; 338*0b57cec5SDimitry Andric } 339*0b57cec5SDimitry Andric 340*0b57cec5SDimitry Andric bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 341*0b57cec5SDimitry Andric if (!D->isTransparentTag()) { 342*0b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 343*0b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 344*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 345*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 346*0b57cec5SDimitry Andric } 347*0b57cec5SDimitry Andric return true; 348*0b57cec5SDimitry Andric } 349*0b57cec5SDimitry Andric 350*0b57cec5SDimitry Andric bool VisitTagDecl(const TagDecl *D) { 351*0b57cec5SDimitry Andric // Non-free standing tags are handled in indexTypeSourceInfo. 352*0b57cec5SDimitry Andric if (D->isFreeStanding()) { 353*0b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 354*0b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 355*0b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 356*0b57cec5SDimitry Andric IndexCtx.indexTagDecl(D, Relations); 357*0b57cec5SDimitry Andric } else { 358*0b57cec5SDimitry Andric SmallVector<SymbolRelation, 1> Relations; 359*0b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 360*0b57cec5SDimitry Andric return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(), 361*0b57cec5SDimitry Andric Relations, D->getLexicalDeclContext()); 362*0b57cec5SDimitry Andric } 363*0b57cec5SDimitry Andric } 364*0b57cec5SDimitry Andric return true; 365*0b57cec5SDimitry Andric } 366*0b57cec5SDimitry Andric 367*0b57cec5SDimitry Andric bool handleReferencedProtocols(const ObjCProtocolList &ProtList, 368*0b57cec5SDimitry Andric const ObjCContainerDecl *ContD, 369*0b57cec5SDimitry Andric SourceLocation SuperLoc) { 370*0b57cec5SDimitry Andric ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 371*0b57cec5SDimitry Andric for (ObjCInterfaceDecl::protocol_iterator 372*0b57cec5SDimitry Andric I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 373*0b57cec5SDimitry Andric SourceLocation Loc = *LI; 374*0b57cec5SDimitry Andric ObjCProtocolDecl *PD = *I; 375*0b57cec5SDimitry Andric SymbolRoleSet roles{}; 376*0b57cec5SDimitry Andric if (Loc == SuperLoc) 377*0b57cec5SDimitry Andric roles |= (SymbolRoleSet)SymbolRole::Implicit; 378*0b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, 379*0b57cec5SDimitry Andric SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); 380*0b57cec5SDimitry Andric } 381*0b57cec5SDimitry Andric return true; 382*0b57cec5SDimitry Andric } 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 385*0b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 386*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 387*0b57cec5SDimitry Andric SourceLocation SuperLoc = D->getSuperClassLoc(); 388*0b57cec5SDimitry Andric if (auto *SuperD = D->getSuperClass()) { 389*0b57cec5SDimitry Andric bool hasSuperTypedef = false; 390*0b57cec5SDimitry Andric if (auto *TInfo = D->getSuperClassTInfo()) { 391*0b57cec5SDimitry Andric if (auto *TT = TInfo->getType()->getAs<TypedefType>()) { 392*0b57cec5SDimitry Andric if (auto *TD = TT->getDecl()) { 393*0b57cec5SDimitry Andric hasSuperTypedef = true; 394*0b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, 395*0b57cec5SDimitry Andric SymbolRoleSet())); 396*0b57cec5SDimitry Andric } 397*0b57cec5SDimitry Andric } 398*0b57cec5SDimitry Andric } 399*0b57cec5SDimitry Andric SymbolRoleSet superRoles{}; 400*0b57cec5SDimitry Andric if (hasSuperTypedef) 401*0b57cec5SDimitry Andric superRoles |= (SymbolRoleSet)SymbolRole::Implicit; 402*0b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, 403*0b57cec5SDimitry Andric SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); 404*0b57cec5SDimitry Andric } 405*0b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 406*0b57cec5SDimitry Andric SuperLoc)); 407*0b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 408*0b57cec5SDimitry Andric } else { 409*0b57cec5SDimitry Andric return IndexCtx.handleReference(D, D->getLocation(), nullptr, 410*0b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 411*0b57cec5SDimitry Andric } 412*0b57cec5SDimitry Andric return true; 413*0b57cec5SDimitry Andric } 414*0b57cec5SDimitry Andric 415*0b57cec5SDimitry Andric bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 416*0b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 417*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 418*0b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 419*0b57cec5SDimitry Andric /*SuperLoc=*/SourceLocation())); 420*0b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 421*0b57cec5SDimitry Andric } else { 422*0b57cec5SDimitry Andric return IndexCtx.handleReference(D, D->getLocation(), nullptr, 423*0b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 424*0b57cec5SDimitry Andric } 425*0b57cec5SDimitry Andric return true; 426*0b57cec5SDimitry Andric } 427*0b57cec5SDimitry Andric 428*0b57cec5SDimitry Andric bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 429*0b57cec5SDimitry Andric const ObjCInterfaceDecl *Class = D->getClassInterface(); 430*0b57cec5SDimitry Andric if (!Class) 431*0b57cec5SDimitry Andric return true; 432*0b57cec5SDimitry Andric 433*0b57cec5SDimitry Andric if (Class->isImplicitInterfaceDecl()) 434*0b57cec5SDimitry Andric IndexCtx.handleDecl(Class); 435*0b57cec5SDimitry Andric 436*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 437*0b57cec5SDimitry Andric 438*0b57cec5SDimitry Andric // Visit implicit @synthesize property implementations first as their 439*0b57cec5SDimitry Andric // location is reported at the name of the @implementation block. This 440*0b57cec5SDimitry Andric // serves no purpose other than to simplify the FileCheck-based tests. 441*0b57cec5SDimitry Andric for (const auto *I : D->property_impls()) { 442*0b57cec5SDimitry Andric if (I->getLocation().isInvalid()) 443*0b57cec5SDimitry Andric IndexCtx.indexDecl(I); 444*0b57cec5SDimitry Andric } 445*0b57cec5SDimitry Andric for (const auto *I : D->decls()) { 446*0b57cec5SDimitry Andric if (!isa<ObjCPropertyImplDecl>(I) || 447*0b57cec5SDimitry Andric cast<ObjCPropertyImplDecl>(I)->getLocation().isValid()) 448*0b57cec5SDimitry Andric IndexCtx.indexDecl(I); 449*0b57cec5SDimitry Andric } 450*0b57cec5SDimitry Andric 451*0b57cec5SDimitry Andric return true; 452*0b57cec5SDimitry Andric } 453*0b57cec5SDimitry Andric 454*0b57cec5SDimitry Andric bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 455*0b57cec5SDimitry Andric if (!IndexCtx.shouldIndex(D)) 456*0b57cec5SDimitry Andric return true; 457*0b57cec5SDimitry Andric const ObjCInterfaceDecl *C = D->getClassInterface(); 458*0b57cec5SDimitry Andric if (!C) 459*0b57cec5SDimitry Andric return true; 460*0b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), 461*0b57cec5SDimitry Andric SymbolRelation{ 462*0b57cec5SDimitry Andric (unsigned)SymbolRole::RelationExtendedBy, D 463*0b57cec5SDimitry Andric })); 464*0b57cec5SDimitry Andric SourceLocation CategoryLoc = D->getCategoryNameLoc(); 465*0b57cec5SDimitry Andric if (!CategoryLoc.isValid()) 466*0b57cec5SDimitry Andric CategoryLoc = D->getLocation(); 467*0b57cec5SDimitry Andric TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); 468*0b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 469*0b57cec5SDimitry Andric /*SuperLoc=*/SourceLocation())); 470*0b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 471*0b57cec5SDimitry Andric return true; 472*0b57cec5SDimitry Andric } 473*0b57cec5SDimitry Andric 474*0b57cec5SDimitry Andric bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 475*0b57cec5SDimitry Andric const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 476*0b57cec5SDimitry Andric if (!Cat) 477*0b57cec5SDimitry Andric return true; 478*0b57cec5SDimitry Andric const ObjCInterfaceDecl *C = D->getClassInterface(); 479*0b57cec5SDimitry Andric if (C) 480*0b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, 481*0b57cec5SDimitry Andric SymbolRoleSet())); 482*0b57cec5SDimitry Andric SourceLocation CategoryLoc = D->getCategoryNameLoc(); 483*0b57cec5SDimitry Andric if (!CategoryLoc.isValid()) 484*0b57cec5SDimitry Andric CategoryLoc = D->getLocation(); 485*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); 486*0b57cec5SDimitry Andric IndexCtx.indexDeclContext(D); 487*0b57cec5SDimitry Andric return true; 488*0b57cec5SDimitry Andric } 489*0b57cec5SDimitry Andric 490*0b57cec5SDimitry Andric bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 491*0b57cec5SDimitry Andric // Methods associated with a property, even user-declared ones, are 492*0b57cec5SDimitry Andric // handled when we handle the property. 493*0b57cec5SDimitry Andric if (D->isPropertyAccessor()) 494*0b57cec5SDimitry Andric return true; 495*0b57cec5SDimitry Andric 496*0b57cec5SDimitry Andric handleObjCMethod(D); 497*0b57cec5SDimitry Andric return true; 498*0b57cec5SDimitry Andric } 499*0b57cec5SDimitry Andric 500*0b57cec5SDimitry Andric bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 501*0b57cec5SDimitry Andric if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 502*0b57cec5SDimitry Andric if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 503*0b57cec5SDimitry Andric handleObjCMethod(MD, D); 504*0b57cec5SDimitry Andric if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 505*0b57cec5SDimitry Andric if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 506*0b57cec5SDimitry Andric handleObjCMethod(MD, D); 507*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 508*0b57cec5SDimitry Andric if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) 509*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, 510*0b57cec5SDimitry Andric D->getLexicalDeclContext(), false, true); 511*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 512*0b57cec5SDimitry Andric return true; 513*0b57cec5SDimitry Andric } 514*0b57cec5SDimitry Andric 515*0b57cec5SDimitry Andric bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 516*0b57cec5SDimitry Andric ObjCPropertyDecl *PD = D->getPropertyDecl(); 517*0b57cec5SDimitry Andric auto *Container = cast<ObjCImplDecl>(D->getDeclContext()); 518*0b57cec5SDimitry Andric SourceLocation Loc = D->getLocation(); 519*0b57cec5SDimitry Andric SymbolRoleSet Roles = 0; 520*0b57cec5SDimitry Andric SmallVector<SymbolRelation, 1> Relations; 521*0b57cec5SDimitry Andric 522*0b57cec5SDimitry Andric if (ObjCIvarDecl *ID = D->getPropertyIvarDecl()) 523*0b57cec5SDimitry Andric Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID}); 524*0b57cec5SDimitry Andric if (Loc.isInvalid()) { 525*0b57cec5SDimitry Andric Loc = Container->getLocation(); 526*0b57cec5SDimitry Andric Roles |= (SymbolRoleSet)SymbolRole::Implicit; 527*0b57cec5SDimitry Andric } 528*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); 529*0b57cec5SDimitry Andric 530*0b57cec5SDimitry Andric if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 531*0b57cec5SDimitry Andric return true; 532*0b57cec5SDimitry Andric 533*0b57cec5SDimitry Andric assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 534*0b57cec5SDimitry Andric SymbolRoleSet AccessorMethodRoles = 535*0b57cec5SDimitry Andric SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit); 536*0b57cec5SDimitry Andric if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 537*0b57cec5SDimitry Andric if (MD->isPropertyAccessor() && 538*0b57cec5SDimitry Andric !hasUserDefined(MD, Container)) 539*0b57cec5SDimitry Andric IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 540*0b57cec5SDimitry Andric } 541*0b57cec5SDimitry Andric if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 542*0b57cec5SDimitry Andric if (MD->isPropertyAccessor() && 543*0b57cec5SDimitry Andric !hasUserDefined(MD, Container)) 544*0b57cec5SDimitry Andric IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 545*0b57cec5SDimitry Andric } 546*0b57cec5SDimitry Andric if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 547*0b57cec5SDimitry Andric if (IvarD->getSynthesize()) { 548*0b57cec5SDimitry Andric // For synthesized ivars, use the location of its name in the 549*0b57cec5SDimitry Andric // corresponding @synthesize. If there isn't one, use the containing 550*0b57cec5SDimitry Andric // @implementation's location, rather than the property's location, 551*0b57cec5SDimitry Andric // otherwise the header file containing the @interface will have different 552*0b57cec5SDimitry Andric // indexing contents based on whether the @implementation was present or 553*0b57cec5SDimitry Andric // not in the translation unit. 554*0b57cec5SDimitry Andric SymbolRoleSet IvarRoles = 0; 555*0b57cec5SDimitry Andric SourceLocation IvarLoc = D->getPropertyIvarDeclLoc(); 556*0b57cec5SDimitry Andric if (D->getLocation().isInvalid()) { 557*0b57cec5SDimitry Andric IvarLoc = Container->getLocation(); 558*0b57cec5SDimitry Andric IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 559*0b57cec5SDimitry Andric } else if (D->getLocation() == IvarLoc) { 560*0b57cec5SDimitry Andric IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 561*0b57cec5SDimitry Andric } 562*0b57cec5SDimitry Andric TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); 563*0b57cec5SDimitry Andric } else { 564*0b57cec5SDimitry Andric IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, 565*0b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 566*0b57cec5SDimitry Andric } 567*0b57cec5SDimitry Andric } 568*0b57cec5SDimitry Andric return true; 569*0b57cec5SDimitry Andric } 570*0b57cec5SDimitry Andric 571*0b57cec5SDimitry Andric bool VisitNamespaceDecl(const NamespaceDecl *D) { 572*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 573*0b57cec5SDimitry Andric IndexCtx.indexDeclContext(D); 574*0b57cec5SDimitry Andric return true; 575*0b57cec5SDimitry Andric } 576*0b57cec5SDimitry Andric 577*0b57cec5SDimitry Andric bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { 578*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 579*0b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 580*0b57cec5SDimitry Andric IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D, 581*0b57cec5SDimitry Andric D->getLexicalDeclContext()); 582*0b57cec5SDimitry Andric return true; 583*0b57cec5SDimitry Andric } 584*0b57cec5SDimitry Andric 585*0b57cec5SDimitry Andric bool VisitUsingDecl(const UsingDecl *D) { 586*0b57cec5SDimitry Andric IndexCtx.handleDecl(D); 587*0b57cec5SDimitry Andric 588*0b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 589*0b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 590*0b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 591*0b57cec5SDimitry Andric D->getLexicalDeclContext()); 592*0b57cec5SDimitry Andric for (const auto *I : D->shadows()) 593*0b57cec5SDimitry Andric IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, 594*0b57cec5SDimitry Andric D->getLexicalDeclContext(), SymbolRoleSet()); 595*0b57cec5SDimitry Andric return true; 596*0b57cec5SDimitry Andric } 597*0b57cec5SDimitry Andric 598*0b57cec5SDimitry Andric bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 599*0b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 600*0b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 601*0b57cec5SDimitry Andric 602*0b57cec5SDimitry Andric // NNS for the local 'using namespace' directives is visited by the body 603*0b57cec5SDimitry Andric // visitor. 604*0b57cec5SDimitry Andric if (!D->getParentFunctionOrMethod()) 605*0b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 606*0b57cec5SDimitry Andric D->getLexicalDeclContext()); 607*0b57cec5SDimitry Andric 608*0b57cec5SDimitry Andric return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 609*0b57cec5SDimitry Andric D->getLocation(), Parent, 610*0b57cec5SDimitry Andric D->getLexicalDeclContext(), 611*0b57cec5SDimitry Andric SymbolRoleSet()); 612*0b57cec5SDimitry Andric } 613*0b57cec5SDimitry Andric 614*0b57cec5SDimitry Andric bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { 615*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 616*0b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 617*0b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 618*0b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 619*0b57cec5SDimitry Andric D->getLexicalDeclContext()); 620*0b57cec5SDimitry Andric return true; 621*0b57cec5SDimitry Andric } 622*0b57cec5SDimitry Andric 623*0b57cec5SDimitry Andric bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { 624*0b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 625*0b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 626*0b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 627*0b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 628*0b57cec5SDimitry Andric D->getLexicalDeclContext()); 629*0b57cec5SDimitry Andric return true; 630*0b57cec5SDimitry Andric } 631*0b57cec5SDimitry Andric 632*0b57cec5SDimitry Andric bool VisitClassTemplateSpecializationDecl(const 633*0b57cec5SDimitry Andric ClassTemplateSpecializationDecl *D) { 634*0b57cec5SDimitry Andric // FIXME: Notify subsequent callbacks if info comes from implicit 635*0b57cec5SDimitry Andric // instantiation. 636*0b57cec5SDimitry Andric llvm::PointerUnion<ClassTemplateDecl *, 637*0b57cec5SDimitry Andric ClassTemplatePartialSpecializationDecl *> 638*0b57cec5SDimitry Andric Template = D->getSpecializedTemplateOrPartial(); 639*0b57cec5SDimitry Andric const Decl *SpecializationOf = 640*0b57cec5SDimitry Andric Template.is<ClassTemplateDecl *>() 641*0b57cec5SDimitry Andric ? (Decl *)Template.get<ClassTemplateDecl *>() 642*0b57cec5SDimitry Andric : Template.get<ClassTemplatePartialSpecializationDecl *>(); 643*0b57cec5SDimitry Andric if (!D->isThisDeclarationADefinition()) 644*0b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 645*0b57cec5SDimitry Andric IndexCtx.indexTagDecl( 646*0b57cec5SDimitry Andric D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 647*0b57cec5SDimitry Andric SpecializationOf)); 648*0b57cec5SDimitry Andric if (TypeSourceInfo *TSI = D->getTypeAsWritten()) 649*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr, 650*0b57cec5SDimitry Andric D->getLexicalDeclContext()); 651*0b57cec5SDimitry Andric return true; 652*0b57cec5SDimitry Andric } 653*0b57cec5SDimitry Andric 654*0b57cec5SDimitry Andric static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) { 655*0b57cec5SDimitry Andric // We want to index the template parameters only once when indexing the 656*0b57cec5SDimitry Andric // canonical declaration. 657*0b57cec5SDimitry Andric if (!D) 658*0b57cec5SDimitry Andric return false; 659*0b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) 660*0b57cec5SDimitry Andric return FD->getCanonicalDecl() == FD; 661*0b57cec5SDimitry Andric else if (const auto *TD = dyn_cast<TagDecl>(D)) 662*0b57cec5SDimitry Andric return TD->getCanonicalDecl() == TD; 663*0b57cec5SDimitry Andric else if (const auto *VD = dyn_cast<VarDecl>(D)) 664*0b57cec5SDimitry Andric return VD->getCanonicalDecl() == VD; 665*0b57cec5SDimitry Andric return true; 666*0b57cec5SDimitry Andric } 667*0b57cec5SDimitry Andric 668*0b57cec5SDimitry Andric bool VisitTemplateDecl(const TemplateDecl *D) { 669*0b57cec5SDimitry Andric 670*0b57cec5SDimitry Andric const NamedDecl *Parent = D->getTemplatedDecl(); 671*0b57cec5SDimitry Andric if (!Parent) 672*0b57cec5SDimitry Andric return true; 673*0b57cec5SDimitry Andric 674*0b57cec5SDimitry Andric // Index the default values for the template parameters. 675*0b57cec5SDimitry Andric if (D->getTemplateParameters() && 676*0b57cec5SDimitry Andric shouldIndexTemplateParameterDefaultValue(Parent)) { 677*0b57cec5SDimitry Andric const TemplateParameterList *Params = D->getTemplateParameters(); 678*0b57cec5SDimitry Andric for (const NamedDecl *TP : *Params) { 679*0b57cec5SDimitry Andric if (IndexCtx.shouldIndexTemplateParameters()) 680*0b57cec5SDimitry Andric IndexCtx.handleDecl(TP); 681*0b57cec5SDimitry Andric if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) { 682*0b57cec5SDimitry Andric if (TTP->hasDefaultArgument()) 683*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent); 684*0b57cec5SDimitry Andric } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) { 685*0b57cec5SDimitry Andric if (NTTP->hasDefaultArgument()) 686*0b57cec5SDimitry Andric IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent); 687*0b57cec5SDimitry Andric } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) { 688*0b57cec5SDimitry Andric if (TTPD->hasDefaultArgument()) 689*0b57cec5SDimitry Andric handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, 690*0b57cec5SDimitry Andric TP->getLexicalDeclContext()); 691*0b57cec5SDimitry Andric } 692*0b57cec5SDimitry Andric } 693*0b57cec5SDimitry Andric } 694*0b57cec5SDimitry Andric 695*0b57cec5SDimitry Andric return Visit(Parent); 696*0b57cec5SDimitry Andric } 697*0b57cec5SDimitry Andric 698*0b57cec5SDimitry Andric bool VisitFriendDecl(const FriendDecl *D) { 699*0b57cec5SDimitry Andric if (auto ND = D->getFriendDecl()) { 700*0b57cec5SDimitry Andric // FIXME: Ignore a class template in a dependent context, these are not 701*0b57cec5SDimitry Andric // linked properly with their redeclarations, ending up with duplicate 702*0b57cec5SDimitry Andric // USRs. 703*0b57cec5SDimitry Andric // See comment "Friend templates are visible in fairly strange ways." in 704*0b57cec5SDimitry Andric // SemaTemplate.cpp which precedes code that prevents the friend template 705*0b57cec5SDimitry Andric // from becoming visible from the enclosing context. 706*0b57cec5SDimitry Andric if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext()) 707*0b57cec5SDimitry Andric return true; 708*0b57cec5SDimitry Andric return Visit(ND); 709*0b57cec5SDimitry Andric } 710*0b57cec5SDimitry Andric if (auto Ty = D->getFriendType()) { 711*0b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext())); 712*0b57cec5SDimitry Andric } 713*0b57cec5SDimitry Andric return true; 714*0b57cec5SDimitry Andric } 715*0b57cec5SDimitry Andric 716*0b57cec5SDimitry Andric bool VisitImportDecl(const ImportDecl *D) { 717*0b57cec5SDimitry Andric return IndexCtx.importedModule(D); 718*0b57cec5SDimitry Andric } 719*0b57cec5SDimitry Andric 720*0b57cec5SDimitry Andric bool VisitStaticAssertDecl(const StaticAssertDecl *D) { 721*0b57cec5SDimitry Andric IndexCtx.indexBody(D->getAssertExpr(), 722*0b57cec5SDimitry Andric dyn_cast<NamedDecl>(D->getDeclContext()), 723*0b57cec5SDimitry Andric D->getLexicalDeclContext()); 724*0b57cec5SDimitry Andric return true; 725*0b57cec5SDimitry Andric } 726*0b57cec5SDimitry Andric }; 727*0b57cec5SDimitry Andric 728*0b57cec5SDimitry Andric } // anonymous namespace 729*0b57cec5SDimitry Andric 730*0b57cec5SDimitry Andric bool IndexingContext::indexDecl(const Decl *D) { 731*0b57cec5SDimitry Andric if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 732*0b57cec5SDimitry Andric return true; 733*0b57cec5SDimitry Andric 734*0b57cec5SDimitry Andric if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation()) 735*0b57cec5SDimitry Andric return true; 736*0b57cec5SDimitry Andric 737*0b57cec5SDimitry Andric IndexingDeclVisitor Visitor(*this); 738*0b57cec5SDimitry Andric bool ShouldContinue = Visitor.Visit(D); 739*0b57cec5SDimitry Andric if (!ShouldContinue) 740*0b57cec5SDimitry Andric return false; 741*0b57cec5SDimitry Andric 742*0b57cec5SDimitry Andric if (!Visitor.Handled && isa<DeclContext>(D)) 743*0b57cec5SDimitry Andric return indexDeclContext(cast<DeclContext>(D)); 744*0b57cec5SDimitry Andric 745*0b57cec5SDimitry Andric return true; 746*0b57cec5SDimitry Andric } 747*0b57cec5SDimitry Andric 748*0b57cec5SDimitry Andric bool IndexingContext::indexDeclContext(const DeclContext *DC) { 749*0b57cec5SDimitry Andric for (const auto *I : DC->decls()) 750*0b57cec5SDimitry Andric if (!indexDecl(I)) 751*0b57cec5SDimitry Andric return false; 752*0b57cec5SDimitry Andric return true; 753*0b57cec5SDimitry Andric } 754*0b57cec5SDimitry Andric 755*0b57cec5SDimitry Andric bool IndexingContext::indexTopLevelDecl(const Decl *D) { 756*0b57cec5SDimitry Andric if (D->getLocation().isInvalid()) 757*0b57cec5SDimitry Andric return true; 758*0b57cec5SDimitry Andric 759*0b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(D)) 760*0b57cec5SDimitry Andric return true; // Wait for the objc container. 761*0b57cec5SDimitry Andric 762*0b57cec5SDimitry Andric return indexDecl(D); 763*0b57cec5SDimitry Andric } 764*0b57cec5SDimitry Andric 765*0b57cec5SDimitry Andric bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 766*0b57cec5SDimitry Andric for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 767*0b57cec5SDimitry Andric if (!indexTopLevelDecl(*I)) 768*0b57cec5SDimitry Andric return false; 769*0b57cec5SDimitry Andric return true; 770*0b57cec5SDimitry Andric } 771