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" 1081ad6265SDimitry Andric #include "clang/AST/ASTConcept.h" 11480093f4SDimitry Andric #include "clang/AST/Attr.h" 12349cc55cSDimitry Andric #include "clang/AST/Decl.h" 1381ad6265SDimitry Andric #include "clang/AST/DeclTemplate.h" 140b57cec5SDimitry Andric #include "clang/AST/DeclVisitor.h" 15480093f4SDimitry Andric #include "clang/Index/IndexDataConsumer.h" 1681ad6265SDimitry Andric #include "clang/Index/IndexSymbol.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric using namespace clang; 190b57cec5SDimitry Andric using namespace index; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #define TRY_DECL(D,CALL_EXPR) \ 220b57cec5SDimitry Andric do { \ 230b57cec5SDimitry Andric if (!IndexCtx.shouldIndex(D)) return true; \ 240b57cec5SDimitry Andric if (!CALL_EXPR) \ 250b57cec5SDimitry Andric return false; \ 260b57cec5SDimitry Andric } while (0) 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #define TRY_TO(CALL_EXPR) \ 290b57cec5SDimitry Andric do { \ 300b57cec5SDimitry Andric if (!CALL_EXPR) \ 310b57cec5SDimitry Andric return false; \ 320b57cec5SDimitry Andric } while (0) 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric namespace { 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { 370b57cec5SDimitry Andric IndexingContext &IndexCtx; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric public: 400b57cec5SDimitry Andric explicit IndexingDeclVisitor(IndexingContext &indexCtx) 410b57cec5SDimitry Andric : IndexCtx(indexCtx) { } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric bool Handled = true; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric bool VisitDecl(const Decl *D) { 460b57cec5SDimitry Andric Handled = false; 470b57cec5SDimitry Andric return true; 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc, 510b57cec5SDimitry Andric const NamedDecl *Parent, 520b57cec5SDimitry Andric const DeclContext *DC) { 530b57cec5SDimitry Andric const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo(); 540b57cec5SDimitry Andric switch (TALoc.getArgument().getKind()) { 550b57cec5SDimitry Andric case TemplateArgument::Expression: 560b57cec5SDimitry Andric IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC); 570b57cec5SDimitry Andric break; 580b57cec5SDimitry Andric case TemplateArgument::Type: 590b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC); 600b57cec5SDimitry Andric break; 610b57cec5SDimitry Andric case TemplateArgument::Template: 620b57cec5SDimitry Andric case TemplateArgument::TemplateExpansion: 630b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(), 640b57cec5SDimitry Andric Parent, DC); 650b57cec5SDimitry Andric if (const TemplateDecl *TD = TALoc.getArgument() 660b57cec5SDimitry Andric .getAsTemplateOrTemplatePattern() 670b57cec5SDimitry Andric .getAsTemplateDecl()) { 680b57cec5SDimitry Andric if (const NamedDecl *TTD = TD->getTemplatedDecl()) 690b57cec5SDimitry Andric IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric break; 720b57cec5SDimitry Andric default: 730b57cec5SDimitry Andric break; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 77480093f4SDimitry Andric /// Returns true if the given method has been defined explicitly by the 78480093f4SDimitry Andric /// user. 79480093f4SDimitry Andric static bool hasUserDefined(const ObjCMethodDecl *D, 80480093f4SDimitry Andric const ObjCImplDecl *Container) { 81480093f4SDimitry Andric const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), 82480093f4SDimitry Andric D->isInstanceMethod()); 83480093f4SDimitry Andric return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition() && 84480093f4SDimitry Andric !MD->isSynthesizedAccessorStub(); 85480093f4SDimitry Andric } 86480093f4SDimitry Andric 87480093f4SDimitry Andric 880b57cec5SDimitry Andric void handleDeclarator(const DeclaratorDecl *D, 890b57cec5SDimitry Andric const NamedDecl *Parent = nullptr, 900b57cec5SDimitry Andric bool isIBType = false) { 910b57cec5SDimitry Andric if (!Parent) Parent = D; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent, 940b57cec5SDimitry Andric Parent->getLexicalDeclContext(), 950b57cec5SDimitry Andric /*isBase=*/false, isIBType); 960b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); 975ffd83dbSDimitry Andric auto IndexDefaultParmeterArgument = [&](const ParmVarDecl *Parm, 985ffd83dbSDimitry Andric const NamedDecl *Parent) { 995ffd83dbSDimitry Andric if (Parm->hasDefaultArg() && !Parm->hasUninstantiatedDefaultArg() && 1005ffd83dbSDimitry Andric !Parm->hasUnparsedDefaultArg()) 1015ffd83dbSDimitry Andric IndexCtx.indexBody(Parm->getDefaultArg(), Parent); 1025ffd83dbSDimitry Andric }; 1030b57cec5SDimitry Andric if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 1040b57cec5SDimitry Andric if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { 1050b57cec5SDimitry Andric auto *DC = Parm->getDeclContext(); 1060b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(DC)) { 1070b57cec5SDimitry Andric if (IndexCtx.shouldIndexParametersInDeclarations() || 1080b57cec5SDimitry Andric FD->isThisDeclarationADefinition()) 1090b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 1100b57cec5SDimitry Andric } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) { 1110b57cec5SDimitry Andric if (MD->isThisDeclarationADefinition()) 1120b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 1130b57cec5SDimitry Andric } else { 1140b57cec5SDimitry Andric IndexCtx.handleDecl(Parm); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1170b57cec5SDimitry Andric if (IndexCtx.shouldIndexParametersInDeclarations() || 1180b57cec5SDimitry Andric FD->isThisDeclarationADefinition()) { 1195ffd83dbSDimitry Andric for (const auto *PI : FD->parameters()) { 1205ffd83dbSDimitry Andric IndexDefaultParmeterArgument(PI, D); 1210b57cec5SDimitry Andric IndexCtx.handleDecl(PI); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric } else { 1260b57cec5SDimitry Andric // Index the default parameter value for function definitions. 1270b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 1280b57cec5SDimitry Andric if (FD->isThisDeclarationADefinition()) { 1290b57cec5SDimitry Andric for (const auto *PV : FD->parameters()) { 1305ffd83dbSDimitry Andric IndexDefaultParmeterArgument(PV, D); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric } 13581ad6265SDimitry Andric if (auto *C = D->getTrailingRequiresClause()) 13681ad6265SDimitry Andric IndexCtx.indexBody(C, Parent); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric bool handleObjCMethod(const ObjCMethodDecl *D, 1400b57cec5SDimitry Andric const ObjCPropertyDecl *AssociatedProp = nullptr) { 1410b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 1420b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl*, 4> Overriden; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric D->getOverriddenMethods(Overriden); 1450b57cec5SDimitry Andric for(auto overridden: Overriden) { 1460b57cec5SDimitry Andric Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf, 1470b57cec5SDimitry Andric overridden); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric if (AssociatedProp) 1500b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf, 1510b57cec5SDimitry Andric AssociatedProp); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric // getLocation() returns beginning token of a method declaration, but for 1540b57cec5SDimitry Andric // indexing purposes we want to point to the base name. 1550b57cec5SDimitry Andric SourceLocation MethodLoc = D->getSelectorStartLoc(); 1560b57cec5SDimitry Andric if (MethodLoc.isInvalid()) 1570b57cec5SDimitry Andric MethodLoc = D->getLocation(); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric SourceLocation AttrLoc; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric // check for (getter=/setter=) 1620b57cec5SDimitry Andric if (AssociatedProp) { 1630b57cec5SDimitry Andric bool isGetter = !D->param_size(); 1640b57cec5SDimitry Andric AttrLoc = isGetter ? 1650b57cec5SDimitry Andric AssociatedProp->getGetterNameLoc(): 1660b57cec5SDimitry Andric AssociatedProp->getSetterNameLoc(); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic; 1700b57cec5SDimitry Andric if (D->isImplicit()) { 1710b57cec5SDimitry Andric if (AttrLoc.isValid()) { 1720b57cec5SDimitry Andric MethodLoc = AttrLoc; 1730b57cec5SDimitry Andric } else { 1740b57cec5SDimitry Andric Roles |= (SymbolRoleSet)SymbolRole::Implicit; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric } else if (AttrLoc.isValid()) { 1770b57cec5SDimitry Andric IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()), 1780b57cec5SDimitry Andric D->getDeclContext(), 0); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); 1820b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); 1830b57cec5SDimitry Andric bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); 1840b57cec5SDimitry Andric for (const auto *I : D->parameters()) { 1850b57cec5SDimitry Andric handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst); 1860b57cec5SDimitry Andric hasIBActionAndFirst = false; 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 1900b57cec5SDimitry Andric const Stmt *Body = D->getBody(); 1910b57cec5SDimitry Andric if (Body) { 1920b57cec5SDimitry Andric IndexCtx.indexBody(Body, D, D); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric return true; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric /// Gather the declarations which the given declaration \D overrides in a 1990b57cec5SDimitry Andric /// pseudo-override manner. 2000b57cec5SDimitry Andric /// 2010b57cec5SDimitry Andric /// Pseudo-overrides occur when a class template specialization declares 2020b57cec5SDimitry Andric /// a declaration that has the same name as a similar declaration in the 2030b57cec5SDimitry Andric /// non-specialized template. 2040b57cec5SDimitry Andric void 2050b57cec5SDimitry Andric gatherTemplatePseudoOverrides(const NamedDecl *D, 2060b57cec5SDimitry Andric SmallVectorImpl<SymbolRelation> &Relations) { 2070b57cec5SDimitry Andric if (!IndexCtx.getLangOpts().CPlusPlus) 2080b57cec5SDimitry Andric return; 2090b57cec5SDimitry Andric const auto *CTSD = 2100b57cec5SDimitry Andric dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext()); 2110b57cec5SDimitry Andric if (!CTSD) 2120b57cec5SDimitry Andric return; 2130b57cec5SDimitry Andric llvm::PointerUnion<ClassTemplateDecl *, 2140b57cec5SDimitry Andric ClassTemplatePartialSpecializationDecl *> 2150b57cec5SDimitry Andric Template = CTSD->getSpecializedTemplateOrPartial(); 2160b57cec5SDimitry Andric if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) { 2170b57cec5SDimitry Andric const CXXRecordDecl *Pattern = CTD->getTemplatedDecl(); 2180b57cec5SDimitry Andric bool TypeOverride = isa<TypeDecl>(D); 2190b57cec5SDimitry Andric for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) { 2200b57cec5SDimitry Andric if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) 2210b57cec5SDimitry Andric ND = CTD->getTemplatedDecl(); 2220b57cec5SDimitry Andric if (ND->isImplicit()) 2230b57cec5SDimitry Andric continue; 2240b57cec5SDimitry Andric // Types can override other types. 2250b57cec5SDimitry Andric if (!TypeOverride) { 2260b57cec5SDimitry Andric if (ND->getKind() != D->getKind()) 2270b57cec5SDimitry Andric continue; 2280b57cec5SDimitry Andric } else if (!isa<TypeDecl>(ND)) 2290b57cec5SDimitry Andric continue; 2300b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { 2310b57cec5SDimitry Andric const auto *DFD = cast<FunctionDecl>(D); 2320b57cec5SDimitry Andric // Function overrides are approximated using the number of parameters. 2330b57cec5SDimitry Andric if (FD->getStorageClass() != DFD->getStorageClass() || 2340b57cec5SDimitry Andric FD->getNumParams() != DFD->getNumParams()) 2350b57cec5SDimitry Andric continue; 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric Relations.emplace_back( 2380b57cec5SDimitry Andric SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric bool VisitFunctionDecl(const FunctionDecl *D) { 2440b57cec5SDimitry Andric SymbolRoleSet Roles{}; 2450b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 2460b57cec5SDimitry Andric if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) { 2470b57cec5SDimitry Andric if (CXXMD->isVirtual()) 2480b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Dynamic; 2490b57cec5SDimitry Andric for (const CXXMethodDecl *O : CXXMD->overridden_methods()) { 2500b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O); 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 2540b57cec5SDimitry Andric if (const auto *Base = D->getPrimaryTemplate()) 2550b57cec5SDimitry Andric Relations.push_back( 2560b57cec5SDimitry Andric SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 2570b57cec5SDimitry Andric Base->getTemplatedDecl())); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations)); 2600b57cec5SDimitry Andric handleDeclarator(D); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 2630b57cec5SDimitry Andric IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(), 2640b57cec5SDimitry Andric Ctor->getParent(), Ctor->getDeclContext(), 2650b57cec5SDimitry Andric (unsigned)SymbolRole::NameReference); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric // Constructor initializers. 2680b57cec5SDimitry Andric for (const auto *Init : Ctor->inits()) { 2690b57cec5SDimitry Andric if (Init->isWritten()) { 2700b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 2710b57cec5SDimitry Andric if (const FieldDecl *Member = Init->getAnyMember()) 2720b57cec5SDimitry Andric IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, 2730b57cec5SDimitry Andric (unsigned)SymbolRole::Write); 2740b57cec5SDimitry Andric IndexCtx.indexBody(Init->getInit(), D, D); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) { 2780b57cec5SDimitry Andric if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { 2790b57cec5SDimitry Andric IndexCtx.handleReference(Dtor->getParent(), 2800b57cec5SDimitry Andric TypeNameInfo->getTypeLoc().getBeginLoc(), 2810b57cec5SDimitry Andric Dtor->getParent(), Dtor->getDeclContext(), 2820b57cec5SDimitry Andric (unsigned)SymbolRole::NameReference); 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) { 2850b57cec5SDimitry Andric IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(), 2860b57cec5SDimitry Andric Guide->getLocation(), Guide, 2870b57cec5SDimitry Andric Guide->getDeclContext()); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric // Template specialization arguments. 2900b57cec5SDimitry Andric if (const ASTTemplateArgumentListInfo *TemplateArgInfo = 2910b57cec5SDimitry Andric D->getTemplateSpecializationArgsAsWritten()) { 2920b57cec5SDimitry Andric for (const auto &Arg : TemplateArgInfo->arguments()) 2930b57cec5SDimitry Andric handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 2970b57cec5SDimitry Andric const Stmt *Body = D->getBody(); 2980b57cec5SDimitry Andric if (Body) { 2990b57cec5SDimitry Andric IndexCtx.indexBody(Body, D, D); 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric return true; 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric bool VisitVarDecl(const VarDecl *D) { 3060b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 3070b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3080b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 3090b57cec5SDimitry Andric handleDeclarator(D); 3100b57cec5SDimitry Andric IndexCtx.indexBody(D->getInit(), D); 3110b57cec5SDimitry Andric return true; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric bool VisitDecompositionDecl(const DecompositionDecl *D) { 3150b57cec5SDimitry Andric for (const auto *Binding : D->bindings()) 3160b57cec5SDimitry Andric TRY_DECL(Binding, IndexCtx.handleDecl(Binding)); 3170b57cec5SDimitry Andric return Base::VisitDecompositionDecl(D); 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric bool VisitFieldDecl(const FieldDecl *D) { 3210b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 3220b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3230b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 3240b57cec5SDimitry Andric handleDeclarator(D); 3250b57cec5SDimitry Andric if (D->isBitField()) 3260b57cec5SDimitry Andric IndexCtx.indexBody(D->getBitWidth(), D); 3270b57cec5SDimitry Andric else if (D->hasInClassInitializer()) 3280b57cec5SDimitry Andric IndexCtx.indexBody(D->getInClassInitializer(), D); 3290b57cec5SDimitry Andric return true; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { 3330b57cec5SDimitry Andric if (D->getSynthesize()) { 3340b57cec5SDimitry Andric // handled in VisitObjCPropertyImplDecl 3350b57cec5SDimitry Andric return true; 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 3380b57cec5SDimitry Andric handleDeclarator(D); 3390b57cec5SDimitry Andric return true; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 3430b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 3440b57cec5SDimitry Andric handleDeclarator(D); 3450b57cec5SDimitry Andric return true; 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 3490b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 3500b57cec5SDimitry Andric IndexCtx.indexBody(D->getInitExpr(), D); 3510b57cec5SDimitry Andric return true; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 3550b57cec5SDimitry Andric if (!D->isTransparentTag()) { 3560b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 3570b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3580b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 3590b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric return true; 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric bool VisitTagDecl(const TagDecl *D) { 3650b57cec5SDimitry Andric // Non-free standing tags are handled in indexTypeSourceInfo. 3660b57cec5SDimitry Andric if (D->isFreeStanding()) { 3670b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 3680b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 3690b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3700b57cec5SDimitry Andric IndexCtx.indexTagDecl(D, Relations); 3710b57cec5SDimitry Andric } else { 3720b57cec5SDimitry Andric SmallVector<SymbolRelation, 1> Relations; 3730b57cec5SDimitry Andric gatherTemplatePseudoOverrides(D, Relations); 3740b57cec5SDimitry Andric return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(), 3750b57cec5SDimitry Andric Relations, D->getLexicalDeclContext()); 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric return true; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 381349cc55cSDimitry Andric bool VisitEnumDecl(const EnumDecl *ED) { 382349cc55cSDimitry Andric TRY_TO(VisitTagDecl(ED)); 383349cc55cSDimitry Andric // Indexing for enumdecl itself is handled inside TagDecl, we just want to 384349cc55cSDimitry Andric // visit integer-base here, which is different than other TagDecl bases. 385349cc55cSDimitry Andric if (auto *TSI = ED->getIntegerTypeSourceInfo()) 386349cc55cSDimitry Andric IndexCtx.indexTypeSourceInfo(TSI, ED, ED, /*isBase=*/true); 387349cc55cSDimitry Andric return true; 388349cc55cSDimitry Andric } 389349cc55cSDimitry Andric 3900b57cec5SDimitry Andric bool handleReferencedProtocols(const ObjCProtocolList &ProtList, 3910b57cec5SDimitry Andric const ObjCContainerDecl *ContD, 3920b57cec5SDimitry Andric SourceLocation SuperLoc) { 3930b57cec5SDimitry Andric ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 3940b57cec5SDimitry Andric for (ObjCInterfaceDecl::protocol_iterator 3950b57cec5SDimitry Andric I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 3960b57cec5SDimitry Andric SourceLocation Loc = *LI; 3970b57cec5SDimitry Andric ObjCProtocolDecl *PD = *I; 3980b57cec5SDimitry Andric SymbolRoleSet roles{}; 3990b57cec5SDimitry Andric if (Loc == SuperLoc) 4000b57cec5SDimitry Andric roles |= (SymbolRoleSet)SymbolRole::Implicit; 4010b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, 4020b57cec5SDimitry Andric SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric return true; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 4080b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 4090b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 4100b57cec5SDimitry Andric SourceLocation SuperLoc = D->getSuperClassLoc(); 4110b57cec5SDimitry Andric if (auto *SuperD = D->getSuperClass()) { 4120b57cec5SDimitry Andric bool hasSuperTypedef = false; 4130b57cec5SDimitry Andric if (auto *TInfo = D->getSuperClassTInfo()) { 4140b57cec5SDimitry Andric if (auto *TT = TInfo->getType()->getAs<TypedefType>()) { 4150b57cec5SDimitry Andric if (auto *TD = TT->getDecl()) { 4160b57cec5SDimitry Andric hasSuperTypedef = true; 4170b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, 4180b57cec5SDimitry Andric SymbolRoleSet())); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric SymbolRoleSet superRoles{}; 4230b57cec5SDimitry Andric if (hasSuperTypedef) 4240b57cec5SDimitry Andric superRoles |= (SymbolRoleSet)SymbolRole::Implicit; 4250b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, 4260b57cec5SDimitry Andric SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 4290b57cec5SDimitry Andric SuperLoc)); 4300b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 4310b57cec5SDimitry Andric } else { 4320b57cec5SDimitry Andric return IndexCtx.handleReference(D, D->getLocation(), nullptr, 4330b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric return true; 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 4390b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) { 4400b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 4410b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 4420b57cec5SDimitry Andric /*SuperLoc=*/SourceLocation())); 4430b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 4440b57cec5SDimitry Andric } else { 4450b57cec5SDimitry Andric return IndexCtx.handleReference(D, D->getLocation(), nullptr, 4460b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric return true; 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 4520b57cec5SDimitry Andric const ObjCInterfaceDecl *Class = D->getClassInterface(); 4530b57cec5SDimitry Andric if (!Class) 4540b57cec5SDimitry Andric return true; 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric if (Class->isImplicitInterfaceDecl()) 4570b57cec5SDimitry Andric IndexCtx.handleDecl(Class); 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric // Visit implicit @synthesize property implementations first as their 4620b57cec5SDimitry Andric // location is reported at the name of the @implementation block. This 4630b57cec5SDimitry Andric // serves no purpose other than to simplify the FileCheck-based tests. 4640b57cec5SDimitry Andric for (const auto *I : D->property_impls()) { 4650b57cec5SDimitry Andric if (I->getLocation().isInvalid()) 4660b57cec5SDimitry Andric IndexCtx.indexDecl(I); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric for (const auto *I : D->decls()) { 4690b57cec5SDimitry Andric if (!isa<ObjCPropertyImplDecl>(I) || 4700b57cec5SDimitry Andric cast<ObjCPropertyImplDecl>(I)->getLocation().isValid()) 4710b57cec5SDimitry Andric IndexCtx.indexDecl(I); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric return true; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 4780b57cec5SDimitry Andric if (!IndexCtx.shouldIndex(D)) 4790b57cec5SDimitry Andric return true; 4800b57cec5SDimitry Andric const ObjCInterfaceDecl *C = D->getClassInterface(); 4810b57cec5SDimitry Andric if (!C) 4820b57cec5SDimitry Andric return true; 4830b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), 4840b57cec5SDimitry Andric SymbolRelation{ 4850b57cec5SDimitry Andric (unsigned)SymbolRole::RelationExtendedBy, D 4860b57cec5SDimitry Andric })); 4870b57cec5SDimitry Andric SourceLocation CategoryLoc = D->getCategoryNameLoc(); 4880b57cec5SDimitry Andric if (!CategoryLoc.isValid()) 4890b57cec5SDimitry Andric CategoryLoc = D->getLocation(); 4900b57cec5SDimitry Andric TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); 4910b57cec5SDimitry Andric TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 4920b57cec5SDimitry Andric /*SuperLoc=*/SourceLocation())); 4930b57cec5SDimitry Andric TRY_TO(IndexCtx.indexDeclContext(D)); 4940b57cec5SDimitry Andric return true; 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 4980b57cec5SDimitry Andric const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 4990b57cec5SDimitry Andric if (!Cat) 5000b57cec5SDimitry Andric return true; 5010b57cec5SDimitry Andric const ObjCInterfaceDecl *C = D->getClassInterface(); 5020b57cec5SDimitry Andric if (C) 5030b57cec5SDimitry Andric TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, 5040b57cec5SDimitry Andric SymbolRoleSet())); 5050b57cec5SDimitry Andric SourceLocation CategoryLoc = D->getCategoryNameLoc(); 5060b57cec5SDimitry Andric if (!CategoryLoc.isValid()) 5070b57cec5SDimitry Andric CategoryLoc = D->getLocation(); 5080b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); 5090b57cec5SDimitry Andric IndexCtx.indexDeclContext(D); 5100b57cec5SDimitry Andric return true; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 5140b57cec5SDimitry Andric // Methods associated with a property, even user-declared ones, are 5150b57cec5SDimitry Andric // handled when we handle the property. 5160b57cec5SDimitry Andric if (D->isPropertyAccessor()) 5170b57cec5SDimitry Andric return true; 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric handleObjCMethod(D); 5200b57cec5SDimitry Andric return true; 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 5240b57cec5SDimitry Andric if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 5250b57cec5SDimitry Andric if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 5260b57cec5SDimitry Andric handleObjCMethod(MD, D); 5270b57cec5SDimitry Andric if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 5280b57cec5SDimitry Andric if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 5290b57cec5SDimitry Andric handleObjCMethod(MD, D); 5300b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 5310b57cec5SDimitry Andric if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) 5320b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, 5330b57cec5SDimitry Andric D->getLexicalDeclContext(), false, true); 5340b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 5350b57cec5SDimitry Andric return true; 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 5390b57cec5SDimitry Andric ObjCPropertyDecl *PD = D->getPropertyDecl(); 5400b57cec5SDimitry Andric auto *Container = cast<ObjCImplDecl>(D->getDeclContext()); 5410b57cec5SDimitry Andric SourceLocation Loc = D->getLocation(); 5420b57cec5SDimitry Andric SymbolRoleSet Roles = 0; 5430b57cec5SDimitry Andric SmallVector<SymbolRelation, 1> Relations; 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric if (ObjCIvarDecl *ID = D->getPropertyIvarDecl()) 5460b57cec5SDimitry Andric Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID}); 5470b57cec5SDimitry Andric if (Loc.isInvalid()) { 5480b57cec5SDimitry Andric Loc = Container->getLocation(); 5490b57cec5SDimitry Andric Roles |= (SymbolRoleSet)SymbolRole::Implicit; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 5540b57cec5SDimitry Andric return true; 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 5570b57cec5SDimitry Andric SymbolRoleSet AccessorMethodRoles = 5580b57cec5SDimitry Andric SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit); 5590b57cec5SDimitry Andric if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 560480093f4SDimitry Andric if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container)) 5610b57cec5SDimitry Andric IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 564480093f4SDimitry Andric if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container)) 5650b57cec5SDimitry Andric IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 5680b57cec5SDimitry Andric if (IvarD->getSynthesize()) { 5690b57cec5SDimitry Andric // For synthesized ivars, use the location of its name in the 5700b57cec5SDimitry Andric // corresponding @synthesize. If there isn't one, use the containing 5710b57cec5SDimitry Andric // @implementation's location, rather than the property's location, 5720b57cec5SDimitry Andric // otherwise the header file containing the @interface will have different 5730b57cec5SDimitry Andric // indexing contents based on whether the @implementation was present or 5740b57cec5SDimitry Andric // not in the translation unit. 5750b57cec5SDimitry Andric SymbolRoleSet IvarRoles = 0; 5760b57cec5SDimitry Andric SourceLocation IvarLoc = D->getPropertyIvarDeclLoc(); 5770b57cec5SDimitry Andric if (D->getLocation().isInvalid()) { 5780b57cec5SDimitry Andric IvarLoc = Container->getLocation(); 5790b57cec5SDimitry Andric IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 5800b57cec5SDimitry Andric } else if (D->getLocation() == IvarLoc) { 5810b57cec5SDimitry Andric IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); 5840b57cec5SDimitry Andric } else { 5850b57cec5SDimitry Andric IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, 5860b57cec5SDimitry Andric D->getDeclContext(), SymbolRoleSet()); 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric return true; 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric bool VisitNamespaceDecl(const NamespaceDecl *D) { 5930b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 5940b57cec5SDimitry Andric IndexCtx.indexDeclContext(D); 5950b57cec5SDimitry Andric return true; 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { 5990b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 6000b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 6010b57cec5SDimitry Andric IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D, 6020b57cec5SDimitry Andric D->getLexicalDeclContext()); 6030b57cec5SDimitry Andric return true; 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric bool VisitUsingDecl(const UsingDecl *D) { 6070b57cec5SDimitry Andric IndexCtx.handleDecl(D); 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 6100b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 6110b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 6120b57cec5SDimitry Andric D->getLexicalDeclContext()); 61381ad6265SDimitry Andric for (const auto *I : D->shadows()) { 61481ad6265SDimitry Andric // Skip unresolved using decls - we already have a decl for the using 61581ad6265SDimitry Andric // itself, so there's not much point adding another decl or reference to 61681ad6265SDimitry Andric // refer to the same location. 61781ad6265SDimitry Andric if (isa<UnresolvedUsingIfExistsDecl>(I->getUnderlyingDecl())) 61881ad6265SDimitry Andric continue; 61981ad6265SDimitry Andric 6200b57cec5SDimitry Andric IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, 6210b57cec5SDimitry Andric D->getLexicalDeclContext(), SymbolRoleSet()); 62281ad6265SDimitry Andric } 6230b57cec5SDimitry Andric return true; 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 6270b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 6280b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric // NNS for the local 'using namespace' directives is visited by the body 6310b57cec5SDimitry Andric // visitor. 6320b57cec5SDimitry Andric if (!D->getParentFunctionOrMethod()) 6330b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 6340b57cec5SDimitry Andric D->getLexicalDeclContext()); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 6370b57cec5SDimitry Andric D->getLocation(), Parent, 6380b57cec5SDimitry Andric D->getLexicalDeclContext(), 6390b57cec5SDimitry Andric SymbolRoleSet()); 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { 6430b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 6440b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 6450b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 6460b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 6470b57cec5SDimitry Andric D->getLexicalDeclContext()); 6480b57cec5SDimitry Andric return true; 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { 6520b57cec5SDimitry Andric TRY_DECL(D, IndexCtx.handleDecl(D)); 6530b57cec5SDimitry Andric const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 6540b57cec5SDimitry Andric const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 6550b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 6560b57cec5SDimitry Andric D->getLexicalDeclContext()); 6570b57cec5SDimitry Andric return true; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric bool VisitClassTemplateSpecializationDecl(const 6610b57cec5SDimitry Andric ClassTemplateSpecializationDecl *D) { 6620b57cec5SDimitry Andric // FIXME: Notify subsequent callbacks if info comes from implicit 6630b57cec5SDimitry Andric // instantiation. 6640b57cec5SDimitry Andric llvm::PointerUnion<ClassTemplateDecl *, 6650b57cec5SDimitry Andric ClassTemplatePartialSpecializationDecl *> 6660b57cec5SDimitry Andric Template = D->getSpecializedTemplateOrPartial(); 6670b57cec5SDimitry Andric const Decl *SpecializationOf = 6680b57cec5SDimitry Andric Template.is<ClassTemplateDecl *>() 6690b57cec5SDimitry Andric ? (Decl *)Template.get<ClassTemplateDecl *>() 6700b57cec5SDimitry Andric : Template.get<ClassTemplatePartialSpecializationDecl *>(); 6710b57cec5SDimitry Andric if (!D->isThisDeclarationADefinition()) 6720b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 6730b57cec5SDimitry Andric IndexCtx.indexTagDecl( 6740b57cec5SDimitry Andric D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 6750b57cec5SDimitry Andric SpecializationOf)); 676*0fca6ea1SDimitry Andric // Template specialization arguments. 677*0fca6ea1SDimitry Andric if (const ASTTemplateArgumentListInfo *TemplateArgInfo = 678*0fca6ea1SDimitry Andric D->getTemplateArgsAsWritten()) { 679*0fca6ea1SDimitry Andric for (const auto &Arg : TemplateArgInfo->arguments()) 680*0fca6ea1SDimitry Andric handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); 681*0fca6ea1SDimitry Andric } 6820b57cec5SDimitry Andric return true; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) { 6860b57cec5SDimitry Andric // We want to index the template parameters only once when indexing the 6870b57cec5SDimitry Andric // canonical declaration. 6880b57cec5SDimitry Andric if (!D) 6890b57cec5SDimitry Andric return false; 6900b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) 6910b57cec5SDimitry Andric return FD->getCanonicalDecl() == FD; 6920b57cec5SDimitry Andric else if (const auto *TD = dyn_cast<TagDecl>(D)) 6930b57cec5SDimitry Andric return TD->getCanonicalDecl() == TD; 6940b57cec5SDimitry Andric else if (const auto *VD = dyn_cast<VarDecl>(D)) 6950b57cec5SDimitry Andric return VD->getCanonicalDecl() == VD; 6960b57cec5SDimitry Andric return true; 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 69981ad6265SDimitry Andric void indexTemplateParameters(TemplateParameterList *Params, 70081ad6265SDimitry Andric const NamedDecl *Parent) { 7010b57cec5SDimitry Andric for (const NamedDecl *TP : *Params) { 7020b57cec5SDimitry Andric if (IndexCtx.shouldIndexTemplateParameters()) 7030b57cec5SDimitry Andric IndexCtx.handleDecl(TP); 7040b57cec5SDimitry Andric if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) { 7050b57cec5SDimitry Andric if (TTP->hasDefaultArgument()) 706*0fca6ea1SDimitry Andric handleTemplateArgumentLoc(TTP->getDefaultArgument(), Parent, 707*0fca6ea1SDimitry Andric TP->getLexicalDeclContext()); 70881ad6265SDimitry Andric if (auto *C = TTP->getTypeConstraint()) 70981ad6265SDimitry Andric IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(), 71081ad6265SDimitry Andric Parent, TTP->getLexicalDeclContext()); 7110b57cec5SDimitry Andric } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) { 71206c3fb27SDimitry Andric IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent); 7130b57cec5SDimitry Andric if (NTTP->hasDefaultArgument()) 714*0fca6ea1SDimitry Andric handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent, 715*0fca6ea1SDimitry Andric TP->getLexicalDeclContext()); 7160b57cec5SDimitry Andric } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) { 7170b57cec5SDimitry Andric if (TTPD->hasDefaultArgument()) 7180b57cec5SDimitry Andric handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, 7190b57cec5SDimitry Andric TP->getLexicalDeclContext()); 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric } 72281ad6265SDimitry Andric if (auto *R = Params->getRequiresClause()) 72381ad6265SDimitry Andric IndexCtx.indexBody(R, Parent); 72481ad6265SDimitry Andric } 72581ad6265SDimitry Andric 72681ad6265SDimitry Andric bool VisitTemplateDecl(const TemplateDecl *D) { 72781ad6265SDimitry Andric const NamedDecl *Parent = D->getTemplatedDecl(); 72881ad6265SDimitry Andric if (!Parent) 72981ad6265SDimitry Andric return true; 73081ad6265SDimitry Andric 73181ad6265SDimitry Andric // Index the default values for the template parameters. 73281ad6265SDimitry Andric auto *Params = D->getTemplateParameters(); 73381ad6265SDimitry Andric if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) { 73481ad6265SDimitry Andric indexTemplateParameters(Params, Parent); 7350b57cec5SDimitry Andric } 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric return Visit(Parent); 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 74081ad6265SDimitry Andric bool VisitConceptDecl(const ConceptDecl *D) { 74181ad6265SDimitry Andric if (auto *Params = D->getTemplateParameters()) 74281ad6265SDimitry Andric indexTemplateParameters(Params, D); 74381ad6265SDimitry Andric if (auto *E = D->getConstraintExpr()) 74481ad6265SDimitry Andric IndexCtx.indexBody(E, D); 74581ad6265SDimitry Andric return IndexCtx.handleDecl(D); 74681ad6265SDimitry Andric } 74781ad6265SDimitry Andric 7480b57cec5SDimitry Andric bool VisitFriendDecl(const FriendDecl *D) { 7490b57cec5SDimitry Andric if (auto ND = D->getFriendDecl()) { 7500b57cec5SDimitry Andric // FIXME: Ignore a class template in a dependent context, these are not 7510b57cec5SDimitry Andric // linked properly with their redeclarations, ending up with duplicate 7520b57cec5SDimitry Andric // USRs. 7530b57cec5SDimitry Andric // See comment "Friend templates are visible in fairly strange ways." in 7540b57cec5SDimitry Andric // SemaTemplate.cpp which precedes code that prevents the friend template 7550b57cec5SDimitry Andric // from becoming visible from the enclosing context. 7560b57cec5SDimitry Andric if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext()) 7570b57cec5SDimitry Andric return true; 7580b57cec5SDimitry Andric return Visit(ND); 7590b57cec5SDimitry Andric } 7600b57cec5SDimitry Andric if (auto Ty = D->getFriendType()) { 7610b57cec5SDimitry Andric IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext())); 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric return true; 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric bool VisitImportDecl(const ImportDecl *D) { 7670b57cec5SDimitry Andric return IndexCtx.importedModule(D); 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric bool VisitStaticAssertDecl(const StaticAssertDecl *D) { 7710b57cec5SDimitry Andric IndexCtx.indexBody(D->getAssertExpr(), 7720b57cec5SDimitry Andric dyn_cast<NamedDecl>(D->getDeclContext()), 7730b57cec5SDimitry Andric D->getLexicalDeclContext()); 7740b57cec5SDimitry Andric return true; 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric }; 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric } // anonymous namespace 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric bool IndexingContext::indexDecl(const Decl *D) { 7810b57cec5SDimitry Andric if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 7820b57cec5SDimitry Andric return true; 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation()) 7850b57cec5SDimitry Andric return true; 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric IndexingDeclVisitor Visitor(*this); 7880b57cec5SDimitry Andric bool ShouldContinue = Visitor.Visit(D); 7890b57cec5SDimitry Andric if (!ShouldContinue) 7900b57cec5SDimitry Andric return false; 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric if (!Visitor.Handled && isa<DeclContext>(D)) 7930b57cec5SDimitry Andric return indexDeclContext(cast<DeclContext>(D)); 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric return true; 7960b57cec5SDimitry Andric } 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric bool IndexingContext::indexDeclContext(const DeclContext *DC) { 7990b57cec5SDimitry Andric for (const auto *I : DC->decls()) 8000b57cec5SDimitry Andric if (!indexDecl(I)) 8010b57cec5SDimitry Andric return false; 8020b57cec5SDimitry Andric return true; 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric bool IndexingContext::indexTopLevelDecl(const Decl *D) { 806fe6060f1SDimitry Andric if (!D || D->getLocation().isInvalid()) 8070b57cec5SDimitry Andric return true; 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(D)) 8100b57cec5SDimitry Andric return true; // Wait for the objc container. 8110b57cec5SDimitry Andric 8125ffd83dbSDimitry Andric if (IndexOpts.ShouldTraverseDecl && !IndexOpts.ShouldTraverseDecl(D)) 8135ffd83dbSDimitry Andric return true; // skip 8145ffd83dbSDimitry Andric 8150b57cec5SDimitry Andric return indexDecl(D); 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric 8180b57cec5SDimitry Andric bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 8190b57cec5SDimitry Andric for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 8200b57cec5SDimitry Andric if (!indexTopLevelDecl(*I)) 8210b57cec5SDimitry Andric return false; 8220b57cec5SDimitry Andric return true; 8230b57cec5SDimitry Andric } 824