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:
IndexingDeclVisitor(IndexingContext & indexCtx)400b57cec5SDimitry Andric explicit IndexingDeclVisitor(IndexingContext &indexCtx)
410b57cec5SDimitry Andric : IndexCtx(indexCtx) { }
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric bool Handled = true;
440b57cec5SDimitry Andric
VisitDecl(const Decl * D)450b57cec5SDimitry Andric bool VisitDecl(const Decl *D) {
460b57cec5SDimitry Andric Handled = false;
470b57cec5SDimitry Andric return true;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric
handleTemplateArgumentLoc(const TemplateArgumentLoc & TALoc,const NamedDecl * Parent,const DeclContext * DC)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.
hasUserDefined(const ObjCMethodDecl * D,const ObjCImplDecl * Container)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
handleDeclarator(const DeclaratorDecl * D,const NamedDecl * Parent=nullptr,bool isIBType=false)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
handleObjCMethod(const ObjCMethodDecl * D,const ObjCPropertyDecl * AssociatedProp=nullptr)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
gatherTemplatePseudoOverrides(const NamedDecl * D,SmallVectorImpl<SymbolRelation> & Relations)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
VisitFunctionDecl(const FunctionDecl * D)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
VisitVarDecl(const VarDecl * D)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
VisitDecompositionDecl(const DecompositionDecl * D)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
VisitFieldDecl(const FieldDecl * D)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
VisitObjCIvarDecl(const ObjCIvarDecl * D)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
VisitMSPropertyDecl(const MSPropertyDecl * D)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
VisitEnumConstantDecl(const EnumConstantDecl * D)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
VisitTypedefNameDecl(const TypedefNameDecl * D)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
VisitTagDecl(const TagDecl * D)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
VisitEnumDecl(const EnumDecl * ED)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
handleReferencedProtocols(const ObjCProtocolList & ProtList,const ObjCContainerDecl * ContD,SourceLocation SuperLoc)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
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)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
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)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
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)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
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)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
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)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
VisitObjCMethodDecl(const ObjCMethodDecl * D)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
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)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
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)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
VisitNamespaceDecl(const NamespaceDecl * D)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
VisitNamespaceAliasDecl(const NamespaceAliasDecl * D)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
VisitUsingDecl(const UsingDecl * D)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
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)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
VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl * D)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
VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl * D)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
VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)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
shouldIndexTemplateParameterDefaultValue(const NamedDecl * D)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
indexTemplateParameters(TemplateParameterList * Params,const NamedDecl * Parent)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
VisitTemplateDecl(const TemplateDecl * D)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
VisitConceptDecl(const ConceptDecl * D)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
VisitFriendDecl(const FriendDecl * D)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
VisitImportDecl(const ImportDecl * D)7660b57cec5SDimitry Andric bool VisitImportDecl(const ImportDecl *D) {
7670b57cec5SDimitry Andric return IndexCtx.importedModule(D);
7680b57cec5SDimitry Andric }
7690b57cec5SDimitry Andric
VisitStaticAssertDecl(const StaticAssertDecl * D)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
indexDecl(const Decl * D)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
indexDeclContext(const DeclContext * DC)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
indexTopLevelDecl(const Decl * D)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
indexDeclGroupRef(DeclGroupRef DG)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