17330f729Sjoerg //===- IndexDecl.cpp - Indexing declarations ------------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "IndexingContext.h"
10*e038c9c4Sjoerg #include "clang/AST/Attr.h"
117330f729Sjoerg #include "clang/AST/DeclVisitor.h"
12*e038c9c4Sjoerg #include "clang/Index/IndexDataConsumer.h"
137330f729Sjoerg
147330f729Sjoerg using namespace clang;
157330f729Sjoerg using namespace index;
167330f729Sjoerg
177330f729Sjoerg #define TRY_DECL(D,CALL_EXPR) \
187330f729Sjoerg do { \
197330f729Sjoerg if (!IndexCtx.shouldIndex(D)) return true; \
207330f729Sjoerg if (!CALL_EXPR) \
217330f729Sjoerg return false; \
227330f729Sjoerg } while (0)
237330f729Sjoerg
247330f729Sjoerg #define TRY_TO(CALL_EXPR) \
257330f729Sjoerg do { \
267330f729Sjoerg if (!CALL_EXPR) \
277330f729Sjoerg return false; \
287330f729Sjoerg } while (0)
297330f729Sjoerg
307330f729Sjoerg namespace {
317330f729Sjoerg
327330f729Sjoerg class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
337330f729Sjoerg IndexingContext &IndexCtx;
347330f729Sjoerg
357330f729Sjoerg public:
IndexingDeclVisitor(IndexingContext & indexCtx)367330f729Sjoerg explicit IndexingDeclVisitor(IndexingContext &indexCtx)
377330f729Sjoerg : IndexCtx(indexCtx) { }
387330f729Sjoerg
397330f729Sjoerg bool Handled = true;
407330f729Sjoerg
VisitDecl(const Decl * D)417330f729Sjoerg bool VisitDecl(const Decl *D) {
427330f729Sjoerg Handled = false;
437330f729Sjoerg return true;
447330f729Sjoerg }
457330f729Sjoerg
handleTemplateArgumentLoc(const TemplateArgumentLoc & TALoc,const NamedDecl * Parent,const DeclContext * DC)467330f729Sjoerg void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
477330f729Sjoerg const NamedDecl *Parent,
487330f729Sjoerg const DeclContext *DC) {
497330f729Sjoerg const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();
507330f729Sjoerg switch (TALoc.getArgument().getKind()) {
517330f729Sjoerg case TemplateArgument::Expression:
527330f729Sjoerg IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
537330f729Sjoerg break;
547330f729Sjoerg case TemplateArgument::Type:
557330f729Sjoerg IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
567330f729Sjoerg break;
577330f729Sjoerg case TemplateArgument::Template:
587330f729Sjoerg case TemplateArgument::TemplateExpansion:
597330f729Sjoerg IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
607330f729Sjoerg Parent, DC);
617330f729Sjoerg if (const TemplateDecl *TD = TALoc.getArgument()
627330f729Sjoerg .getAsTemplateOrTemplatePattern()
637330f729Sjoerg .getAsTemplateDecl()) {
647330f729Sjoerg if (const NamedDecl *TTD = TD->getTemplatedDecl())
657330f729Sjoerg IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
667330f729Sjoerg }
677330f729Sjoerg break;
687330f729Sjoerg default:
697330f729Sjoerg break;
707330f729Sjoerg }
717330f729Sjoerg }
727330f729Sjoerg
73*e038c9c4Sjoerg /// Returns true if the given method has been defined explicitly by the
74*e038c9c4Sjoerg /// user.
hasUserDefined(const ObjCMethodDecl * D,const ObjCImplDecl * Container)75*e038c9c4Sjoerg static bool hasUserDefined(const ObjCMethodDecl *D,
76*e038c9c4Sjoerg const ObjCImplDecl *Container) {
77*e038c9c4Sjoerg const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
78*e038c9c4Sjoerg D->isInstanceMethod());
79*e038c9c4Sjoerg return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition() &&
80*e038c9c4Sjoerg !MD->isSynthesizedAccessorStub();
81*e038c9c4Sjoerg }
82*e038c9c4Sjoerg
83*e038c9c4Sjoerg
handleDeclarator(const DeclaratorDecl * D,const NamedDecl * Parent=nullptr,bool isIBType=false)847330f729Sjoerg void handleDeclarator(const DeclaratorDecl *D,
857330f729Sjoerg const NamedDecl *Parent = nullptr,
867330f729Sjoerg bool isIBType = false) {
877330f729Sjoerg if (!Parent) Parent = D;
887330f729Sjoerg
897330f729Sjoerg IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
907330f729Sjoerg Parent->getLexicalDeclContext(),
917330f729Sjoerg /*isBase=*/false, isIBType);
927330f729Sjoerg IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
93*e038c9c4Sjoerg auto IndexDefaultParmeterArgument = [&](const ParmVarDecl *Parm,
94*e038c9c4Sjoerg const NamedDecl *Parent) {
95*e038c9c4Sjoerg if (Parm->hasDefaultArg() && !Parm->hasUninstantiatedDefaultArg() &&
96*e038c9c4Sjoerg !Parm->hasUnparsedDefaultArg())
97*e038c9c4Sjoerg IndexCtx.indexBody(Parm->getDefaultArg(), Parent);
98*e038c9c4Sjoerg };
997330f729Sjoerg if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
1007330f729Sjoerg if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
1017330f729Sjoerg auto *DC = Parm->getDeclContext();
1027330f729Sjoerg if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
1037330f729Sjoerg if (IndexCtx.shouldIndexParametersInDeclarations() ||
1047330f729Sjoerg FD->isThisDeclarationADefinition())
1057330f729Sjoerg IndexCtx.handleDecl(Parm);
1067330f729Sjoerg } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
1077330f729Sjoerg if (MD->isThisDeclarationADefinition())
1087330f729Sjoerg IndexCtx.handleDecl(Parm);
1097330f729Sjoerg } else {
1107330f729Sjoerg IndexCtx.handleDecl(Parm);
1117330f729Sjoerg }
1127330f729Sjoerg } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1137330f729Sjoerg if (IndexCtx.shouldIndexParametersInDeclarations() ||
1147330f729Sjoerg FD->isThisDeclarationADefinition()) {
115*e038c9c4Sjoerg for (const auto *PI : FD->parameters()) {
116*e038c9c4Sjoerg IndexDefaultParmeterArgument(PI, D);
1177330f729Sjoerg IndexCtx.handleDecl(PI);
1187330f729Sjoerg }
1197330f729Sjoerg }
1207330f729Sjoerg }
1217330f729Sjoerg } else {
1227330f729Sjoerg // Index the default parameter value for function definitions.
1237330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
1247330f729Sjoerg if (FD->isThisDeclarationADefinition()) {
1257330f729Sjoerg for (const auto *PV : FD->parameters()) {
126*e038c9c4Sjoerg IndexDefaultParmeterArgument(PV, D);
1277330f729Sjoerg }
1287330f729Sjoerg }
1297330f729Sjoerg }
1307330f729Sjoerg }
1317330f729Sjoerg }
1327330f729Sjoerg
handleObjCMethod(const ObjCMethodDecl * D,const ObjCPropertyDecl * AssociatedProp=nullptr)1337330f729Sjoerg bool handleObjCMethod(const ObjCMethodDecl *D,
1347330f729Sjoerg const ObjCPropertyDecl *AssociatedProp = nullptr) {
1357330f729Sjoerg SmallVector<SymbolRelation, 4> Relations;
1367330f729Sjoerg SmallVector<const ObjCMethodDecl*, 4> Overriden;
1377330f729Sjoerg
1387330f729Sjoerg D->getOverriddenMethods(Overriden);
1397330f729Sjoerg for(auto overridden: Overriden) {
1407330f729Sjoerg Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
1417330f729Sjoerg overridden);
1427330f729Sjoerg }
1437330f729Sjoerg if (AssociatedProp)
1447330f729Sjoerg Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
1457330f729Sjoerg AssociatedProp);
1467330f729Sjoerg
1477330f729Sjoerg // getLocation() returns beginning token of a method declaration, but for
1487330f729Sjoerg // indexing purposes we want to point to the base name.
1497330f729Sjoerg SourceLocation MethodLoc = D->getSelectorStartLoc();
1507330f729Sjoerg if (MethodLoc.isInvalid())
1517330f729Sjoerg MethodLoc = D->getLocation();
1527330f729Sjoerg
1537330f729Sjoerg SourceLocation AttrLoc;
1547330f729Sjoerg
1557330f729Sjoerg // check for (getter=/setter=)
1567330f729Sjoerg if (AssociatedProp) {
1577330f729Sjoerg bool isGetter = !D->param_size();
1587330f729Sjoerg AttrLoc = isGetter ?
1597330f729Sjoerg AssociatedProp->getGetterNameLoc():
1607330f729Sjoerg AssociatedProp->getSetterNameLoc();
1617330f729Sjoerg }
1627330f729Sjoerg
1637330f729Sjoerg SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
1647330f729Sjoerg if (D->isImplicit()) {
1657330f729Sjoerg if (AttrLoc.isValid()) {
1667330f729Sjoerg MethodLoc = AttrLoc;
1677330f729Sjoerg } else {
1687330f729Sjoerg Roles |= (SymbolRoleSet)SymbolRole::Implicit;
1697330f729Sjoerg }
1707330f729Sjoerg } else if (AttrLoc.isValid()) {
1717330f729Sjoerg IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
1727330f729Sjoerg D->getDeclContext(), 0);
1737330f729Sjoerg }
1747330f729Sjoerg
1757330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
1767330f729Sjoerg IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
1777330f729Sjoerg bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
1787330f729Sjoerg for (const auto *I : D->parameters()) {
1797330f729Sjoerg handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
1807330f729Sjoerg hasIBActionAndFirst = false;
1817330f729Sjoerg }
1827330f729Sjoerg
1837330f729Sjoerg if (D->isThisDeclarationADefinition()) {
1847330f729Sjoerg const Stmt *Body = D->getBody();
1857330f729Sjoerg if (Body) {
1867330f729Sjoerg IndexCtx.indexBody(Body, D, D);
1877330f729Sjoerg }
1887330f729Sjoerg }
1897330f729Sjoerg return true;
1907330f729Sjoerg }
1917330f729Sjoerg
1927330f729Sjoerg /// Gather the declarations which the given declaration \D overrides in a
1937330f729Sjoerg /// pseudo-override manner.
1947330f729Sjoerg ///
1957330f729Sjoerg /// Pseudo-overrides occur when a class template specialization declares
1967330f729Sjoerg /// a declaration that has the same name as a similar declaration in the
1977330f729Sjoerg /// non-specialized template.
1987330f729Sjoerg void
gatherTemplatePseudoOverrides(const NamedDecl * D,SmallVectorImpl<SymbolRelation> & Relations)1997330f729Sjoerg gatherTemplatePseudoOverrides(const NamedDecl *D,
2007330f729Sjoerg SmallVectorImpl<SymbolRelation> &Relations) {
2017330f729Sjoerg if (!IndexCtx.getLangOpts().CPlusPlus)
2027330f729Sjoerg return;
2037330f729Sjoerg const auto *CTSD =
2047330f729Sjoerg dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
2057330f729Sjoerg if (!CTSD)
2067330f729Sjoerg return;
2077330f729Sjoerg llvm::PointerUnion<ClassTemplateDecl *,
2087330f729Sjoerg ClassTemplatePartialSpecializationDecl *>
2097330f729Sjoerg Template = CTSD->getSpecializedTemplateOrPartial();
2107330f729Sjoerg if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
2117330f729Sjoerg const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
2127330f729Sjoerg bool TypeOverride = isa<TypeDecl>(D);
2137330f729Sjoerg for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
2147330f729Sjoerg if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
2157330f729Sjoerg ND = CTD->getTemplatedDecl();
2167330f729Sjoerg if (ND->isImplicit())
2177330f729Sjoerg continue;
2187330f729Sjoerg // Types can override other types.
2197330f729Sjoerg if (!TypeOverride) {
2207330f729Sjoerg if (ND->getKind() != D->getKind())
2217330f729Sjoerg continue;
2227330f729Sjoerg } else if (!isa<TypeDecl>(ND))
2237330f729Sjoerg continue;
2247330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
2257330f729Sjoerg const auto *DFD = cast<FunctionDecl>(D);
2267330f729Sjoerg // Function overrides are approximated using the number of parameters.
2277330f729Sjoerg if (FD->getStorageClass() != DFD->getStorageClass() ||
2287330f729Sjoerg FD->getNumParams() != DFD->getNumParams())
2297330f729Sjoerg continue;
2307330f729Sjoerg }
2317330f729Sjoerg Relations.emplace_back(
2327330f729Sjoerg SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
2337330f729Sjoerg }
2347330f729Sjoerg }
2357330f729Sjoerg }
2367330f729Sjoerg
VisitFunctionDecl(const FunctionDecl * D)2377330f729Sjoerg bool VisitFunctionDecl(const FunctionDecl *D) {
2387330f729Sjoerg SymbolRoleSet Roles{};
2397330f729Sjoerg SmallVector<SymbolRelation, 4> Relations;
2407330f729Sjoerg if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
2417330f729Sjoerg if (CXXMD->isVirtual())
2427330f729Sjoerg Roles |= (unsigned)SymbolRole::Dynamic;
2437330f729Sjoerg for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
2447330f729Sjoerg Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
2457330f729Sjoerg }
2467330f729Sjoerg }
2477330f729Sjoerg gatherTemplatePseudoOverrides(D, Relations);
2487330f729Sjoerg if (const auto *Base = D->getPrimaryTemplate())
2497330f729Sjoerg Relations.push_back(
2507330f729Sjoerg SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
2517330f729Sjoerg Base->getTemplatedDecl()));
2527330f729Sjoerg
2537330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
2547330f729Sjoerg handleDeclarator(D);
2557330f729Sjoerg
2567330f729Sjoerg if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
2577330f729Sjoerg IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
2587330f729Sjoerg Ctor->getParent(), Ctor->getDeclContext(),
2597330f729Sjoerg (unsigned)SymbolRole::NameReference);
2607330f729Sjoerg
2617330f729Sjoerg // Constructor initializers.
2627330f729Sjoerg for (const auto *Init : Ctor->inits()) {
2637330f729Sjoerg if (Init->isWritten()) {
2647330f729Sjoerg IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
2657330f729Sjoerg if (const FieldDecl *Member = Init->getAnyMember())
2667330f729Sjoerg IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
2677330f729Sjoerg (unsigned)SymbolRole::Write);
2687330f729Sjoerg IndexCtx.indexBody(Init->getInit(), D, D);
2697330f729Sjoerg }
2707330f729Sjoerg }
2717330f729Sjoerg } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
2727330f729Sjoerg if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
2737330f729Sjoerg IndexCtx.handleReference(Dtor->getParent(),
2747330f729Sjoerg TypeNameInfo->getTypeLoc().getBeginLoc(),
2757330f729Sjoerg Dtor->getParent(), Dtor->getDeclContext(),
2767330f729Sjoerg (unsigned)SymbolRole::NameReference);
2777330f729Sjoerg }
2787330f729Sjoerg } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
2797330f729Sjoerg IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
2807330f729Sjoerg Guide->getLocation(), Guide,
2817330f729Sjoerg Guide->getDeclContext());
2827330f729Sjoerg }
2837330f729Sjoerg // Template specialization arguments.
2847330f729Sjoerg if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
2857330f729Sjoerg D->getTemplateSpecializationArgsAsWritten()) {
2867330f729Sjoerg for (const auto &Arg : TemplateArgInfo->arguments())
2877330f729Sjoerg handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
2887330f729Sjoerg }
2897330f729Sjoerg
2907330f729Sjoerg if (D->isThisDeclarationADefinition()) {
2917330f729Sjoerg const Stmt *Body = D->getBody();
2927330f729Sjoerg if (Body) {
2937330f729Sjoerg IndexCtx.indexBody(Body, D, D);
2947330f729Sjoerg }
2957330f729Sjoerg }
2967330f729Sjoerg return true;
2977330f729Sjoerg }
2987330f729Sjoerg
VisitVarDecl(const VarDecl * D)2997330f729Sjoerg bool VisitVarDecl(const VarDecl *D) {
3007330f729Sjoerg SmallVector<SymbolRelation, 4> Relations;
3017330f729Sjoerg gatherTemplatePseudoOverrides(D, Relations);
3027330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
3037330f729Sjoerg handleDeclarator(D);
3047330f729Sjoerg IndexCtx.indexBody(D->getInit(), D);
3057330f729Sjoerg return true;
3067330f729Sjoerg }
3077330f729Sjoerg
VisitDecompositionDecl(const DecompositionDecl * D)3087330f729Sjoerg bool VisitDecompositionDecl(const DecompositionDecl *D) {
3097330f729Sjoerg for (const auto *Binding : D->bindings())
3107330f729Sjoerg TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
3117330f729Sjoerg return Base::VisitDecompositionDecl(D);
3127330f729Sjoerg }
3137330f729Sjoerg
VisitFieldDecl(const FieldDecl * D)3147330f729Sjoerg bool VisitFieldDecl(const FieldDecl *D) {
3157330f729Sjoerg SmallVector<SymbolRelation, 4> Relations;
3167330f729Sjoerg gatherTemplatePseudoOverrides(D, Relations);
3177330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
3187330f729Sjoerg handleDeclarator(D);
3197330f729Sjoerg if (D->isBitField())
3207330f729Sjoerg IndexCtx.indexBody(D->getBitWidth(), D);
3217330f729Sjoerg else if (D->hasInClassInitializer())
3227330f729Sjoerg IndexCtx.indexBody(D->getInClassInitializer(), D);
3237330f729Sjoerg return true;
3247330f729Sjoerg }
3257330f729Sjoerg
VisitObjCIvarDecl(const ObjCIvarDecl * D)3267330f729Sjoerg bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
3277330f729Sjoerg if (D->getSynthesize()) {
3287330f729Sjoerg // handled in VisitObjCPropertyImplDecl
3297330f729Sjoerg return true;
3307330f729Sjoerg }
3317330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
3327330f729Sjoerg handleDeclarator(D);
3337330f729Sjoerg return true;
3347330f729Sjoerg }
3357330f729Sjoerg
VisitMSPropertyDecl(const MSPropertyDecl * D)3367330f729Sjoerg bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
3377330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
3387330f729Sjoerg handleDeclarator(D);
3397330f729Sjoerg return true;
3407330f729Sjoerg }
3417330f729Sjoerg
VisitEnumConstantDecl(const EnumConstantDecl * D)3427330f729Sjoerg bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
3437330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
3447330f729Sjoerg IndexCtx.indexBody(D->getInitExpr(), D);
3457330f729Sjoerg return true;
3467330f729Sjoerg }
3477330f729Sjoerg
VisitTypedefNameDecl(const TypedefNameDecl * D)3487330f729Sjoerg bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
3497330f729Sjoerg if (!D->isTransparentTag()) {
3507330f729Sjoerg SmallVector<SymbolRelation, 4> Relations;
3517330f729Sjoerg gatherTemplatePseudoOverrides(D, Relations);
3527330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
3537330f729Sjoerg IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
3547330f729Sjoerg }
3557330f729Sjoerg return true;
3567330f729Sjoerg }
3577330f729Sjoerg
VisitTagDecl(const TagDecl * D)3587330f729Sjoerg bool VisitTagDecl(const TagDecl *D) {
3597330f729Sjoerg // Non-free standing tags are handled in indexTypeSourceInfo.
3607330f729Sjoerg if (D->isFreeStanding()) {
3617330f729Sjoerg if (D->isThisDeclarationADefinition()) {
3627330f729Sjoerg SmallVector<SymbolRelation, 4> Relations;
3637330f729Sjoerg gatherTemplatePseudoOverrides(D, Relations);
3647330f729Sjoerg IndexCtx.indexTagDecl(D, Relations);
3657330f729Sjoerg } else {
3667330f729Sjoerg SmallVector<SymbolRelation, 1> Relations;
3677330f729Sjoerg gatherTemplatePseudoOverrides(D, Relations);
3687330f729Sjoerg return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
3697330f729Sjoerg Relations, D->getLexicalDeclContext());
3707330f729Sjoerg }
3717330f729Sjoerg }
3727330f729Sjoerg return true;
3737330f729Sjoerg }
3747330f729Sjoerg
handleReferencedProtocols(const ObjCProtocolList & ProtList,const ObjCContainerDecl * ContD,SourceLocation SuperLoc)3757330f729Sjoerg bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
3767330f729Sjoerg const ObjCContainerDecl *ContD,
3777330f729Sjoerg SourceLocation SuperLoc) {
3787330f729Sjoerg ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
3797330f729Sjoerg for (ObjCInterfaceDecl::protocol_iterator
3807330f729Sjoerg I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
3817330f729Sjoerg SourceLocation Loc = *LI;
3827330f729Sjoerg ObjCProtocolDecl *PD = *I;
3837330f729Sjoerg SymbolRoleSet roles{};
3847330f729Sjoerg if (Loc == SuperLoc)
3857330f729Sjoerg roles |= (SymbolRoleSet)SymbolRole::Implicit;
3867330f729Sjoerg TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
3877330f729Sjoerg SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
3887330f729Sjoerg }
3897330f729Sjoerg return true;
3907330f729Sjoerg }
3917330f729Sjoerg
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)3927330f729Sjoerg bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
3937330f729Sjoerg if (D->isThisDeclarationADefinition()) {
3947330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
3957330f729Sjoerg SourceLocation SuperLoc = D->getSuperClassLoc();
3967330f729Sjoerg if (auto *SuperD = D->getSuperClass()) {
3977330f729Sjoerg bool hasSuperTypedef = false;
3987330f729Sjoerg if (auto *TInfo = D->getSuperClassTInfo()) {
3997330f729Sjoerg if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
4007330f729Sjoerg if (auto *TD = TT->getDecl()) {
4017330f729Sjoerg hasSuperTypedef = true;
4027330f729Sjoerg TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
4037330f729Sjoerg SymbolRoleSet()));
4047330f729Sjoerg }
4057330f729Sjoerg }
4067330f729Sjoerg }
4077330f729Sjoerg SymbolRoleSet superRoles{};
4087330f729Sjoerg if (hasSuperTypedef)
4097330f729Sjoerg superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
4107330f729Sjoerg TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
4117330f729Sjoerg SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
4127330f729Sjoerg }
4137330f729Sjoerg TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
4147330f729Sjoerg SuperLoc));
4157330f729Sjoerg TRY_TO(IndexCtx.indexDeclContext(D));
4167330f729Sjoerg } else {
4177330f729Sjoerg return IndexCtx.handleReference(D, D->getLocation(), nullptr,
4187330f729Sjoerg D->getDeclContext(), SymbolRoleSet());
4197330f729Sjoerg }
4207330f729Sjoerg return true;
4217330f729Sjoerg }
4227330f729Sjoerg
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)4237330f729Sjoerg bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
4247330f729Sjoerg if (D->isThisDeclarationADefinition()) {
4257330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
4267330f729Sjoerg TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
4277330f729Sjoerg /*SuperLoc=*/SourceLocation()));
4287330f729Sjoerg TRY_TO(IndexCtx.indexDeclContext(D));
4297330f729Sjoerg } else {
4307330f729Sjoerg return IndexCtx.handleReference(D, D->getLocation(), nullptr,
4317330f729Sjoerg D->getDeclContext(), SymbolRoleSet());
4327330f729Sjoerg }
4337330f729Sjoerg return true;
4347330f729Sjoerg }
4357330f729Sjoerg
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)4367330f729Sjoerg bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
4377330f729Sjoerg const ObjCInterfaceDecl *Class = D->getClassInterface();
4387330f729Sjoerg if (!Class)
4397330f729Sjoerg return true;
4407330f729Sjoerg
4417330f729Sjoerg if (Class->isImplicitInterfaceDecl())
4427330f729Sjoerg IndexCtx.handleDecl(Class);
4437330f729Sjoerg
4447330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
4457330f729Sjoerg
4467330f729Sjoerg // Visit implicit @synthesize property implementations first as their
4477330f729Sjoerg // location is reported at the name of the @implementation block. This
4487330f729Sjoerg // serves no purpose other than to simplify the FileCheck-based tests.
4497330f729Sjoerg for (const auto *I : D->property_impls()) {
4507330f729Sjoerg if (I->getLocation().isInvalid())
4517330f729Sjoerg IndexCtx.indexDecl(I);
4527330f729Sjoerg }
4537330f729Sjoerg for (const auto *I : D->decls()) {
4547330f729Sjoerg if (!isa<ObjCPropertyImplDecl>(I) ||
4557330f729Sjoerg cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
4567330f729Sjoerg IndexCtx.indexDecl(I);
4577330f729Sjoerg }
4587330f729Sjoerg
4597330f729Sjoerg return true;
4607330f729Sjoerg }
4617330f729Sjoerg
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)4627330f729Sjoerg bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
4637330f729Sjoerg if (!IndexCtx.shouldIndex(D))
4647330f729Sjoerg return true;
4657330f729Sjoerg const ObjCInterfaceDecl *C = D->getClassInterface();
4667330f729Sjoerg if (!C)
4677330f729Sjoerg return true;
4687330f729Sjoerg TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
4697330f729Sjoerg SymbolRelation{
4707330f729Sjoerg (unsigned)SymbolRole::RelationExtendedBy, D
4717330f729Sjoerg }));
4727330f729Sjoerg SourceLocation CategoryLoc = D->getCategoryNameLoc();
4737330f729Sjoerg if (!CategoryLoc.isValid())
4747330f729Sjoerg CategoryLoc = D->getLocation();
4757330f729Sjoerg TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
4767330f729Sjoerg TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
4777330f729Sjoerg /*SuperLoc=*/SourceLocation()));
4787330f729Sjoerg TRY_TO(IndexCtx.indexDeclContext(D));
4797330f729Sjoerg return true;
4807330f729Sjoerg }
4817330f729Sjoerg
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)4827330f729Sjoerg bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
4837330f729Sjoerg const ObjCCategoryDecl *Cat = D->getCategoryDecl();
4847330f729Sjoerg if (!Cat)
4857330f729Sjoerg return true;
4867330f729Sjoerg const ObjCInterfaceDecl *C = D->getClassInterface();
4877330f729Sjoerg if (C)
4887330f729Sjoerg TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
4897330f729Sjoerg SymbolRoleSet()));
4907330f729Sjoerg SourceLocation CategoryLoc = D->getCategoryNameLoc();
4917330f729Sjoerg if (!CategoryLoc.isValid())
4927330f729Sjoerg CategoryLoc = D->getLocation();
4937330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
4947330f729Sjoerg IndexCtx.indexDeclContext(D);
4957330f729Sjoerg return true;
4967330f729Sjoerg }
4977330f729Sjoerg
VisitObjCMethodDecl(const ObjCMethodDecl * D)4987330f729Sjoerg bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
4997330f729Sjoerg // Methods associated with a property, even user-declared ones, are
5007330f729Sjoerg // handled when we handle the property.
5017330f729Sjoerg if (D->isPropertyAccessor())
5027330f729Sjoerg return true;
5037330f729Sjoerg
5047330f729Sjoerg handleObjCMethod(D);
5057330f729Sjoerg return true;
5067330f729Sjoerg }
5077330f729Sjoerg
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)5087330f729Sjoerg bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
5097330f729Sjoerg if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
5107330f729Sjoerg if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
5117330f729Sjoerg handleObjCMethod(MD, D);
5127330f729Sjoerg if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
5137330f729Sjoerg if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
5147330f729Sjoerg handleObjCMethod(MD, D);
5157330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
5167330f729Sjoerg if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
5177330f729Sjoerg IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
5187330f729Sjoerg D->getLexicalDeclContext(), false, true);
5197330f729Sjoerg IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
5207330f729Sjoerg return true;
5217330f729Sjoerg }
5227330f729Sjoerg
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)5237330f729Sjoerg bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
5247330f729Sjoerg ObjCPropertyDecl *PD = D->getPropertyDecl();
5257330f729Sjoerg auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
5267330f729Sjoerg SourceLocation Loc = D->getLocation();
5277330f729Sjoerg SymbolRoleSet Roles = 0;
5287330f729Sjoerg SmallVector<SymbolRelation, 1> Relations;
5297330f729Sjoerg
5307330f729Sjoerg if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
5317330f729Sjoerg Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
5327330f729Sjoerg if (Loc.isInvalid()) {
5337330f729Sjoerg Loc = Container->getLocation();
5347330f729Sjoerg Roles |= (SymbolRoleSet)SymbolRole::Implicit;
5357330f729Sjoerg }
5367330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
5377330f729Sjoerg
5387330f729Sjoerg if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
5397330f729Sjoerg return true;
5407330f729Sjoerg
5417330f729Sjoerg assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
5427330f729Sjoerg SymbolRoleSet AccessorMethodRoles =
5437330f729Sjoerg SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
5447330f729Sjoerg if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
545*e038c9c4Sjoerg if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
5467330f729Sjoerg IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
5477330f729Sjoerg }
5487330f729Sjoerg if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
549*e038c9c4Sjoerg if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
5507330f729Sjoerg IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
5517330f729Sjoerg }
5527330f729Sjoerg if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
5537330f729Sjoerg if (IvarD->getSynthesize()) {
5547330f729Sjoerg // For synthesized ivars, use the location of its name in the
5557330f729Sjoerg // corresponding @synthesize. If there isn't one, use the containing
5567330f729Sjoerg // @implementation's location, rather than the property's location,
5577330f729Sjoerg // otherwise the header file containing the @interface will have different
5587330f729Sjoerg // indexing contents based on whether the @implementation was present or
5597330f729Sjoerg // not in the translation unit.
5607330f729Sjoerg SymbolRoleSet IvarRoles = 0;
5617330f729Sjoerg SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
5627330f729Sjoerg if (D->getLocation().isInvalid()) {
5637330f729Sjoerg IvarLoc = Container->getLocation();
5647330f729Sjoerg IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
5657330f729Sjoerg } else if (D->getLocation() == IvarLoc) {
5667330f729Sjoerg IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
5677330f729Sjoerg }
5687330f729Sjoerg TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
5697330f729Sjoerg } else {
5707330f729Sjoerg IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
5717330f729Sjoerg D->getDeclContext(), SymbolRoleSet());
5727330f729Sjoerg }
5737330f729Sjoerg }
5747330f729Sjoerg return true;
5757330f729Sjoerg }
5767330f729Sjoerg
VisitNamespaceDecl(const NamespaceDecl * D)5777330f729Sjoerg bool VisitNamespaceDecl(const NamespaceDecl *D) {
5787330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
5797330f729Sjoerg IndexCtx.indexDeclContext(D);
5807330f729Sjoerg return true;
5817330f729Sjoerg }
5827330f729Sjoerg
VisitNamespaceAliasDecl(const NamespaceAliasDecl * D)5837330f729Sjoerg bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
5847330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
5857330f729Sjoerg IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
5867330f729Sjoerg IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
5877330f729Sjoerg D->getLexicalDeclContext());
5887330f729Sjoerg return true;
5897330f729Sjoerg }
5907330f729Sjoerg
VisitUsingDecl(const UsingDecl * D)5917330f729Sjoerg bool VisitUsingDecl(const UsingDecl *D) {
5927330f729Sjoerg IndexCtx.handleDecl(D);
5937330f729Sjoerg
5947330f729Sjoerg const DeclContext *DC = D->getDeclContext()->getRedeclContext();
5957330f729Sjoerg const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
5967330f729Sjoerg IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
5977330f729Sjoerg D->getLexicalDeclContext());
5987330f729Sjoerg for (const auto *I : D->shadows())
5997330f729Sjoerg IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
6007330f729Sjoerg D->getLexicalDeclContext(), SymbolRoleSet());
6017330f729Sjoerg return true;
6027330f729Sjoerg }
6037330f729Sjoerg
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)6047330f729Sjoerg bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
6057330f729Sjoerg const DeclContext *DC = D->getDeclContext()->getRedeclContext();
6067330f729Sjoerg const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
6077330f729Sjoerg
6087330f729Sjoerg // NNS for the local 'using namespace' directives is visited by the body
6097330f729Sjoerg // visitor.
6107330f729Sjoerg if (!D->getParentFunctionOrMethod())
6117330f729Sjoerg IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
6127330f729Sjoerg D->getLexicalDeclContext());
6137330f729Sjoerg
6147330f729Sjoerg return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
6157330f729Sjoerg D->getLocation(), Parent,
6167330f729Sjoerg D->getLexicalDeclContext(),
6177330f729Sjoerg SymbolRoleSet());
6187330f729Sjoerg }
6197330f729Sjoerg
VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl * D)6207330f729Sjoerg bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
6217330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
6227330f729Sjoerg const DeclContext *DC = D->getDeclContext()->getRedeclContext();
6237330f729Sjoerg const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
6247330f729Sjoerg IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
6257330f729Sjoerg D->getLexicalDeclContext());
6267330f729Sjoerg return true;
6277330f729Sjoerg }
6287330f729Sjoerg
VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl * D)6297330f729Sjoerg bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
6307330f729Sjoerg TRY_DECL(D, IndexCtx.handleDecl(D));
6317330f729Sjoerg const DeclContext *DC = D->getDeclContext()->getRedeclContext();
6327330f729Sjoerg const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
6337330f729Sjoerg IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
6347330f729Sjoerg D->getLexicalDeclContext());
6357330f729Sjoerg return true;
6367330f729Sjoerg }
6377330f729Sjoerg
VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)6387330f729Sjoerg bool VisitClassTemplateSpecializationDecl(const
6397330f729Sjoerg ClassTemplateSpecializationDecl *D) {
6407330f729Sjoerg // FIXME: Notify subsequent callbacks if info comes from implicit
6417330f729Sjoerg // instantiation.
6427330f729Sjoerg llvm::PointerUnion<ClassTemplateDecl *,
6437330f729Sjoerg ClassTemplatePartialSpecializationDecl *>
6447330f729Sjoerg Template = D->getSpecializedTemplateOrPartial();
6457330f729Sjoerg const Decl *SpecializationOf =
6467330f729Sjoerg Template.is<ClassTemplateDecl *>()
6477330f729Sjoerg ? (Decl *)Template.get<ClassTemplateDecl *>()
6487330f729Sjoerg : Template.get<ClassTemplatePartialSpecializationDecl *>();
6497330f729Sjoerg if (!D->isThisDeclarationADefinition())
6507330f729Sjoerg IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
6517330f729Sjoerg IndexCtx.indexTagDecl(
6527330f729Sjoerg D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
6537330f729Sjoerg SpecializationOf));
6547330f729Sjoerg if (TypeSourceInfo *TSI = D->getTypeAsWritten())
6557330f729Sjoerg IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
6567330f729Sjoerg D->getLexicalDeclContext());
6577330f729Sjoerg return true;
6587330f729Sjoerg }
6597330f729Sjoerg
shouldIndexTemplateParameterDefaultValue(const NamedDecl * D)6607330f729Sjoerg static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
6617330f729Sjoerg // We want to index the template parameters only once when indexing the
6627330f729Sjoerg // canonical declaration.
6637330f729Sjoerg if (!D)
6647330f729Sjoerg return false;
6657330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D))
6667330f729Sjoerg return FD->getCanonicalDecl() == FD;
6677330f729Sjoerg else if (const auto *TD = dyn_cast<TagDecl>(D))
6687330f729Sjoerg return TD->getCanonicalDecl() == TD;
6697330f729Sjoerg else if (const auto *VD = dyn_cast<VarDecl>(D))
6707330f729Sjoerg return VD->getCanonicalDecl() == VD;
6717330f729Sjoerg return true;
6727330f729Sjoerg }
6737330f729Sjoerg
VisitTemplateDecl(const TemplateDecl * D)6747330f729Sjoerg bool VisitTemplateDecl(const TemplateDecl *D) {
6757330f729Sjoerg
6767330f729Sjoerg const NamedDecl *Parent = D->getTemplatedDecl();
6777330f729Sjoerg if (!Parent)
6787330f729Sjoerg return true;
6797330f729Sjoerg
6807330f729Sjoerg // Index the default values for the template parameters.
6817330f729Sjoerg if (D->getTemplateParameters() &&
6827330f729Sjoerg shouldIndexTemplateParameterDefaultValue(Parent)) {
6837330f729Sjoerg const TemplateParameterList *Params = D->getTemplateParameters();
6847330f729Sjoerg for (const NamedDecl *TP : *Params) {
6857330f729Sjoerg if (IndexCtx.shouldIndexTemplateParameters())
6867330f729Sjoerg IndexCtx.handleDecl(TP);
6877330f729Sjoerg if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
6887330f729Sjoerg if (TTP->hasDefaultArgument())
6897330f729Sjoerg IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
6907330f729Sjoerg } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
6917330f729Sjoerg if (NTTP->hasDefaultArgument())
6927330f729Sjoerg IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
6937330f729Sjoerg } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
6947330f729Sjoerg if (TTPD->hasDefaultArgument())
6957330f729Sjoerg handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
6967330f729Sjoerg TP->getLexicalDeclContext());
6977330f729Sjoerg }
6987330f729Sjoerg }
6997330f729Sjoerg }
7007330f729Sjoerg
7017330f729Sjoerg return Visit(Parent);
7027330f729Sjoerg }
7037330f729Sjoerg
VisitFriendDecl(const FriendDecl * D)7047330f729Sjoerg bool VisitFriendDecl(const FriendDecl *D) {
7057330f729Sjoerg if (auto ND = D->getFriendDecl()) {
7067330f729Sjoerg // FIXME: Ignore a class template in a dependent context, these are not
7077330f729Sjoerg // linked properly with their redeclarations, ending up with duplicate
7087330f729Sjoerg // USRs.
7097330f729Sjoerg // See comment "Friend templates are visible in fairly strange ways." in
7107330f729Sjoerg // SemaTemplate.cpp which precedes code that prevents the friend template
7117330f729Sjoerg // from becoming visible from the enclosing context.
7127330f729Sjoerg if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
7137330f729Sjoerg return true;
7147330f729Sjoerg return Visit(ND);
7157330f729Sjoerg }
7167330f729Sjoerg if (auto Ty = D->getFriendType()) {
7177330f729Sjoerg IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
7187330f729Sjoerg }
7197330f729Sjoerg return true;
7207330f729Sjoerg }
7217330f729Sjoerg
VisitImportDecl(const ImportDecl * D)7227330f729Sjoerg bool VisitImportDecl(const ImportDecl *D) {
7237330f729Sjoerg return IndexCtx.importedModule(D);
7247330f729Sjoerg }
7257330f729Sjoerg
VisitStaticAssertDecl(const StaticAssertDecl * D)7267330f729Sjoerg bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
7277330f729Sjoerg IndexCtx.indexBody(D->getAssertExpr(),
7287330f729Sjoerg dyn_cast<NamedDecl>(D->getDeclContext()),
7297330f729Sjoerg D->getLexicalDeclContext());
7307330f729Sjoerg return true;
7317330f729Sjoerg }
7327330f729Sjoerg };
7337330f729Sjoerg
7347330f729Sjoerg } // anonymous namespace
7357330f729Sjoerg
indexDecl(const Decl * D)7367330f729Sjoerg bool IndexingContext::indexDecl(const Decl *D) {
7377330f729Sjoerg if (D->isImplicit() && shouldIgnoreIfImplicit(D))
7387330f729Sjoerg return true;
7397330f729Sjoerg
7407330f729Sjoerg if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
7417330f729Sjoerg return true;
7427330f729Sjoerg
7437330f729Sjoerg IndexingDeclVisitor Visitor(*this);
7447330f729Sjoerg bool ShouldContinue = Visitor.Visit(D);
7457330f729Sjoerg if (!ShouldContinue)
7467330f729Sjoerg return false;
7477330f729Sjoerg
7487330f729Sjoerg if (!Visitor.Handled && isa<DeclContext>(D))
7497330f729Sjoerg return indexDeclContext(cast<DeclContext>(D));
7507330f729Sjoerg
7517330f729Sjoerg return true;
7527330f729Sjoerg }
7537330f729Sjoerg
indexDeclContext(const DeclContext * DC)7547330f729Sjoerg bool IndexingContext::indexDeclContext(const DeclContext *DC) {
7557330f729Sjoerg for (const auto *I : DC->decls())
7567330f729Sjoerg if (!indexDecl(I))
7577330f729Sjoerg return false;
7587330f729Sjoerg return true;
7597330f729Sjoerg }
7607330f729Sjoerg
indexTopLevelDecl(const Decl * D)7617330f729Sjoerg bool IndexingContext::indexTopLevelDecl(const Decl *D) {
762*e038c9c4Sjoerg if (!D || D->getLocation().isInvalid())
7637330f729Sjoerg return true;
7647330f729Sjoerg
7657330f729Sjoerg if (isa<ObjCMethodDecl>(D))
7667330f729Sjoerg return true; // Wait for the objc container.
7677330f729Sjoerg
768*e038c9c4Sjoerg if (IndexOpts.ShouldTraverseDecl && !IndexOpts.ShouldTraverseDecl(D))
769*e038c9c4Sjoerg return true; // skip
770*e038c9c4Sjoerg
7717330f729Sjoerg return indexDecl(D);
7727330f729Sjoerg }
7737330f729Sjoerg
indexDeclGroupRef(DeclGroupRef DG)7747330f729Sjoerg bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
7757330f729Sjoerg for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
7767330f729Sjoerg if (!indexTopLevelDecl(*I))
7777330f729Sjoerg return false;
7787330f729Sjoerg return true;
7797330f729Sjoerg }
780