xref: /freebsd/contrib/llvm-project/clang/lib/Index/IndexDecl.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- IndexDecl.cpp - Indexing declarations ------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "IndexingContext.h"
10*0b57cec5SDimitry Andric #include "clang/Index/IndexDataConsumer.h"
11*0b57cec5SDimitry Andric #include "clang/AST/DeclVisitor.h"
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric using namespace clang;
14*0b57cec5SDimitry Andric using namespace index;
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric #define TRY_DECL(D,CALL_EXPR)                                                  \
17*0b57cec5SDimitry Andric   do {                                                                         \
18*0b57cec5SDimitry Andric     if (!IndexCtx.shouldIndex(D)) return true;                                 \
19*0b57cec5SDimitry Andric     if (!CALL_EXPR)                                                            \
20*0b57cec5SDimitry Andric       return false;                                                            \
21*0b57cec5SDimitry Andric   } while (0)
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric #define TRY_TO(CALL_EXPR)                                                      \
24*0b57cec5SDimitry Andric   do {                                                                         \
25*0b57cec5SDimitry Andric     if (!CALL_EXPR)                                                            \
26*0b57cec5SDimitry Andric       return false;                                                            \
27*0b57cec5SDimitry Andric   } while (0)
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric namespace {
30*0b57cec5SDimitry Andric 
31*0b57cec5SDimitry Andric class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
32*0b57cec5SDimitry Andric   IndexingContext &IndexCtx;
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric public:
35*0b57cec5SDimitry Andric   explicit IndexingDeclVisitor(IndexingContext &indexCtx)
36*0b57cec5SDimitry Andric     : IndexCtx(indexCtx) { }
37*0b57cec5SDimitry Andric 
38*0b57cec5SDimitry Andric   bool Handled = true;
39*0b57cec5SDimitry Andric 
40*0b57cec5SDimitry Andric   bool VisitDecl(const Decl *D) {
41*0b57cec5SDimitry Andric     Handled = false;
42*0b57cec5SDimitry Andric     return true;
43*0b57cec5SDimitry Andric   }
44*0b57cec5SDimitry Andric 
45*0b57cec5SDimitry Andric   /// Returns true if the given method has been defined explicitly by the
46*0b57cec5SDimitry Andric   /// user.
47*0b57cec5SDimitry Andric   static bool hasUserDefined(const ObjCMethodDecl *D,
48*0b57cec5SDimitry Andric                              const ObjCImplDecl *Container) {
49*0b57cec5SDimitry Andric     const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
50*0b57cec5SDimitry Andric                                                     D->isInstanceMethod());
51*0b57cec5SDimitry Andric     return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
52*0b57cec5SDimitry Andric   }
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric   void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
55*0b57cec5SDimitry Andric                                  const NamedDecl *Parent,
56*0b57cec5SDimitry Andric                                  const DeclContext *DC) {
57*0b57cec5SDimitry Andric     const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();
58*0b57cec5SDimitry Andric     switch (TALoc.getArgument().getKind()) {
59*0b57cec5SDimitry Andric     case TemplateArgument::Expression:
60*0b57cec5SDimitry Andric       IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
61*0b57cec5SDimitry Andric       break;
62*0b57cec5SDimitry Andric     case TemplateArgument::Type:
63*0b57cec5SDimitry Andric       IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
64*0b57cec5SDimitry Andric       break;
65*0b57cec5SDimitry Andric     case TemplateArgument::Template:
66*0b57cec5SDimitry Andric     case TemplateArgument::TemplateExpansion:
67*0b57cec5SDimitry Andric       IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
68*0b57cec5SDimitry Andric                                            Parent, DC);
69*0b57cec5SDimitry Andric       if (const TemplateDecl *TD = TALoc.getArgument()
70*0b57cec5SDimitry Andric                                        .getAsTemplateOrTemplatePattern()
71*0b57cec5SDimitry Andric                                        .getAsTemplateDecl()) {
72*0b57cec5SDimitry Andric         if (const NamedDecl *TTD = TD->getTemplatedDecl())
73*0b57cec5SDimitry Andric           IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
74*0b57cec5SDimitry Andric       }
75*0b57cec5SDimitry Andric       break;
76*0b57cec5SDimitry Andric     default:
77*0b57cec5SDimitry Andric       break;
78*0b57cec5SDimitry Andric     }
79*0b57cec5SDimitry Andric   }
80*0b57cec5SDimitry Andric 
81*0b57cec5SDimitry Andric   void handleDeclarator(const DeclaratorDecl *D,
82*0b57cec5SDimitry Andric                         const NamedDecl *Parent = nullptr,
83*0b57cec5SDimitry Andric                         bool isIBType = false) {
84*0b57cec5SDimitry Andric     if (!Parent) Parent = D;
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
87*0b57cec5SDimitry Andric                                  Parent->getLexicalDeclContext(),
88*0b57cec5SDimitry Andric                                  /*isBase=*/false, isIBType);
89*0b57cec5SDimitry Andric     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
90*0b57cec5SDimitry Andric     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
91*0b57cec5SDimitry Andric       if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
92*0b57cec5SDimitry Andric         auto *DC = Parm->getDeclContext();
93*0b57cec5SDimitry Andric         if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
94*0b57cec5SDimitry Andric           if (IndexCtx.shouldIndexParametersInDeclarations() ||
95*0b57cec5SDimitry Andric               FD->isThisDeclarationADefinition())
96*0b57cec5SDimitry Andric             IndexCtx.handleDecl(Parm);
97*0b57cec5SDimitry Andric         } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
98*0b57cec5SDimitry Andric           if (MD->isThisDeclarationADefinition())
99*0b57cec5SDimitry Andric             IndexCtx.handleDecl(Parm);
100*0b57cec5SDimitry Andric         } else {
101*0b57cec5SDimitry Andric           IndexCtx.handleDecl(Parm);
102*0b57cec5SDimitry Andric         }
103*0b57cec5SDimitry Andric       } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
104*0b57cec5SDimitry Andric         if (IndexCtx.shouldIndexParametersInDeclarations() ||
105*0b57cec5SDimitry Andric             FD->isThisDeclarationADefinition()) {
106*0b57cec5SDimitry Andric           for (auto PI : FD->parameters()) {
107*0b57cec5SDimitry Andric             IndexCtx.handleDecl(PI);
108*0b57cec5SDimitry Andric           }
109*0b57cec5SDimitry Andric         }
110*0b57cec5SDimitry Andric       }
111*0b57cec5SDimitry Andric     } else {
112*0b57cec5SDimitry Andric       // Index the default parameter value for function definitions.
113*0b57cec5SDimitry Andric       if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
114*0b57cec5SDimitry Andric         if (FD->isThisDeclarationADefinition()) {
115*0b57cec5SDimitry Andric           for (const auto *PV : FD->parameters()) {
116*0b57cec5SDimitry Andric             if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() &&
117*0b57cec5SDimitry Andric                 !PV->hasUnparsedDefaultArg())
118*0b57cec5SDimitry Andric               IndexCtx.indexBody(PV->getDefaultArg(), D);
119*0b57cec5SDimitry Andric           }
120*0b57cec5SDimitry Andric         }
121*0b57cec5SDimitry Andric       }
122*0b57cec5SDimitry Andric     }
123*0b57cec5SDimitry Andric   }
124*0b57cec5SDimitry Andric 
125*0b57cec5SDimitry Andric   bool handleObjCMethod(const ObjCMethodDecl *D,
126*0b57cec5SDimitry Andric                         const ObjCPropertyDecl *AssociatedProp = nullptr) {
127*0b57cec5SDimitry Andric     SmallVector<SymbolRelation, 4> Relations;
128*0b57cec5SDimitry Andric     SmallVector<const ObjCMethodDecl*, 4> Overriden;
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric     D->getOverriddenMethods(Overriden);
131*0b57cec5SDimitry Andric     for(auto overridden: Overriden) {
132*0b57cec5SDimitry Andric       Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
133*0b57cec5SDimitry Andric                              overridden);
134*0b57cec5SDimitry Andric     }
135*0b57cec5SDimitry Andric     if (AssociatedProp)
136*0b57cec5SDimitry Andric       Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
137*0b57cec5SDimitry Andric                              AssociatedProp);
138*0b57cec5SDimitry Andric 
139*0b57cec5SDimitry Andric     // getLocation() returns beginning token of a method declaration, but for
140*0b57cec5SDimitry Andric     // indexing purposes we want to point to the base name.
141*0b57cec5SDimitry Andric     SourceLocation MethodLoc = D->getSelectorStartLoc();
142*0b57cec5SDimitry Andric     if (MethodLoc.isInvalid())
143*0b57cec5SDimitry Andric       MethodLoc = D->getLocation();
144*0b57cec5SDimitry Andric 
145*0b57cec5SDimitry Andric     SourceLocation AttrLoc;
146*0b57cec5SDimitry Andric 
147*0b57cec5SDimitry Andric     // check for (getter=/setter=)
148*0b57cec5SDimitry Andric     if (AssociatedProp) {
149*0b57cec5SDimitry Andric       bool isGetter = !D->param_size();
150*0b57cec5SDimitry Andric       AttrLoc = isGetter ?
151*0b57cec5SDimitry Andric         AssociatedProp->getGetterNameLoc():
152*0b57cec5SDimitry Andric         AssociatedProp->getSetterNameLoc();
153*0b57cec5SDimitry Andric     }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric     SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
156*0b57cec5SDimitry Andric     if (D->isImplicit()) {
157*0b57cec5SDimitry Andric       if (AttrLoc.isValid()) {
158*0b57cec5SDimitry Andric         MethodLoc = AttrLoc;
159*0b57cec5SDimitry Andric       } else {
160*0b57cec5SDimitry Andric         Roles |= (SymbolRoleSet)SymbolRole::Implicit;
161*0b57cec5SDimitry Andric       }
162*0b57cec5SDimitry Andric     } else if (AttrLoc.isValid()) {
163*0b57cec5SDimitry Andric       IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
164*0b57cec5SDimitry Andric                                D->getDeclContext(), 0);
165*0b57cec5SDimitry Andric     }
166*0b57cec5SDimitry Andric 
167*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
168*0b57cec5SDimitry Andric     IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
169*0b57cec5SDimitry Andric     bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
170*0b57cec5SDimitry Andric     for (const auto *I : D->parameters()) {
171*0b57cec5SDimitry Andric       handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
172*0b57cec5SDimitry Andric       hasIBActionAndFirst = false;
173*0b57cec5SDimitry Andric     }
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric     if (D->isThisDeclarationADefinition()) {
176*0b57cec5SDimitry Andric       const Stmt *Body = D->getBody();
177*0b57cec5SDimitry Andric       if (Body) {
178*0b57cec5SDimitry Andric         IndexCtx.indexBody(Body, D, D);
179*0b57cec5SDimitry Andric       }
180*0b57cec5SDimitry Andric     }
181*0b57cec5SDimitry Andric     return true;
182*0b57cec5SDimitry Andric   }
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric   /// Gather the declarations which the given declaration \D overrides in a
185*0b57cec5SDimitry Andric   /// pseudo-override manner.
186*0b57cec5SDimitry Andric   ///
187*0b57cec5SDimitry Andric   /// Pseudo-overrides occur when a class template specialization declares
188*0b57cec5SDimitry Andric   /// a declaration that has the same name as a similar declaration in the
189*0b57cec5SDimitry Andric   /// non-specialized template.
190*0b57cec5SDimitry Andric   void
191*0b57cec5SDimitry Andric   gatherTemplatePseudoOverrides(const NamedDecl *D,
192*0b57cec5SDimitry Andric                                 SmallVectorImpl<SymbolRelation> &Relations) {
193*0b57cec5SDimitry Andric     if (!IndexCtx.getLangOpts().CPlusPlus)
194*0b57cec5SDimitry Andric       return;
195*0b57cec5SDimitry Andric     const auto *CTSD =
196*0b57cec5SDimitry Andric         dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
197*0b57cec5SDimitry Andric     if (!CTSD)
198*0b57cec5SDimitry Andric       return;
199*0b57cec5SDimitry Andric     llvm::PointerUnion<ClassTemplateDecl *,
200*0b57cec5SDimitry Andric                        ClassTemplatePartialSpecializationDecl *>
201*0b57cec5SDimitry Andric         Template = CTSD->getSpecializedTemplateOrPartial();
202*0b57cec5SDimitry Andric     if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
203*0b57cec5SDimitry Andric       const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
204*0b57cec5SDimitry Andric       bool TypeOverride = isa<TypeDecl>(D);
205*0b57cec5SDimitry Andric       for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
206*0b57cec5SDimitry Andric         if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
207*0b57cec5SDimitry Andric           ND = CTD->getTemplatedDecl();
208*0b57cec5SDimitry Andric         if (ND->isImplicit())
209*0b57cec5SDimitry Andric           continue;
210*0b57cec5SDimitry Andric         // Types can override other types.
211*0b57cec5SDimitry Andric         if (!TypeOverride) {
212*0b57cec5SDimitry Andric           if (ND->getKind() != D->getKind())
213*0b57cec5SDimitry Andric             continue;
214*0b57cec5SDimitry Andric         } else if (!isa<TypeDecl>(ND))
215*0b57cec5SDimitry Andric           continue;
216*0b57cec5SDimitry Andric         if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
217*0b57cec5SDimitry Andric           const auto *DFD = cast<FunctionDecl>(D);
218*0b57cec5SDimitry Andric           // Function overrides are approximated using the number of parameters.
219*0b57cec5SDimitry Andric           if (FD->getStorageClass() != DFD->getStorageClass() ||
220*0b57cec5SDimitry Andric               FD->getNumParams() != DFD->getNumParams())
221*0b57cec5SDimitry Andric             continue;
222*0b57cec5SDimitry Andric         }
223*0b57cec5SDimitry Andric         Relations.emplace_back(
224*0b57cec5SDimitry Andric             SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
225*0b57cec5SDimitry Andric       }
226*0b57cec5SDimitry Andric     }
227*0b57cec5SDimitry Andric   }
228*0b57cec5SDimitry Andric 
229*0b57cec5SDimitry Andric   bool VisitFunctionDecl(const FunctionDecl *D) {
230*0b57cec5SDimitry Andric     SymbolRoleSet Roles{};
231*0b57cec5SDimitry Andric     SmallVector<SymbolRelation, 4> Relations;
232*0b57cec5SDimitry Andric     if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
233*0b57cec5SDimitry Andric       if (CXXMD->isVirtual())
234*0b57cec5SDimitry Andric         Roles |= (unsigned)SymbolRole::Dynamic;
235*0b57cec5SDimitry Andric       for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
236*0b57cec5SDimitry Andric         Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
237*0b57cec5SDimitry Andric       }
238*0b57cec5SDimitry Andric     }
239*0b57cec5SDimitry Andric     gatherTemplatePseudoOverrides(D, Relations);
240*0b57cec5SDimitry Andric     if (const auto *Base = D->getPrimaryTemplate())
241*0b57cec5SDimitry Andric       Relations.push_back(
242*0b57cec5SDimitry Andric           SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
243*0b57cec5SDimitry Andric                          Base->getTemplatedDecl()));
244*0b57cec5SDimitry Andric 
245*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
246*0b57cec5SDimitry Andric     handleDeclarator(D);
247*0b57cec5SDimitry Andric 
248*0b57cec5SDimitry Andric     if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
249*0b57cec5SDimitry Andric       IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
250*0b57cec5SDimitry Andric                                Ctor->getParent(), Ctor->getDeclContext(),
251*0b57cec5SDimitry Andric                                (unsigned)SymbolRole::NameReference);
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric       // Constructor initializers.
254*0b57cec5SDimitry Andric       for (const auto *Init : Ctor->inits()) {
255*0b57cec5SDimitry Andric         if (Init->isWritten()) {
256*0b57cec5SDimitry Andric           IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
257*0b57cec5SDimitry Andric           if (const FieldDecl *Member = Init->getAnyMember())
258*0b57cec5SDimitry Andric             IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
259*0b57cec5SDimitry Andric                                      (unsigned)SymbolRole::Write);
260*0b57cec5SDimitry Andric           IndexCtx.indexBody(Init->getInit(), D, D);
261*0b57cec5SDimitry Andric         }
262*0b57cec5SDimitry Andric       }
263*0b57cec5SDimitry Andric     } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
264*0b57cec5SDimitry Andric       if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
265*0b57cec5SDimitry Andric         IndexCtx.handleReference(Dtor->getParent(),
266*0b57cec5SDimitry Andric                                  TypeNameInfo->getTypeLoc().getBeginLoc(),
267*0b57cec5SDimitry Andric                                  Dtor->getParent(), Dtor->getDeclContext(),
268*0b57cec5SDimitry Andric                                  (unsigned)SymbolRole::NameReference);
269*0b57cec5SDimitry Andric       }
270*0b57cec5SDimitry Andric     } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
271*0b57cec5SDimitry Andric       IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
272*0b57cec5SDimitry Andric                                Guide->getLocation(), Guide,
273*0b57cec5SDimitry Andric                                Guide->getDeclContext());
274*0b57cec5SDimitry Andric     }
275*0b57cec5SDimitry Andric     // Template specialization arguments.
276*0b57cec5SDimitry Andric     if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
277*0b57cec5SDimitry Andric             D->getTemplateSpecializationArgsAsWritten()) {
278*0b57cec5SDimitry Andric       for (const auto &Arg : TemplateArgInfo->arguments())
279*0b57cec5SDimitry Andric         handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
280*0b57cec5SDimitry Andric     }
281*0b57cec5SDimitry Andric 
282*0b57cec5SDimitry Andric     if (D->isThisDeclarationADefinition()) {
283*0b57cec5SDimitry Andric       const Stmt *Body = D->getBody();
284*0b57cec5SDimitry Andric       if (Body) {
285*0b57cec5SDimitry Andric         IndexCtx.indexBody(Body, D, D);
286*0b57cec5SDimitry Andric       }
287*0b57cec5SDimitry Andric     }
288*0b57cec5SDimitry Andric     return true;
289*0b57cec5SDimitry Andric   }
290*0b57cec5SDimitry Andric 
291*0b57cec5SDimitry Andric   bool VisitVarDecl(const VarDecl *D) {
292*0b57cec5SDimitry Andric     SmallVector<SymbolRelation, 4> Relations;
293*0b57cec5SDimitry Andric     gatherTemplatePseudoOverrides(D, Relations);
294*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
295*0b57cec5SDimitry Andric     handleDeclarator(D);
296*0b57cec5SDimitry Andric     IndexCtx.indexBody(D->getInit(), D);
297*0b57cec5SDimitry Andric     return true;
298*0b57cec5SDimitry Andric   }
299*0b57cec5SDimitry Andric 
300*0b57cec5SDimitry Andric   bool VisitDecompositionDecl(const DecompositionDecl *D) {
301*0b57cec5SDimitry Andric     for (const auto *Binding : D->bindings())
302*0b57cec5SDimitry Andric       TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
303*0b57cec5SDimitry Andric     return Base::VisitDecompositionDecl(D);
304*0b57cec5SDimitry Andric   }
305*0b57cec5SDimitry Andric 
306*0b57cec5SDimitry Andric   bool VisitFieldDecl(const FieldDecl *D) {
307*0b57cec5SDimitry Andric     SmallVector<SymbolRelation, 4> Relations;
308*0b57cec5SDimitry Andric     gatherTemplatePseudoOverrides(D, Relations);
309*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
310*0b57cec5SDimitry Andric     handleDeclarator(D);
311*0b57cec5SDimitry Andric     if (D->isBitField())
312*0b57cec5SDimitry Andric       IndexCtx.indexBody(D->getBitWidth(), D);
313*0b57cec5SDimitry Andric     else if (D->hasInClassInitializer())
314*0b57cec5SDimitry Andric       IndexCtx.indexBody(D->getInClassInitializer(), D);
315*0b57cec5SDimitry Andric     return true;
316*0b57cec5SDimitry Andric   }
317*0b57cec5SDimitry Andric 
318*0b57cec5SDimitry Andric   bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
319*0b57cec5SDimitry Andric     if (D->getSynthesize()) {
320*0b57cec5SDimitry Andric       // handled in VisitObjCPropertyImplDecl
321*0b57cec5SDimitry Andric       return true;
322*0b57cec5SDimitry Andric     }
323*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
324*0b57cec5SDimitry Andric     handleDeclarator(D);
325*0b57cec5SDimitry Andric     return true;
326*0b57cec5SDimitry Andric   }
327*0b57cec5SDimitry Andric 
328*0b57cec5SDimitry Andric   bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
329*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
330*0b57cec5SDimitry Andric     handleDeclarator(D);
331*0b57cec5SDimitry Andric     return true;
332*0b57cec5SDimitry Andric   }
333*0b57cec5SDimitry Andric 
334*0b57cec5SDimitry Andric   bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
335*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
336*0b57cec5SDimitry Andric     IndexCtx.indexBody(D->getInitExpr(), D);
337*0b57cec5SDimitry Andric     return true;
338*0b57cec5SDimitry Andric   }
339*0b57cec5SDimitry Andric 
340*0b57cec5SDimitry Andric   bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
341*0b57cec5SDimitry Andric     if (!D->isTransparentTag()) {
342*0b57cec5SDimitry Andric       SmallVector<SymbolRelation, 4> Relations;
343*0b57cec5SDimitry Andric       gatherTemplatePseudoOverrides(D, Relations);
344*0b57cec5SDimitry Andric       TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
345*0b57cec5SDimitry Andric       IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
346*0b57cec5SDimitry Andric     }
347*0b57cec5SDimitry Andric     return true;
348*0b57cec5SDimitry Andric   }
349*0b57cec5SDimitry Andric 
350*0b57cec5SDimitry Andric   bool VisitTagDecl(const TagDecl *D) {
351*0b57cec5SDimitry Andric     // Non-free standing tags are handled in indexTypeSourceInfo.
352*0b57cec5SDimitry Andric     if (D->isFreeStanding()) {
353*0b57cec5SDimitry Andric       if (D->isThisDeclarationADefinition()) {
354*0b57cec5SDimitry Andric         SmallVector<SymbolRelation, 4> Relations;
355*0b57cec5SDimitry Andric         gatherTemplatePseudoOverrides(D, Relations);
356*0b57cec5SDimitry Andric         IndexCtx.indexTagDecl(D, Relations);
357*0b57cec5SDimitry Andric       } else {
358*0b57cec5SDimitry Andric         SmallVector<SymbolRelation, 1> Relations;
359*0b57cec5SDimitry Andric         gatherTemplatePseudoOverrides(D, Relations);
360*0b57cec5SDimitry Andric         return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
361*0b57cec5SDimitry Andric                                    Relations, D->getLexicalDeclContext());
362*0b57cec5SDimitry Andric       }
363*0b57cec5SDimitry Andric     }
364*0b57cec5SDimitry Andric     return true;
365*0b57cec5SDimitry Andric   }
366*0b57cec5SDimitry Andric 
367*0b57cec5SDimitry Andric   bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
368*0b57cec5SDimitry Andric                                  const ObjCContainerDecl *ContD,
369*0b57cec5SDimitry Andric                                  SourceLocation SuperLoc) {
370*0b57cec5SDimitry Andric     ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
371*0b57cec5SDimitry Andric     for (ObjCInterfaceDecl::protocol_iterator
372*0b57cec5SDimitry Andric          I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
373*0b57cec5SDimitry Andric       SourceLocation Loc = *LI;
374*0b57cec5SDimitry Andric       ObjCProtocolDecl *PD = *I;
375*0b57cec5SDimitry Andric       SymbolRoleSet roles{};
376*0b57cec5SDimitry Andric       if (Loc == SuperLoc)
377*0b57cec5SDimitry Andric         roles |= (SymbolRoleSet)SymbolRole::Implicit;
378*0b57cec5SDimitry Andric       TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
379*0b57cec5SDimitry Andric           SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
380*0b57cec5SDimitry Andric     }
381*0b57cec5SDimitry Andric     return true;
382*0b57cec5SDimitry Andric   }
383*0b57cec5SDimitry Andric 
384*0b57cec5SDimitry Andric   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
385*0b57cec5SDimitry Andric     if (D->isThisDeclarationADefinition()) {
386*0b57cec5SDimitry Andric       TRY_DECL(D, IndexCtx.handleDecl(D));
387*0b57cec5SDimitry Andric       SourceLocation SuperLoc = D->getSuperClassLoc();
388*0b57cec5SDimitry Andric       if (auto *SuperD = D->getSuperClass()) {
389*0b57cec5SDimitry Andric         bool hasSuperTypedef = false;
390*0b57cec5SDimitry Andric         if (auto *TInfo = D->getSuperClassTInfo()) {
391*0b57cec5SDimitry Andric           if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
392*0b57cec5SDimitry Andric             if (auto *TD = TT->getDecl()) {
393*0b57cec5SDimitry Andric               hasSuperTypedef = true;
394*0b57cec5SDimitry Andric               TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
395*0b57cec5SDimitry Andric                                               SymbolRoleSet()));
396*0b57cec5SDimitry Andric             }
397*0b57cec5SDimitry Andric           }
398*0b57cec5SDimitry Andric         }
399*0b57cec5SDimitry Andric         SymbolRoleSet superRoles{};
400*0b57cec5SDimitry Andric         if (hasSuperTypedef)
401*0b57cec5SDimitry Andric           superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
402*0b57cec5SDimitry Andric         TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
403*0b57cec5SDimitry Andric             SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
404*0b57cec5SDimitry Andric       }
405*0b57cec5SDimitry Andric       TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
406*0b57cec5SDimitry Andric                                        SuperLoc));
407*0b57cec5SDimitry Andric       TRY_TO(IndexCtx.indexDeclContext(D));
408*0b57cec5SDimitry Andric     } else {
409*0b57cec5SDimitry Andric       return IndexCtx.handleReference(D, D->getLocation(), nullptr,
410*0b57cec5SDimitry Andric                                       D->getDeclContext(), SymbolRoleSet());
411*0b57cec5SDimitry Andric     }
412*0b57cec5SDimitry Andric     return true;
413*0b57cec5SDimitry Andric   }
414*0b57cec5SDimitry Andric 
415*0b57cec5SDimitry Andric   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
416*0b57cec5SDimitry Andric     if (D->isThisDeclarationADefinition()) {
417*0b57cec5SDimitry Andric       TRY_DECL(D, IndexCtx.handleDecl(D));
418*0b57cec5SDimitry Andric       TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
419*0b57cec5SDimitry Andric                                        /*SuperLoc=*/SourceLocation()));
420*0b57cec5SDimitry Andric       TRY_TO(IndexCtx.indexDeclContext(D));
421*0b57cec5SDimitry Andric     } else {
422*0b57cec5SDimitry Andric       return IndexCtx.handleReference(D, D->getLocation(), nullptr,
423*0b57cec5SDimitry Andric                                       D->getDeclContext(), SymbolRoleSet());
424*0b57cec5SDimitry Andric     }
425*0b57cec5SDimitry Andric     return true;
426*0b57cec5SDimitry Andric   }
427*0b57cec5SDimitry Andric 
428*0b57cec5SDimitry Andric   bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
429*0b57cec5SDimitry Andric     const ObjCInterfaceDecl *Class = D->getClassInterface();
430*0b57cec5SDimitry Andric     if (!Class)
431*0b57cec5SDimitry Andric       return true;
432*0b57cec5SDimitry Andric 
433*0b57cec5SDimitry Andric     if (Class->isImplicitInterfaceDecl())
434*0b57cec5SDimitry Andric       IndexCtx.handleDecl(Class);
435*0b57cec5SDimitry Andric 
436*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
437*0b57cec5SDimitry Andric 
438*0b57cec5SDimitry Andric     // Visit implicit @synthesize property implementations first as their
439*0b57cec5SDimitry Andric     // location is reported at the name of the @implementation block. This
440*0b57cec5SDimitry Andric     // serves no purpose other than to simplify the FileCheck-based tests.
441*0b57cec5SDimitry Andric     for (const auto *I : D->property_impls()) {
442*0b57cec5SDimitry Andric       if (I->getLocation().isInvalid())
443*0b57cec5SDimitry Andric         IndexCtx.indexDecl(I);
444*0b57cec5SDimitry Andric     }
445*0b57cec5SDimitry Andric     for (const auto *I : D->decls()) {
446*0b57cec5SDimitry Andric       if (!isa<ObjCPropertyImplDecl>(I) ||
447*0b57cec5SDimitry Andric           cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
448*0b57cec5SDimitry Andric         IndexCtx.indexDecl(I);
449*0b57cec5SDimitry Andric     }
450*0b57cec5SDimitry Andric 
451*0b57cec5SDimitry Andric     return true;
452*0b57cec5SDimitry Andric   }
453*0b57cec5SDimitry Andric 
454*0b57cec5SDimitry Andric   bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
455*0b57cec5SDimitry Andric     if (!IndexCtx.shouldIndex(D))
456*0b57cec5SDimitry Andric       return true;
457*0b57cec5SDimitry Andric     const ObjCInterfaceDecl *C = D->getClassInterface();
458*0b57cec5SDimitry Andric     if (!C)
459*0b57cec5SDimitry Andric       return true;
460*0b57cec5SDimitry Andric     TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
461*0b57cec5SDimitry Andric                                    SymbolRelation{
462*0b57cec5SDimitry Andric                                      (unsigned)SymbolRole::RelationExtendedBy, D
463*0b57cec5SDimitry Andric                                    }));
464*0b57cec5SDimitry Andric     SourceLocation CategoryLoc = D->getCategoryNameLoc();
465*0b57cec5SDimitry Andric     if (!CategoryLoc.isValid())
466*0b57cec5SDimitry Andric       CategoryLoc = D->getLocation();
467*0b57cec5SDimitry Andric     TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
468*0b57cec5SDimitry Andric     TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
469*0b57cec5SDimitry Andric                                      /*SuperLoc=*/SourceLocation()));
470*0b57cec5SDimitry Andric     TRY_TO(IndexCtx.indexDeclContext(D));
471*0b57cec5SDimitry Andric     return true;
472*0b57cec5SDimitry Andric   }
473*0b57cec5SDimitry Andric 
474*0b57cec5SDimitry Andric   bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
475*0b57cec5SDimitry Andric     const ObjCCategoryDecl *Cat = D->getCategoryDecl();
476*0b57cec5SDimitry Andric     if (!Cat)
477*0b57cec5SDimitry Andric       return true;
478*0b57cec5SDimitry Andric     const ObjCInterfaceDecl *C = D->getClassInterface();
479*0b57cec5SDimitry Andric     if (C)
480*0b57cec5SDimitry Andric       TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
481*0b57cec5SDimitry Andric                                       SymbolRoleSet()));
482*0b57cec5SDimitry Andric     SourceLocation CategoryLoc = D->getCategoryNameLoc();
483*0b57cec5SDimitry Andric     if (!CategoryLoc.isValid())
484*0b57cec5SDimitry Andric       CategoryLoc = D->getLocation();
485*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
486*0b57cec5SDimitry Andric     IndexCtx.indexDeclContext(D);
487*0b57cec5SDimitry Andric     return true;
488*0b57cec5SDimitry Andric   }
489*0b57cec5SDimitry Andric 
490*0b57cec5SDimitry Andric   bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
491*0b57cec5SDimitry Andric     // Methods associated with a property, even user-declared ones, are
492*0b57cec5SDimitry Andric     // handled when we handle the property.
493*0b57cec5SDimitry Andric     if (D->isPropertyAccessor())
494*0b57cec5SDimitry Andric       return true;
495*0b57cec5SDimitry Andric 
496*0b57cec5SDimitry Andric     handleObjCMethod(D);
497*0b57cec5SDimitry Andric     return true;
498*0b57cec5SDimitry Andric   }
499*0b57cec5SDimitry Andric 
500*0b57cec5SDimitry Andric   bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
501*0b57cec5SDimitry Andric     if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
502*0b57cec5SDimitry Andric       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
503*0b57cec5SDimitry Andric         handleObjCMethod(MD, D);
504*0b57cec5SDimitry Andric     if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
505*0b57cec5SDimitry Andric       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
506*0b57cec5SDimitry Andric         handleObjCMethod(MD, D);
507*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
508*0b57cec5SDimitry Andric     if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
509*0b57cec5SDimitry Andric       IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
510*0b57cec5SDimitry Andric                                    D->getLexicalDeclContext(), false, true);
511*0b57cec5SDimitry Andric     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
512*0b57cec5SDimitry Andric     return true;
513*0b57cec5SDimitry Andric   }
514*0b57cec5SDimitry Andric 
515*0b57cec5SDimitry Andric   bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
516*0b57cec5SDimitry Andric     ObjCPropertyDecl *PD = D->getPropertyDecl();
517*0b57cec5SDimitry Andric     auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
518*0b57cec5SDimitry Andric     SourceLocation Loc = D->getLocation();
519*0b57cec5SDimitry Andric     SymbolRoleSet Roles = 0;
520*0b57cec5SDimitry Andric     SmallVector<SymbolRelation, 1> Relations;
521*0b57cec5SDimitry Andric 
522*0b57cec5SDimitry Andric     if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
523*0b57cec5SDimitry Andric       Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
524*0b57cec5SDimitry Andric     if (Loc.isInvalid()) {
525*0b57cec5SDimitry Andric       Loc = Container->getLocation();
526*0b57cec5SDimitry Andric       Roles |= (SymbolRoleSet)SymbolRole::Implicit;
527*0b57cec5SDimitry Andric     }
528*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
529*0b57cec5SDimitry Andric 
530*0b57cec5SDimitry Andric     if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
531*0b57cec5SDimitry Andric       return true;
532*0b57cec5SDimitry Andric 
533*0b57cec5SDimitry Andric     assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
534*0b57cec5SDimitry Andric     SymbolRoleSet AccessorMethodRoles =
535*0b57cec5SDimitry Andric       SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
536*0b57cec5SDimitry Andric     if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
537*0b57cec5SDimitry Andric       if (MD->isPropertyAccessor() &&
538*0b57cec5SDimitry Andric           !hasUserDefined(MD, Container))
539*0b57cec5SDimitry Andric         IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
540*0b57cec5SDimitry Andric     }
541*0b57cec5SDimitry Andric     if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
542*0b57cec5SDimitry Andric       if (MD->isPropertyAccessor() &&
543*0b57cec5SDimitry Andric           !hasUserDefined(MD, Container))
544*0b57cec5SDimitry Andric         IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
545*0b57cec5SDimitry Andric     }
546*0b57cec5SDimitry Andric     if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
547*0b57cec5SDimitry Andric       if (IvarD->getSynthesize()) {
548*0b57cec5SDimitry Andric         // For synthesized ivars, use the location of its name in the
549*0b57cec5SDimitry Andric         // corresponding @synthesize. If there isn't one, use the containing
550*0b57cec5SDimitry Andric         // @implementation's location, rather than the property's location,
551*0b57cec5SDimitry Andric         // otherwise the header file containing the @interface will have different
552*0b57cec5SDimitry Andric         // indexing contents based on whether the @implementation was present or
553*0b57cec5SDimitry Andric         // not in the translation unit.
554*0b57cec5SDimitry Andric         SymbolRoleSet IvarRoles = 0;
555*0b57cec5SDimitry Andric         SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
556*0b57cec5SDimitry Andric         if (D->getLocation().isInvalid()) {
557*0b57cec5SDimitry Andric           IvarLoc = Container->getLocation();
558*0b57cec5SDimitry Andric           IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
559*0b57cec5SDimitry Andric         } else if (D->getLocation() == IvarLoc) {
560*0b57cec5SDimitry Andric           IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
561*0b57cec5SDimitry Andric         }
562*0b57cec5SDimitry Andric         TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
563*0b57cec5SDimitry Andric       } else {
564*0b57cec5SDimitry Andric         IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
565*0b57cec5SDimitry Andric                                  D->getDeclContext(), SymbolRoleSet());
566*0b57cec5SDimitry Andric       }
567*0b57cec5SDimitry Andric     }
568*0b57cec5SDimitry Andric     return true;
569*0b57cec5SDimitry Andric   }
570*0b57cec5SDimitry Andric 
571*0b57cec5SDimitry Andric   bool VisitNamespaceDecl(const NamespaceDecl *D) {
572*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
573*0b57cec5SDimitry Andric     IndexCtx.indexDeclContext(D);
574*0b57cec5SDimitry Andric     return true;
575*0b57cec5SDimitry Andric   }
576*0b57cec5SDimitry Andric 
577*0b57cec5SDimitry Andric   bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
578*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
579*0b57cec5SDimitry Andric     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
580*0b57cec5SDimitry Andric     IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
581*0b57cec5SDimitry Andric                              D->getLexicalDeclContext());
582*0b57cec5SDimitry Andric     return true;
583*0b57cec5SDimitry Andric   }
584*0b57cec5SDimitry Andric 
585*0b57cec5SDimitry Andric   bool VisitUsingDecl(const UsingDecl *D) {
586*0b57cec5SDimitry Andric     IndexCtx.handleDecl(D);
587*0b57cec5SDimitry Andric 
588*0b57cec5SDimitry Andric     const DeclContext *DC = D->getDeclContext()->getRedeclContext();
589*0b57cec5SDimitry Andric     const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
590*0b57cec5SDimitry Andric     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
591*0b57cec5SDimitry Andric                                          D->getLexicalDeclContext());
592*0b57cec5SDimitry Andric     for (const auto *I : D->shadows())
593*0b57cec5SDimitry Andric       IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
594*0b57cec5SDimitry Andric                                D->getLexicalDeclContext(), SymbolRoleSet());
595*0b57cec5SDimitry Andric     return true;
596*0b57cec5SDimitry Andric   }
597*0b57cec5SDimitry Andric 
598*0b57cec5SDimitry Andric   bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
599*0b57cec5SDimitry Andric     const DeclContext *DC = D->getDeclContext()->getRedeclContext();
600*0b57cec5SDimitry Andric     const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
601*0b57cec5SDimitry Andric 
602*0b57cec5SDimitry Andric     // NNS for the local 'using namespace' directives is visited by the body
603*0b57cec5SDimitry Andric     // visitor.
604*0b57cec5SDimitry Andric     if (!D->getParentFunctionOrMethod())
605*0b57cec5SDimitry Andric       IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
606*0b57cec5SDimitry Andric                                            D->getLexicalDeclContext());
607*0b57cec5SDimitry Andric 
608*0b57cec5SDimitry Andric     return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
609*0b57cec5SDimitry Andric                                     D->getLocation(), Parent,
610*0b57cec5SDimitry Andric                                     D->getLexicalDeclContext(),
611*0b57cec5SDimitry Andric                                     SymbolRoleSet());
612*0b57cec5SDimitry Andric   }
613*0b57cec5SDimitry Andric 
614*0b57cec5SDimitry Andric   bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
615*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
616*0b57cec5SDimitry Andric     const DeclContext *DC = D->getDeclContext()->getRedeclContext();
617*0b57cec5SDimitry Andric     const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
618*0b57cec5SDimitry Andric     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
619*0b57cec5SDimitry Andric                                          D->getLexicalDeclContext());
620*0b57cec5SDimitry Andric     return true;
621*0b57cec5SDimitry Andric   }
622*0b57cec5SDimitry Andric 
623*0b57cec5SDimitry Andric   bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
624*0b57cec5SDimitry Andric     TRY_DECL(D, IndexCtx.handleDecl(D));
625*0b57cec5SDimitry Andric     const DeclContext *DC = D->getDeclContext()->getRedeclContext();
626*0b57cec5SDimitry Andric     const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
627*0b57cec5SDimitry Andric     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
628*0b57cec5SDimitry Andric                                          D->getLexicalDeclContext());
629*0b57cec5SDimitry Andric     return true;
630*0b57cec5SDimitry Andric   }
631*0b57cec5SDimitry Andric 
632*0b57cec5SDimitry Andric   bool VisitClassTemplateSpecializationDecl(const
633*0b57cec5SDimitry Andric                                            ClassTemplateSpecializationDecl *D) {
634*0b57cec5SDimitry Andric     // FIXME: Notify subsequent callbacks if info comes from implicit
635*0b57cec5SDimitry Andric     // instantiation.
636*0b57cec5SDimitry Andric     llvm::PointerUnion<ClassTemplateDecl *,
637*0b57cec5SDimitry Andric                        ClassTemplatePartialSpecializationDecl *>
638*0b57cec5SDimitry Andric         Template = D->getSpecializedTemplateOrPartial();
639*0b57cec5SDimitry Andric     const Decl *SpecializationOf =
640*0b57cec5SDimitry Andric         Template.is<ClassTemplateDecl *>()
641*0b57cec5SDimitry Andric             ? (Decl *)Template.get<ClassTemplateDecl *>()
642*0b57cec5SDimitry Andric             : Template.get<ClassTemplatePartialSpecializationDecl *>();
643*0b57cec5SDimitry Andric     if (!D->isThisDeclarationADefinition())
644*0b57cec5SDimitry Andric       IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
645*0b57cec5SDimitry Andric     IndexCtx.indexTagDecl(
646*0b57cec5SDimitry Andric         D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
647*0b57cec5SDimitry Andric                           SpecializationOf));
648*0b57cec5SDimitry Andric     if (TypeSourceInfo *TSI = D->getTypeAsWritten())
649*0b57cec5SDimitry Andric       IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
650*0b57cec5SDimitry Andric                                    D->getLexicalDeclContext());
651*0b57cec5SDimitry Andric     return true;
652*0b57cec5SDimitry Andric   }
653*0b57cec5SDimitry Andric 
654*0b57cec5SDimitry Andric   static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
655*0b57cec5SDimitry Andric     // We want to index the template parameters only once when indexing the
656*0b57cec5SDimitry Andric     // canonical declaration.
657*0b57cec5SDimitry Andric     if (!D)
658*0b57cec5SDimitry Andric       return false;
659*0b57cec5SDimitry Andric     if (const auto *FD = dyn_cast<FunctionDecl>(D))
660*0b57cec5SDimitry Andric       return FD->getCanonicalDecl() == FD;
661*0b57cec5SDimitry Andric     else if (const auto *TD = dyn_cast<TagDecl>(D))
662*0b57cec5SDimitry Andric       return TD->getCanonicalDecl() == TD;
663*0b57cec5SDimitry Andric     else if (const auto *VD = dyn_cast<VarDecl>(D))
664*0b57cec5SDimitry Andric       return VD->getCanonicalDecl() == VD;
665*0b57cec5SDimitry Andric     return true;
666*0b57cec5SDimitry Andric   }
667*0b57cec5SDimitry Andric 
668*0b57cec5SDimitry Andric   bool VisitTemplateDecl(const TemplateDecl *D) {
669*0b57cec5SDimitry Andric 
670*0b57cec5SDimitry Andric     const NamedDecl *Parent = D->getTemplatedDecl();
671*0b57cec5SDimitry Andric     if (!Parent)
672*0b57cec5SDimitry Andric       return true;
673*0b57cec5SDimitry Andric 
674*0b57cec5SDimitry Andric     // Index the default values for the template parameters.
675*0b57cec5SDimitry Andric     if (D->getTemplateParameters() &&
676*0b57cec5SDimitry Andric         shouldIndexTemplateParameterDefaultValue(Parent)) {
677*0b57cec5SDimitry Andric       const TemplateParameterList *Params = D->getTemplateParameters();
678*0b57cec5SDimitry Andric       for (const NamedDecl *TP : *Params) {
679*0b57cec5SDimitry Andric         if (IndexCtx.shouldIndexTemplateParameters())
680*0b57cec5SDimitry Andric           IndexCtx.handleDecl(TP);
681*0b57cec5SDimitry Andric         if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
682*0b57cec5SDimitry Andric           if (TTP->hasDefaultArgument())
683*0b57cec5SDimitry Andric             IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
684*0b57cec5SDimitry Andric         } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
685*0b57cec5SDimitry Andric           if (NTTP->hasDefaultArgument())
686*0b57cec5SDimitry Andric             IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
687*0b57cec5SDimitry Andric         } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
688*0b57cec5SDimitry Andric           if (TTPD->hasDefaultArgument())
689*0b57cec5SDimitry Andric             handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
690*0b57cec5SDimitry Andric                                       TP->getLexicalDeclContext());
691*0b57cec5SDimitry Andric         }
692*0b57cec5SDimitry Andric       }
693*0b57cec5SDimitry Andric     }
694*0b57cec5SDimitry Andric 
695*0b57cec5SDimitry Andric     return Visit(Parent);
696*0b57cec5SDimitry Andric   }
697*0b57cec5SDimitry Andric 
698*0b57cec5SDimitry Andric   bool VisitFriendDecl(const FriendDecl *D) {
699*0b57cec5SDimitry Andric     if (auto ND = D->getFriendDecl()) {
700*0b57cec5SDimitry Andric       // FIXME: Ignore a class template in a dependent context, these are not
701*0b57cec5SDimitry Andric       // linked properly with their redeclarations, ending up with duplicate
702*0b57cec5SDimitry Andric       // USRs.
703*0b57cec5SDimitry Andric       // See comment "Friend templates are visible in fairly strange ways." in
704*0b57cec5SDimitry Andric       // SemaTemplate.cpp which precedes code that prevents the friend template
705*0b57cec5SDimitry Andric       // from becoming visible from the enclosing context.
706*0b57cec5SDimitry Andric       if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
707*0b57cec5SDimitry Andric         return true;
708*0b57cec5SDimitry Andric       return Visit(ND);
709*0b57cec5SDimitry Andric     }
710*0b57cec5SDimitry Andric     if (auto Ty = D->getFriendType()) {
711*0b57cec5SDimitry Andric       IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
712*0b57cec5SDimitry Andric     }
713*0b57cec5SDimitry Andric     return true;
714*0b57cec5SDimitry Andric   }
715*0b57cec5SDimitry Andric 
716*0b57cec5SDimitry Andric   bool VisitImportDecl(const ImportDecl *D) {
717*0b57cec5SDimitry Andric     return IndexCtx.importedModule(D);
718*0b57cec5SDimitry Andric   }
719*0b57cec5SDimitry Andric 
720*0b57cec5SDimitry Andric   bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
721*0b57cec5SDimitry Andric     IndexCtx.indexBody(D->getAssertExpr(),
722*0b57cec5SDimitry Andric                        dyn_cast<NamedDecl>(D->getDeclContext()),
723*0b57cec5SDimitry Andric                        D->getLexicalDeclContext());
724*0b57cec5SDimitry Andric     return true;
725*0b57cec5SDimitry Andric   }
726*0b57cec5SDimitry Andric };
727*0b57cec5SDimitry Andric 
728*0b57cec5SDimitry Andric } // anonymous namespace
729*0b57cec5SDimitry Andric 
730*0b57cec5SDimitry Andric bool IndexingContext::indexDecl(const Decl *D) {
731*0b57cec5SDimitry Andric   if (D->isImplicit() && shouldIgnoreIfImplicit(D))
732*0b57cec5SDimitry Andric     return true;
733*0b57cec5SDimitry Andric 
734*0b57cec5SDimitry Andric   if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
735*0b57cec5SDimitry Andric     return true;
736*0b57cec5SDimitry Andric 
737*0b57cec5SDimitry Andric   IndexingDeclVisitor Visitor(*this);
738*0b57cec5SDimitry Andric   bool ShouldContinue = Visitor.Visit(D);
739*0b57cec5SDimitry Andric   if (!ShouldContinue)
740*0b57cec5SDimitry Andric     return false;
741*0b57cec5SDimitry Andric 
742*0b57cec5SDimitry Andric   if (!Visitor.Handled && isa<DeclContext>(D))
743*0b57cec5SDimitry Andric     return indexDeclContext(cast<DeclContext>(D));
744*0b57cec5SDimitry Andric 
745*0b57cec5SDimitry Andric   return true;
746*0b57cec5SDimitry Andric }
747*0b57cec5SDimitry Andric 
748*0b57cec5SDimitry Andric bool IndexingContext::indexDeclContext(const DeclContext *DC) {
749*0b57cec5SDimitry Andric   for (const auto *I : DC->decls())
750*0b57cec5SDimitry Andric     if (!indexDecl(I))
751*0b57cec5SDimitry Andric       return false;
752*0b57cec5SDimitry Andric   return true;
753*0b57cec5SDimitry Andric }
754*0b57cec5SDimitry Andric 
755*0b57cec5SDimitry Andric bool IndexingContext::indexTopLevelDecl(const Decl *D) {
756*0b57cec5SDimitry Andric   if (D->getLocation().isInvalid())
757*0b57cec5SDimitry Andric     return true;
758*0b57cec5SDimitry Andric 
759*0b57cec5SDimitry Andric   if (isa<ObjCMethodDecl>(D))
760*0b57cec5SDimitry Andric     return true; // Wait for the objc container.
761*0b57cec5SDimitry Andric 
762*0b57cec5SDimitry Andric   return indexDecl(D);
763*0b57cec5SDimitry Andric }
764*0b57cec5SDimitry Andric 
765*0b57cec5SDimitry Andric bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
766*0b57cec5SDimitry Andric   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
767*0b57cec5SDimitry Andric     if (!indexTopLevelDecl(*I))
768*0b57cec5SDimitry Andric       return false;
769*0b57cec5SDimitry Andric   return true;
770*0b57cec5SDimitry Andric }
771