xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Index/IndexDecl.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
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