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