10b57cec5SDimitry Andric //===- IndexDecl.cpp - Indexing declarations ------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "IndexingContext.h" 10*480093f4SDimitry Andric #include "clang/AST/Attr.h" 110b57cec5SDimitry Andric #include "clang/AST/DeclVisitor.h" 12*480093f4SDimitry Andric #include "clang/Index/IndexDataConsumer.h" 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric using namespace clang; 150b57cec5SDimitry Andric using namespace index; 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #define TRY_DECL(D,CALL_EXPR) \ 180b57cec5SDimitry Andric do { \ 190b57cec5SDimitry Andric if (!IndexCtx.shouldIndex(D)) return true; \ 200b57cec5SDimitry Andric if (!CALL_EXPR) \ 210b57cec5SDimitry Andric return false; \ 220b57cec5SDimitry Andric } while (0) 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define TRY_TO(CALL_EXPR) \ 250b57cec5SDimitry Andric do { \ 260b57cec5SDimitry Andric if (!CALL_EXPR) \ 270b57cec5SDimitry Andric return false; \ 280b57cec5SDimitry Andric } while (0) 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { 330b57cec5SDimitry Andric IndexingContext &IndexCtx; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric public: 360b57cec5SDimitry Andric explicit IndexingDeclVisitor(IndexingContext &indexCtx) 370b57cec5SDimitry Andric : IndexCtx(indexCtx) { } 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric bool Handled = true; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric bool VisitDecl(const Decl *D) { 420b57cec5SDimitry Andric Handled = false; 430b57cec5SDimitry Andric return true; 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc, 470b57cec5SDimitry Andric const NamedDecl *Parent, 480b57cec5SDimitry Andric const DeclContext *DC) { 490b57cec5SDimitry Andric const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo(); 500b57cec5SDimitry Andric switch (TALoc.getArgument().getKind()) { 510b57cec5SDimitry Andric case TemplateArgument::Expression: 520b57cec5SDimitry Andric IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC); 530b57cec5SDimitry Andric break; 540b57cec5SDimitry Andric case TemplateArgument::Type: 550b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC); 560b57cec5SDimitry Andric break; 570b57cec5SDimitry Andric case TemplateArgument::Template: 580b57cec5SDimitry Andric case TemplateArgument::TemplateExpansion: 590b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(), 600b57cec5SDimitry Andric Parent, DC); 610b57cec5SDimitry Andric if (const TemplateDecl *TD = TALoc.getArgument() 620b57cec5SDimitry Andric .getAsTemplateOrTemplatePattern() 630b57cec5SDimitry Andric .getAsTemplateDecl()) { 640b57cec5SDimitry Andric if (const NamedDecl *TTD = TD->getTemplatedDecl()) 650b57cec5SDimitry Andric IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric break; 680b57cec5SDimitry Andric default: 690b57cec5SDimitry Andric break; 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 73*480093f4SDimitry Andric /// Returns true if the given method has been defined explicitly by the 74*480093f4SDimitry Andric /// user. 75*480093f4SDimitry Andric static bool hasUserDefined(const ObjCMethodDecl *D, 76*480093f4SDimitry Andric const ObjCImplDecl *Container) { 77*480093f4SDimitry Andric const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), 78*480093f4SDimitry Andric D->isInstanceMethod()); 79*480093f4SDimitry Andric return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition() && 80*480093f4SDimitry Andric !MD->isSynthesizedAccessorStub(); 81*480093f4SDimitry Andric } 82*480093f4SDimitry Andric 83*480093f4SDimitry Andric 840b57cec5SDimitry Andric void handleDeclarator(const DeclaratorDecl *D, 850b57cec5SDimitry Andric const NamedDecl *Parent = nullptr, 860b57cec5SDimitry Andric bool isIBType = false) { 870b57cec5SDimitry Andric if (!Parent) Parent = D; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent, 900b57cec5SDimitry Andric Parent->getLexicalDeclContext(), 910b57cec5SDimitry Andric /*isBase=*/false, isIBType); 920b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); 930b57cec5SDimitry Andric if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 940b57cec5SDimitry Andric if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { 950b57cec5SDimitry Andric auto *DC = Parm->getDeclContext(); 960b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(DC)) { 970b57cec5SDimitry Andric if (IndexCtx.shouldIndexParametersInDeclarations() || 980b57cec5SDimitry Andric FD->isThisDeclarationADefinition()) 990b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 1000b57cec5SDimitry Andric } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) { 1010b57cec5SDimitry Andric if (MD->isThisDeclarationADefinition()) 1020b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 1030b57cec5SDimitry Andric } else { 1040b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1070b57cec5SDimitry Andric if (IndexCtx.shouldIndexParametersInDeclarations() || 1080b57cec5SDimitry Andric FD->isThisDeclarationADefinition()) { 1090b57cec5SDimitry Andric for (auto PI : FD->parameters()) { 1100b57cec5SDimitry Andric IndexCtx.handleDecl(PI); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric } else { 1150b57cec5SDimitry Andric // Index the default parameter value for function definitions. 1160b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 1170b57cec5SDimitry Andric if (FD->isThisDeclarationADefinition()) { 1180b57cec5SDimitry Andric for (const auto *PV : FD->parameters()) { 1190b57cec5SDimitry Andric if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() && 1200b57cec5SDimitry Andric !PV->hasUnparsedDefaultArg()) 1210b57cec5SDimitry Andric IndexCtx.indexBody(PV->getDefaultArg(), D); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric bool handleObjCMethod(const ObjCMethodDecl *D, 1290b57cec5SDimitry Andric const ObjCPropertyDecl *AssociatedProp = nullptr) { 1300b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 1310b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl*, 4> Overriden; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric D->getOverriddenMethods(Overriden); 1340b57cec5SDimitry Andric for(auto overridden: Overriden) { 1350b57cec5SDimitry Andric Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf, 1360b57cec5SDimitry Andric overridden); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric if (AssociatedProp) 1390b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf, 1400b57cec5SDimitry Andric AssociatedProp); 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // getLocation() returns beginning token of a method declaration, but for 1430b57cec5SDimitry Andric // indexing purposes we want to point to the base name. 1440b57cec5SDimitry Andric SourceLocation MethodLoc = D->getSelectorStartLoc(); 1450b57cec5SDimitry Andric if (MethodLoc.isInvalid()) 1460b57cec5SDimitry Andric MethodLoc = D->getLocation(); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric SourceLocation AttrLoc; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric // check for (getter=/setter=) 1510b57cec5SDimitry Andric if (AssociatedProp) { 1520b57cec5SDimitry Andric bool isGetter = !D->param_size(); 1530b57cec5SDimitry Andric AttrLoc = isGetter ? 1540b57cec5SDimitry Andric AssociatedProp->getGetterNameLoc(): 1550b57cec5SDimitry Andric AssociatedProp->getSetterNameLoc(); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic; 1590b57cec5SDimitry Andric if (D->isImplicit()) { 1600b57cec5SDimitry Andric if (AttrLoc.isValid()) { 1610b57cec5SDimitry Andric MethodLoc = AttrLoc; 1620b57cec5SDimitry Andric } else { 1630b57cec5SDimitry Andric Roles |= (SymbolRoleSet)SymbolRole::Implicit; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric } else if (AttrLoc.isValid()) { 1660b57cec5SDimitry Andric IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()), 1670b57cec5SDimitry Andric D->getDeclContext(), 0); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); 1710b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); 1720b57cec5SDimitry Andric bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); 1730b57cec5SDimitry Andric for (const auto *I : D->parameters()) { 1740b57cec5SDimitry Andric handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst); 1750b57cec5SDimitry Andric hasIBActionAndFirst = false; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 1790b57cec5SDimitry Andric const Stmt *Body = D->getBody(); 1800b57cec5SDimitry Andric if (Body) { 1810b57cec5SDimitry Andric IndexCtx.indexBody(Body, D, D); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric return true; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric /// Gather the declarations which the given declaration \D overrides in a 1880b57cec5SDimitry Andric /// pseudo-override manner. 1890b57cec5SDimitry Andric /// 1900b57cec5SDimitry Andric /// Pseudo-overrides occur when a class template specialization declares 1910b57cec5SDimitry Andric /// a declaration that has the same name as a similar declaration in the 1920b57cec5SDimitry Andric /// non-specialized template. 1930b57cec5SDimitry Andric void 1940b57cec5SDimitry Andric gatherTemplatePseudoOverrides(const NamedDecl *D, 1950b57cec5SDimitry Andric SmallVectorImpl<SymbolRelation> &Relations) { 1960b57cec5SDimitry Andric if (!IndexCtx.getLangOpts().CPlusPlus) 1970b57cec5SDimitry Andric return; 1980b57cec5SDimitry Andric const auto *CTSD = 1990b57cec5SDimitry Andric dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext()); 2000b57cec5SDimitry Andric if (!CTSD) 2010b57cec5SDimitry Andric return; 2020b57cec5SDimitry Andric llvm::PointerUnion<ClassTemplateDecl *, 2030b57cec5SDimitry Andric ClassTemplatePartialSpecializationDecl *> 2040b57cec5SDimitry Andric Template = CTSD->getSpecializedTemplateOrPartial(); 2050b57cec5SDimitry Andric if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) { 2060b57cec5SDimitry Andric const CXXRecordDecl *Pattern = CTD->getTemplatedDecl(); 2070b57cec5SDimitry Andric bool TypeOverride = isa<TypeDecl>(D); 2080b57cec5SDimitry Andric for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) { 2090b57cec5SDimitry Andric if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) 2100b57cec5SDimitry Andric ND = CTD->getTemplatedDecl(); 2110b57cec5SDimitry Andric if (ND->isImplicit()) 2120b57cec5SDimitry Andric continue; 2130b57cec5SDimitry Andric // Types can override other types. 2140b57cec5SDimitry Andric if (!TypeOverride) { 2150b57cec5SDimitry Andric if (ND->getKind() != D->getKind()) 2160b57cec5SDimitry Andric continue; 2170b57cec5SDimitry Andric } else if (!isa<TypeDecl>(ND)) 2180b57cec5SDimitry Andric continue; 2190b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { 2200b57cec5SDimitry Andric const auto *DFD = cast<FunctionDecl>(D); 2210b57cec5SDimitry Andric // Function overrides are approximated using the number of parameters. 2220b57cec5SDimitry Andric if (FD->getStorageClass() != DFD->getStorageClass() || 2230b57cec5SDimitry Andric FD->getNumParams() != DFD->getNumParams()) 2240b57cec5SDimitry Andric continue; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric Relations.emplace_back( 2270b57cec5SDimitry Andric SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric bool VisitFunctionDecl(const FunctionDecl *D) { 2330b57cec5SDimitry Andric SymbolRoleSet Roles{}; 2340b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 2350b57cec5SDimitry Andric if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) { 2360b57cec5SDimitry Andric if (CXXMD->isVirtual()) 2370b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Dynamic; 2380b57cec5SDimitry Andric for (const CXXMethodDecl *O : CXXMD->overridden_methods()) { 2390b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 2430b57cec5SDimitry Andric if (const auto *Base = D->getPrimaryTemplate()) 2440b57cec5SDimitry Andric Relations.push_back( 2450b57cec5SDimitry Andric SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 2460b57cec5SDimitry Andric Base->getTemplatedDecl())); 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations)); 2490b57cec5SDimitry Andric handleDeclarator(D); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 2520b57cec5SDimitry Andric IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(), 2530b57cec5SDimitry Andric Ctor->getParent(), Ctor->getDeclContext(), 2540b57cec5SDimitry Andric (unsigned)SymbolRole::NameReference); 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric // Constructor initializers. 2570b57cec5SDimitry Andric for (const auto *Init : Ctor->inits()) { 2580b57cec5SDimitry Andric if (Init->isWritten()) { 2590b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 2600b57cec5SDimitry Andric if (const FieldDecl *Member = Init->getAnyMember()) 2610b57cec5SDimitry Andric IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, 2620b57cec5SDimitry Andric (unsigned)SymbolRole::Write); 2630b57cec5SDimitry Andric IndexCtx.indexBody(Init->getInit(), D, D); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) { 2670b57cec5SDimitry Andric if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { 2680b57cec5SDimitry Andric IndexCtx.handleReference(Dtor->getParent(), 2690b57cec5SDimitry Andric TypeNameInfo->getTypeLoc().getBeginLoc(), 2700b57cec5SDimitry Andric Dtor->getParent(), Dtor->getDeclContext(), 2710b57cec5SDimitry Andric (unsigned)SymbolRole::NameReference); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) { 2740b57cec5SDimitry Andric IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(), 2750b57cec5SDimitry Andric Guide->getLocation(), Guide, 2760b57cec5SDimitry Andric Guide->getDeclContext()); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric // Template specialization arguments. 2790b57cec5SDimitry Andric if (const ASTTemplateArgumentListInfo *TemplateArgInfo = 2800b57cec5SDimitry Andric D->getTemplateSpecializationArgsAsWritten()) { 2810b57cec5SDimitry Andric for (const auto &Arg : TemplateArgInfo->arguments()) 2820b57cec5SDimitry Andric handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 2860b57cec5SDimitry Andric const Stmt *Body = D->getBody(); 2870b57cec5SDimitry Andric if (Body) { 2880b57cec5SDimitry Andric IndexCtx.indexBody(Body, D, D); 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric return true; 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric bool VisitVarDecl(const VarDecl *D) { 2950b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 2960b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 2970b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 2980b57cec5SDimitry Andric handleDeclarator(D); 2990b57cec5SDimitry Andric IndexCtx.indexBody(D->getInit(), D); 3000b57cec5SDimitry Andric return true; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric bool VisitDecompositionDecl(const DecompositionDecl *D) { 3040b57cec5SDimitry Andric for (const auto *Binding : D->bindings()) 3050b57cec5SDimitry Andric TRY_DECL(Binding, IndexCtx.handleDecl(Binding)); 3060b57cec5SDimitry Andric return Base::VisitDecompositionDecl(D); 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric bool VisitFieldDecl(const FieldDecl *D) { 3100b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 3110b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3120b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 3130b57cec5SDimitry Andric handleDeclarator(D); 3140b57cec5SDimitry Andric if (D->isBitField()) 3150b57cec5SDimitry Andric IndexCtx.indexBody(D->getBitWidth(), D); 3160b57cec5SDimitry Andric else if (D->hasInClassInitializer()) 3170b57cec5SDimitry Andric IndexCtx.indexBody(D->getInClassInitializer(), D); 3180b57cec5SDimitry Andric return true; 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { 3220b57cec5SDimitry Andric if (D->getSynthesize()) { 3230b57cec5SDimitry Andric // handled in VisitObjCPropertyImplDecl 3240b57cec5SDimitry Andric return true; 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 3270b57cec5SDimitry Andric handleDeclarator(D); 3280b57cec5SDimitry Andric return true; 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 3320b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 3330b57cec5SDimitry Andric handleDeclarator(D); 3340b57cec5SDimitry Andric return true; 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 3380b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 3390b57cec5SDimitry Andric IndexCtx.indexBody(D->getInitExpr(), D); 3400b57cec5SDimitry Andric return true; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 3440b57cec5SDimitry Andric if (!D->isTransparentTag()) { 3450b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 3460b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3470b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 3480b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric return true; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric bool VisitTagDecl(const TagDecl *D) { 3540b57cec5SDimitry Andric // Non-free standing tags are handled in indexTypeSourceInfo. 3550b57cec5SDimitry Andric if (D->isFreeStanding()) { 3560b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 3570b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 3580b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3590b57cec5SDimitry Andric IndexCtx.indexTagDecl(D, Relations); 3600b57cec5SDimitry Andric } else { 3610b57cec5SDimitry Andric SmallVector<SymbolRelation, 1> Relations; 3620b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3630b57cec5SDimitry Andric return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(), 3640b57cec5SDimitry Andric Relations, D->getLexicalDeclContext()); 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric return true; 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric bool handleReferencedProtocols(const ObjCProtocolList &ProtList, 3710b57cec5SDimitry Andric const ObjCContainerDecl *ContD, 3720b57cec5SDimitry Andric SourceLocation SuperLoc) { 3730b57cec5SDimitry Andric ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 3740b57cec5SDimitry Andric for (ObjCInterfaceDecl::protocol_iterator 3750b57cec5SDimitry Andric I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 3760b57cec5SDimitry Andric SourceLocation Loc = *LI; 3770b57cec5SDimitry Andric ObjCProtocolDecl *PD = *I; 3780b57cec5SDimitry Andric SymbolRoleSet roles{}; 3790b57cec5SDimitry Andric if (Loc == SuperLoc) 3800b57cec5SDimitry Andric roles |= (SymbolRoleSet)SymbolRole::Implicit; 3810b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, 3820b57cec5SDimitry Andric SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric return true; 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 3880b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 3890b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 3900b57cec5SDimitry Andric SourceLocation SuperLoc = D->getSuperClassLoc(); 3910b57cec5SDimitry Andric if (auto *SuperD = D->getSuperClass()) { 3920b57cec5SDimitry Andric bool hasSuperTypedef = false; 3930b57cec5SDimitry Andric if (auto *TInfo = D->getSuperClassTInfo()) { 3940b57cec5SDimitry Andric if (auto *TT = TInfo->getType()->getAs<TypedefType>()) { 3950b57cec5SDimitry Andric if (auto *TD = TT->getDecl()) { 3960b57cec5SDimitry Andric hasSuperTypedef = true; 3970b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, 3980b57cec5SDimitry Andric SymbolRoleSet())); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric SymbolRoleSet superRoles{}; 4030b57cec5SDimitry Andric if (hasSuperTypedef) 4040b57cec5SDimitry Andric superRoles |= (SymbolRoleSet)SymbolRole::Implicit; 4050b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, 4060b57cec5SDimitry Andric SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 4090b57cec5SDimitry Andric SuperLoc)); 4100b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 4110b57cec5SDimitry Andric } else { 4120b57cec5SDimitry Andric return IndexCtx.handleReference(D, D->getLocation(), nullptr, 4130b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric return true; 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 4190b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 4200b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 4210b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 4220b57cec5SDimitry Andric /*SuperLoc=*/SourceLocation())); 4230b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 4240b57cec5SDimitry Andric } else { 4250b57cec5SDimitry Andric return IndexCtx.handleReference(D, D->getLocation(), nullptr, 4260b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric return true; 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 4320b57cec5SDimitry Andric const ObjCInterfaceDecl *Class = D->getClassInterface(); 4330b57cec5SDimitry Andric if (!Class) 4340b57cec5SDimitry Andric return true; 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric if (Class->isImplicitInterfaceDecl()) 4370b57cec5SDimitry Andric IndexCtx.handleDecl(Class); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric // Visit implicit @synthesize property implementations first as their 4420b57cec5SDimitry Andric // location is reported at the name of the @implementation block. This 4430b57cec5SDimitry Andric // serves no purpose other than to simplify the FileCheck-based tests. 4440b57cec5SDimitry Andric for (const auto *I : D->property_impls()) { 4450b57cec5SDimitry Andric if (I->getLocation().isInvalid()) 4460b57cec5SDimitry Andric IndexCtx.indexDecl(I); 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric for (const auto *I : D->decls()) { 4490b57cec5SDimitry Andric if (!isa<ObjCPropertyImplDecl>(I) || 4500b57cec5SDimitry Andric cast<ObjCPropertyImplDecl>(I)->getLocation().isValid()) 4510b57cec5SDimitry Andric IndexCtx.indexDecl(I); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric return true; 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 4580b57cec5SDimitry Andric if (!IndexCtx.shouldIndex(D)) 4590b57cec5SDimitry Andric return true; 4600b57cec5SDimitry Andric const ObjCInterfaceDecl *C = D->getClassInterface(); 4610b57cec5SDimitry Andric if (!C) 4620b57cec5SDimitry Andric return true; 4630b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), 4640b57cec5SDimitry Andric SymbolRelation{ 4650b57cec5SDimitry Andric (unsigned)SymbolRole::RelationExtendedBy, D 4660b57cec5SDimitry Andric })); 4670b57cec5SDimitry Andric SourceLocation CategoryLoc = D->getCategoryNameLoc(); 4680b57cec5SDimitry Andric if (!CategoryLoc.isValid()) 4690b57cec5SDimitry Andric CategoryLoc = D->getLocation(); 4700b57cec5SDimitry Andric TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); 4710b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 4720b57cec5SDimitry Andric /*SuperLoc=*/SourceLocation())); 4730b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 4740b57cec5SDimitry Andric return true; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 4780b57cec5SDimitry Andric const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 4790b57cec5SDimitry Andric if (!Cat) 4800b57cec5SDimitry Andric return true; 4810b57cec5SDimitry Andric const ObjCInterfaceDecl *C = D->getClassInterface(); 4820b57cec5SDimitry Andric if (C) 4830b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, 4840b57cec5SDimitry Andric SymbolRoleSet())); 4850b57cec5SDimitry Andric SourceLocation CategoryLoc = D->getCategoryNameLoc(); 4860b57cec5SDimitry Andric if (!CategoryLoc.isValid()) 4870b57cec5SDimitry Andric CategoryLoc = D->getLocation(); 4880b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); 4890b57cec5SDimitry Andric IndexCtx.indexDeclContext(D); 4900b57cec5SDimitry Andric return true; 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 4940b57cec5SDimitry Andric // Methods associated with a property, even user-declared ones, are 4950b57cec5SDimitry Andric // handled when we handle the property. 4960b57cec5SDimitry Andric if (D->isPropertyAccessor()) 4970b57cec5SDimitry Andric return true; 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric handleObjCMethod(D); 5000b57cec5SDimitry Andric return true; 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 5040b57cec5SDimitry Andric if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 5050b57cec5SDimitry Andric if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 5060b57cec5SDimitry Andric handleObjCMethod(MD, D); 5070b57cec5SDimitry Andric if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 5080b57cec5SDimitry Andric if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 5090b57cec5SDimitry Andric handleObjCMethod(MD, D); 5100b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 5110b57cec5SDimitry Andric if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) 5120b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, 5130b57cec5SDimitry Andric D->getLexicalDeclContext(), false, true); 5140b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 5150b57cec5SDimitry Andric return true; 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 5190b57cec5SDimitry Andric ObjCPropertyDecl *PD = D->getPropertyDecl(); 5200b57cec5SDimitry Andric auto *Container = cast<ObjCImplDecl>(D->getDeclContext()); 5210b57cec5SDimitry Andric SourceLocation Loc = D->getLocation(); 5220b57cec5SDimitry Andric SymbolRoleSet Roles = 0; 5230b57cec5SDimitry Andric SmallVector<SymbolRelation, 1> Relations; 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric if (ObjCIvarDecl *ID = D->getPropertyIvarDecl()) 5260b57cec5SDimitry Andric Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID}); 5270b57cec5SDimitry Andric if (Loc.isInvalid()) { 5280b57cec5SDimitry Andric Loc = Container->getLocation(); 5290b57cec5SDimitry Andric Roles |= (SymbolRoleSet)SymbolRole::Implicit; 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 5340b57cec5SDimitry Andric return true; 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 5370b57cec5SDimitry Andric SymbolRoleSet AccessorMethodRoles = 5380b57cec5SDimitry Andric SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit); 5390b57cec5SDimitry Andric if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 540*480093f4SDimitry Andric if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container)) 5410b57cec5SDimitry Andric IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 544*480093f4SDimitry Andric if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container)) 5450b57cec5SDimitry Andric IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 5480b57cec5SDimitry Andric if (IvarD->getSynthesize()) { 5490b57cec5SDimitry Andric // For synthesized ivars, use the location of its name in the 5500b57cec5SDimitry Andric // corresponding @synthesize. If there isn't one, use the containing 5510b57cec5SDimitry Andric // @implementation's location, rather than the property's location, 5520b57cec5SDimitry Andric // otherwise the header file containing the @interface will have different 5530b57cec5SDimitry Andric // indexing contents based on whether the @implementation was present or 5540b57cec5SDimitry Andric // not in the translation unit. 5550b57cec5SDimitry Andric SymbolRoleSet IvarRoles = 0; 5560b57cec5SDimitry Andric SourceLocation IvarLoc = D->getPropertyIvarDeclLoc(); 5570b57cec5SDimitry Andric if (D->getLocation().isInvalid()) { 5580b57cec5SDimitry Andric IvarLoc = Container->getLocation(); 5590b57cec5SDimitry Andric IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 5600b57cec5SDimitry Andric } else if (D->getLocation() == IvarLoc) { 5610b57cec5SDimitry Andric IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); 5640b57cec5SDimitry Andric } else { 5650b57cec5SDimitry Andric IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, 5660b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric } 5690b57cec5SDimitry Andric return true; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric bool VisitNamespaceDecl(const NamespaceDecl *D) { 5730b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 5740b57cec5SDimitry Andric IndexCtx.indexDeclContext(D); 5750b57cec5SDimitry Andric return true; 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { 5790b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 5800b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 5810b57cec5SDimitry Andric IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D, 5820b57cec5SDimitry Andric D->getLexicalDeclContext()); 5830b57cec5SDimitry Andric return true; 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric bool VisitUsingDecl(const UsingDecl *D) { 5870b57cec5SDimitry Andric IndexCtx.handleDecl(D); 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 5900b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 5910b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 5920b57cec5SDimitry Andric D->getLexicalDeclContext()); 5930b57cec5SDimitry Andric for (const auto *I : D->shadows()) 5940b57cec5SDimitry Andric IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, 5950b57cec5SDimitry Andric D->getLexicalDeclContext(), SymbolRoleSet()); 5960b57cec5SDimitry Andric return true; 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 6000b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 6010b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric // NNS for the local 'using namespace' directives is visited by the body 6040b57cec5SDimitry Andric // visitor. 6050b57cec5SDimitry Andric if (!D->getParentFunctionOrMethod()) 6060b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 6070b57cec5SDimitry Andric D->getLexicalDeclContext()); 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 6100b57cec5SDimitry Andric D->getLocation(), Parent, 6110b57cec5SDimitry Andric D->getLexicalDeclContext(), 6120b57cec5SDimitry Andric SymbolRoleSet()); 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { 6160b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 6170b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 6180b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 6190b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 6200b57cec5SDimitry Andric D->getLexicalDeclContext()); 6210b57cec5SDimitry Andric return true; 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { 6250b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 6260b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 6270b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 6280b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 6290b57cec5SDimitry Andric D->getLexicalDeclContext()); 6300b57cec5SDimitry Andric return true; 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric bool VisitClassTemplateSpecializationDecl(const 6340b57cec5SDimitry Andric ClassTemplateSpecializationDecl *D) { 6350b57cec5SDimitry Andric // FIXME: Notify subsequent callbacks if info comes from implicit 6360b57cec5SDimitry Andric // instantiation. 6370b57cec5SDimitry Andric llvm::PointerUnion<ClassTemplateDecl *, 6380b57cec5SDimitry Andric ClassTemplatePartialSpecializationDecl *> 6390b57cec5SDimitry Andric Template = D->getSpecializedTemplateOrPartial(); 6400b57cec5SDimitry Andric const Decl *SpecializationOf = 6410b57cec5SDimitry Andric Template.is<ClassTemplateDecl *>() 6420b57cec5SDimitry Andric ? (Decl *)Template.get<ClassTemplateDecl *>() 6430b57cec5SDimitry Andric : Template.get<ClassTemplatePartialSpecializationDecl *>(); 6440b57cec5SDimitry Andric if (!D->isThisDeclarationADefinition()) 6450b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 6460b57cec5SDimitry Andric IndexCtx.indexTagDecl( 6470b57cec5SDimitry Andric D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 6480b57cec5SDimitry Andric SpecializationOf)); 6490b57cec5SDimitry Andric if (TypeSourceInfo *TSI = D->getTypeAsWritten()) 6500b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr, 6510b57cec5SDimitry Andric D->getLexicalDeclContext()); 6520b57cec5SDimitry Andric return true; 6530b57cec5SDimitry Andric } 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) { 6560b57cec5SDimitry Andric // We want to index the template parameters only once when indexing the 6570b57cec5SDimitry Andric // canonical declaration. 6580b57cec5SDimitry Andric if (!D) 6590b57cec5SDimitry Andric return false; 6600b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) 6610b57cec5SDimitry Andric return FD->getCanonicalDecl() == FD; 6620b57cec5SDimitry Andric else if (const auto *TD = dyn_cast<TagDecl>(D)) 6630b57cec5SDimitry Andric return TD->getCanonicalDecl() == TD; 6640b57cec5SDimitry Andric else if (const auto *VD = dyn_cast<VarDecl>(D)) 6650b57cec5SDimitry Andric return VD->getCanonicalDecl() == VD; 6660b57cec5SDimitry Andric return true; 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric bool VisitTemplateDecl(const TemplateDecl *D) { 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric const NamedDecl *Parent = D->getTemplatedDecl(); 6720b57cec5SDimitry Andric if (!Parent) 6730b57cec5SDimitry Andric return true; 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric // Index the default values for the template parameters. 6760b57cec5SDimitry Andric if (D->getTemplateParameters() && 6770b57cec5SDimitry Andric shouldIndexTemplateParameterDefaultValue(Parent)) { 6780b57cec5SDimitry Andric const TemplateParameterList *Params = D->getTemplateParameters(); 6790b57cec5SDimitry Andric for (const NamedDecl *TP : *Params) { 6800b57cec5SDimitry Andric if (IndexCtx.shouldIndexTemplateParameters()) 6810b57cec5SDimitry Andric IndexCtx.handleDecl(TP); 6820b57cec5SDimitry Andric if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) { 6830b57cec5SDimitry Andric if (TTP->hasDefaultArgument()) 6840b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent); 6850b57cec5SDimitry Andric } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) { 6860b57cec5SDimitry Andric if (NTTP->hasDefaultArgument()) 6870b57cec5SDimitry Andric IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent); 6880b57cec5SDimitry Andric } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) { 6890b57cec5SDimitry Andric if (TTPD->hasDefaultArgument()) 6900b57cec5SDimitry Andric handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, 6910b57cec5SDimitry Andric TP->getLexicalDeclContext()); 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric return Visit(Parent); 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric bool VisitFriendDecl(const FriendDecl *D) { 7000b57cec5SDimitry Andric if (auto ND = D->getFriendDecl()) { 7010b57cec5SDimitry Andric // FIXME: Ignore a class template in a dependent context, these are not 7020b57cec5SDimitry Andric // linked properly with their redeclarations, ending up with duplicate 7030b57cec5SDimitry Andric // USRs. 7040b57cec5SDimitry Andric // See comment "Friend templates are visible in fairly strange ways." in 7050b57cec5SDimitry Andric // SemaTemplate.cpp which precedes code that prevents the friend template 7060b57cec5SDimitry Andric // from becoming visible from the enclosing context. 7070b57cec5SDimitry Andric if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext()) 7080b57cec5SDimitry Andric return true; 7090b57cec5SDimitry Andric return Visit(ND); 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric if (auto Ty = D->getFriendType()) { 7120b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext())); 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric return true; 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric bool VisitImportDecl(const ImportDecl *D) { 7180b57cec5SDimitry Andric return IndexCtx.importedModule(D); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric bool VisitStaticAssertDecl(const StaticAssertDecl *D) { 7220b57cec5SDimitry Andric IndexCtx.indexBody(D->getAssertExpr(), 7230b57cec5SDimitry Andric dyn_cast<NamedDecl>(D->getDeclContext()), 7240b57cec5SDimitry Andric D->getLexicalDeclContext()); 7250b57cec5SDimitry Andric return true; 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric }; 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric } // anonymous namespace 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric bool IndexingContext::indexDecl(const Decl *D) { 7320b57cec5SDimitry Andric if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 7330b57cec5SDimitry Andric return true; 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation()) 7360b57cec5SDimitry Andric return true; 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric IndexingDeclVisitor Visitor(*this); 7390b57cec5SDimitry Andric bool ShouldContinue = Visitor.Visit(D); 7400b57cec5SDimitry Andric if (!ShouldContinue) 7410b57cec5SDimitry Andric return false; 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric if (!Visitor.Handled && isa<DeclContext>(D)) 7440b57cec5SDimitry Andric return indexDeclContext(cast<DeclContext>(D)); 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric return true; 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric bool IndexingContext::indexDeclContext(const DeclContext *DC) { 7500b57cec5SDimitry Andric for (const auto *I : DC->decls()) 7510b57cec5SDimitry Andric if (!indexDecl(I)) 7520b57cec5SDimitry Andric return false; 7530b57cec5SDimitry Andric return true; 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric bool IndexingContext::indexTopLevelDecl(const Decl *D) { 7570b57cec5SDimitry Andric if (D->getLocation().isInvalid()) 7580b57cec5SDimitry Andric return true; 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(D)) 7610b57cec5SDimitry Andric return true; // Wait for the objc container. 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric return indexDecl(D); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 7670b57cec5SDimitry Andric for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 7680b57cec5SDimitry Andric if (!indexTopLevelDecl(*I)) 7690b57cec5SDimitry Andric return false; 7700b57cec5SDimitry Andric return true; 7710b57cec5SDimitry Andric } 772