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