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