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