blob: aa73d937df315abb7bfc49bf8d700ce14a5cf1fe [file] [log] [blame]
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +00001//===- IndexDecl.cpp - Indexing declarations ------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "IndexingContext.h"
10#include "clang/Index/IndexDataConsumer.h"
11#include "clang/AST/DeclVisitor.h"
12
13using namespace clang;
14using namespace index;
15
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +000016#define TRY_DECL(D,CALL_EXPR) \
17 do { \
18 if (!IndexCtx.shouldIndex(D)) return true; \
19 if (!CALL_EXPR) \
20 return false; \
21 } while (0)
22
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +000023#define TRY_TO(CALL_EXPR) \
24 do { \
25 if (!CALL_EXPR) \
26 return false; \
27 } while (0)
28
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000029namespace {
30
31class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
32 IndexingContext &IndexCtx;
33
34public:
35 explicit IndexingDeclVisitor(IndexingContext &indexCtx)
36 : IndexCtx(indexCtx) { }
37
38 bool Handled = true;
39
40 bool VisitDecl(const Decl *D) {
41 Handled = false;
42 return true;
43 }
44
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000045 /// Returns true if the given method has been defined explicitly by the
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000046 /// user.
47 static bool hasUserDefined(const ObjCMethodDecl *D,
48 const ObjCImplDecl *Container) {
49 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
50 D->isInstanceMethod());
51 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
52 }
53
Alex Lorenzd43f75b2017-05-12 16:32:26 +000054 void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
55 const NamedDecl *Parent,
56 const DeclContext *DC) {
57 const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();
58 switch (TALoc.getArgument().getKind()) {
59 case TemplateArgument::Expression:
60 IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
61 break;
62 case TemplateArgument::Type:
63 IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
64 break;
Alex Lorenz80cb5492017-05-22 16:50:54 +000065 case TemplateArgument::Template:
66 case TemplateArgument::TemplateExpansion:
67 IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
68 Parent, DC);
69 if (const TemplateDecl *TD = TALoc.getArgument()
70 .getAsTemplateOrTemplatePattern()
71 .getAsTemplateDecl()) {
72 if (const NamedDecl *TTD = TD->getTemplatedDecl())
73 IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
74 }
75 break;
Alex Lorenzd43f75b2017-05-12 16:32:26 +000076 default:
77 break;
78 }
79 }
80
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000081 void handleDeclarator(const DeclaratorDecl *D,
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000082 const NamedDecl *Parent = nullptr,
83 bool isIBType = false) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000084 if (!Parent) Parent = D;
85
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000086 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
87 Parent->getLexicalDeclContext(),
88 /*isBase=*/false, isIBType);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000089 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
90 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
91 // Only index parameters in definitions, parameters in declarations are
92 // not useful.
93 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
94 auto *DC = Parm->getDeclContext();
95 if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
96 if (FD->isThisDeclarationADefinition())
97 IndexCtx.handleDecl(Parm);
98 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
99 if (MD->isThisDeclarationADefinition())
100 IndexCtx.handleDecl(Parm);
101 } else {
102 IndexCtx.handleDecl(Parm);
103 }
104 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
105 if (FD->isThisDeclarationADefinition()) {
David Majnemer59f77922016-06-24 04:05:48 +0000106 for (auto PI : FD->parameters()) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000107 IndexCtx.handleDecl(PI);
108 }
109 }
110 }
Alex Lorenz365cb472017-05-22 15:17:44 +0000111 } else {
112 // Index the default parameter value for function definitions.
113 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
114 if (FD->isThisDeclarationADefinition()) {
115 for (const auto *PV : FD->parameters()) {
116 if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() &&
117 !PV->hasUnparsedDefaultArg())
118 IndexCtx.indexBody(PV->getDefaultArg(), D);
119 }
120 }
121 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000122 }
123 }
124
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000125 bool handleObjCMethod(const ObjCMethodDecl *D,
126 const ObjCPropertyDecl *AssociatedProp = nullptr) {
127 SmallVector<SymbolRelation, 4> Relations;
128 SmallVector<const ObjCMethodDecl*, 4> Overriden;
129
130 D->getOverriddenMethods(Overriden);
131 for(auto overridden: Overriden) {
132 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
133 overridden);
134 }
135 if (AssociatedProp)
136 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
137 AssociatedProp);
138
Argyrios Kyrtzidisaee15fb2017-01-26 02:11:50 +0000139 // getLocation() returns beginning token of a method declaration, but for
140 // indexing purposes we want to point to the base name.
141 SourceLocation MethodLoc = D->getSelectorStartLoc();
142 if (MethodLoc.isInvalid())
143 MethodLoc = D->getLocation();
144
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000145 SourceLocation AttrLoc;
146
147 // check for (getter=/setter=)
148 if (AssociatedProp) {
149 bool isGetter = !D->param_size();
150 AttrLoc = isGetter ?
151 AssociatedProp->getGetterNameLoc():
152 AssociatedProp->getSetterNameLoc();
153 }
154
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000155 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000156 if (D->isImplicit()) {
157 if (AttrLoc.isValid()) {
158 MethodLoc = AttrLoc;
159 } else {
160 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
161 }
162 } else if (AttrLoc.isValid()) {
163 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
164 D->getDeclContext(), 0);
165 }
166
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000167 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000168 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000169 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
170 for (const auto *I : D->parameters()) {
171 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
172 hasIBActionAndFirst = false;
173 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000174
175 if (D->isThisDeclarationADefinition()) {
176 const Stmt *Body = D->getBody();
177 if (Body) {
178 IndexCtx.indexBody(Body, D, D);
179 }
180 }
181 return true;
182 }
183
Alex Lorenza352ba02017-04-24 14:04:58 +0000184 /// Gather the declarations which the given declaration \D overrides in a
185 /// pseudo-override manner.
186 ///
187 /// Pseudo-overrides occur when a class template specialization declares
188 /// a declaration that has the same name as a similar declaration in the
189 /// non-specialized template.
190 void
191 gatherTemplatePseudoOverrides(const NamedDecl *D,
192 SmallVectorImpl<SymbolRelation> &Relations) {
193 if (!IndexCtx.getLangOpts().CPlusPlus)
194 return;
195 const auto *CTSD =
196 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
197 if (!CTSD)
198 return;
199 llvm::PointerUnion<ClassTemplateDecl *,
200 ClassTemplatePartialSpecializationDecl *>
201 Template = CTSD->getSpecializedTemplateOrPartial();
202 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
203 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
204 bool TypeOverride = isa<TypeDecl>(D);
205 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
206 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
207 ND = CTD->getTemplatedDecl();
208 if (ND->isImplicit())
209 continue;
210 // Types can override other types.
211 if (!TypeOverride) {
212 if (ND->getKind() != D->getKind())
213 continue;
214 } else if (!isa<TypeDecl>(ND))
215 continue;
216 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
217 const auto *DFD = cast<FunctionDecl>(D);
218 // Function overrides are approximated using the number of parameters.
219 if (FD->getStorageClass() != DFD->getStorageClass() ||
220 FD->getNumParams() != DFD->getNumParams())
221 continue;
222 }
223 Relations.emplace_back(
Alex Lorenz9e2fea12017-05-04 10:42:06 +0000224 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
Alex Lorenza352ba02017-04-24 14:04:58 +0000225 }
226 }
227 }
228
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000229 bool VisitFunctionDecl(const FunctionDecl *D) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000230 SymbolRoleSet Roles{};
231 SmallVector<SymbolRelation, 4> Relations;
232 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
233 if (CXXMD->isVirtual())
234 Roles |= (unsigned)SymbolRole::Dynamic;
Benjamin Krameracfa3392017-12-17 23:52:45 +0000235 for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
236 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000237 }
238 }
Alex Lorenza352ba02017-04-24 14:04:58 +0000239 gatherTemplatePseudoOverrides(D, Relations);
Alex Lorenz5bf767c2017-04-25 14:22:29 +0000240 if (const auto *Base = D->getPrimaryTemplate())
241 Relations.push_back(
242 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
243 Base->getTemplatedDecl()));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000244
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000245 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000246 handleDeclarator(D);
247
248 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000249 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
250 Ctor->getParent(), Ctor->getDeclContext());
251
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000252 // Constructor initializers.
253 for (const auto *Init : Ctor->inits()) {
254 if (Init->isWritten()) {
255 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
256 if (const FieldDecl *Member = Init->getAnyMember())
257 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
258 (unsigned)SymbolRole::Write);
259 IndexCtx.indexBody(Init->getInit(), D, D);
260 }
261 }
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000262 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
263 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
264 IndexCtx.handleReference(Dtor->getParent(),
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000265 TypeNameInfo->getTypeLoc().getBeginLoc(),
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000266 Dtor->getParent(), Dtor->getDeclContext());
267 }
Argyrios Kyrtzidis47827622017-08-15 17:20:37 +0000268 } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
269 IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
270 Guide->getLocation(), Guide,
271 Guide->getDeclContext());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000272 }
Alex Lorenzd43f75b2017-05-12 16:32:26 +0000273 // Template specialization arguments.
274 if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
275 D->getTemplateSpecializationArgsAsWritten()) {
276 for (const auto &Arg : TemplateArgInfo->arguments())
277 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
278 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000279
280 if (D->isThisDeclarationADefinition()) {
281 const Stmt *Body = D->getBody();
282 if (Body) {
283 IndexCtx.indexBody(Body, D, D);
284 }
285 }
286 return true;
287 }
288
289 bool VisitVarDecl(const VarDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000290 SmallVector<SymbolRelation, 4> Relations;
291 gatherTemplatePseudoOverrides(D, Relations);
292 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000293 handleDeclarator(D);
294 IndexCtx.indexBody(D->getInit(), D);
295 return true;
296 }
297
Alex Lorenz8a656c92017-06-15 21:19:01 +0000298 bool VisitDecompositionDecl(const DecompositionDecl *D) {
299 for (const auto *Binding : D->bindings())
300 TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
301 return Base::VisitDecompositionDecl(D);
302 }
303
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000304 bool VisitFieldDecl(const FieldDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000305 SmallVector<SymbolRelation, 4> Relations;
306 gatherTemplatePseudoOverrides(D, Relations);
307 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000308 handleDeclarator(D);
309 if (D->isBitField())
310 IndexCtx.indexBody(D->getBitWidth(), D);
311 else if (D->hasInClassInitializer())
312 IndexCtx.indexBody(D->getInClassInitializer(), D);
313 return true;
314 }
315
316 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
317 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000318 // handled in VisitObjCPropertyImplDecl
319 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000320 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000321 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000322 handleDeclarator(D);
323 return true;
324 }
325
326 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
327 handleDeclarator(D);
328 return true;
329 }
330
331 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000332 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000333 IndexCtx.indexBody(D->getInitExpr(), D);
334 return true;
335 }
336
337 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000338 if (!D->isTransparentTag()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000339 SmallVector<SymbolRelation, 4> Relations;
340 gatherTemplatePseudoOverrides(D, Relations);
341 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000342 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
343 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000344 return true;
345 }
346
347 bool VisitTagDecl(const TagDecl *D) {
348 // Non-free standing tags are handled in indexTypeSourceInfo.
349 if (D->isFreeStanding()) {
350 if (D->isThisDeclarationADefinition()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000351 SmallVector<SymbolRelation, 4> Relations;
352 gatherTemplatePseudoOverrides(D, Relations);
353 IndexCtx.indexTagDecl(D, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000354 } else {
Alex Lorenzd283dd42017-06-21 13:51:04 +0000355 SmallVector<SymbolRelation, 1> Relations;
356 gatherTemplatePseudoOverrides(D, Relations);
Alex Lorenz41856682017-11-09 20:50:59 +0000357 return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
358 Relations, D->getLexicalDeclContext());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000359 }
360 }
361 return true;
362 }
363
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000364 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000365 const ObjCContainerDecl *ContD,
366 SourceLocation SuperLoc) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000367 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
368 for (ObjCInterfaceDecl::protocol_iterator
369 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
370 SourceLocation Loc = *LI;
371 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000372 SymbolRoleSet roles{};
373 if (Loc == SuperLoc)
374 roles |= (SymbolRoleSet)SymbolRole::Implicit;
375 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000376 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
377 }
378 return true;
379 }
380
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000381 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
382 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000383 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000384 SourceLocation SuperLoc = D->getSuperClassLoc();
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000385 if (auto *SuperD = D->getSuperClass()) {
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000386 bool hasSuperTypedef = false;
387 if (auto *TInfo = D->getSuperClassTInfo()) {
388 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
389 if (auto *TD = TT->getDecl()) {
390 hasSuperTypedef = true;
391 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
392 SymbolRoleSet()));
393 }
394 }
395 }
396 SymbolRoleSet superRoles{};
397 if (hasSuperTypedef)
398 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
399 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000400 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
401 }
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000402 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
403 SuperLoc));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000404 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000405 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000406 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
407 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000408 }
409 return true;
410 }
411
412 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
413 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000414 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000415 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
416 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000417 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000418 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000419 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
420 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000421 }
422 return true;
423 }
424
425 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
426 const ObjCInterfaceDecl *Class = D->getClassInterface();
427 if (!Class)
428 return true;
429
430 if (Class->isImplicitInterfaceDecl())
431 IndexCtx.handleDecl(Class);
432
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000433 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000434
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000435 // Visit implicit @synthesize property implementations first as their
436 // location is reported at the name of the @implementation block. This
437 // serves no purpose other than to simplify the FileCheck-based tests.
438 for (const auto *I : D->property_impls()) {
439 if (I->getLocation().isInvalid())
440 IndexCtx.indexDecl(I);
441 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000442 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000443 if (!isa<ObjCPropertyImplDecl>(I) ||
444 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000445 IndexCtx.indexDecl(I);
446 }
447
448 return true;
449 }
450
451 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000452 if (!IndexCtx.shouldIndex(D))
453 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000454 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000455 if (!C)
456 return true;
457 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
458 SymbolRelation{
459 (unsigned)SymbolRole::RelationExtendedBy, D
460 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000461 SourceLocation CategoryLoc = D->getCategoryNameLoc();
462 if (!CategoryLoc.isValid())
463 CategoryLoc = D->getLocation();
464 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000465 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
466 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000467 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000468 return true;
469 }
470
471 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
472 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
473 if (!Cat)
474 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000475 const ObjCInterfaceDecl *C = D->getClassInterface();
476 if (C)
477 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
478 SymbolRoleSet()));
479 SourceLocation CategoryLoc = D->getCategoryNameLoc();
480 if (!CategoryLoc.isValid())
481 CategoryLoc = D->getLocation();
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000482 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000483 IndexCtx.indexDeclContext(D);
484 return true;
485 }
486
487 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
488 // Methods associated with a property, even user-declared ones, are
489 // handled when we handle the property.
490 if (D->isPropertyAccessor())
491 return true;
492
493 handleObjCMethod(D);
494 return true;
495 }
496
497 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
498 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
499 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000500 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000501 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
502 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000503 handleObjCMethod(MD, D);
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000504 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000505 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
506 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
507 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000508 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
509 return true;
510 }
511
512 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
513 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000514 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
515 SourceLocation Loc = D->getLocation();
516 SymbolRoleSet Roles = 0;
517 SmallVector<SymbolRelation, 1> Relations;
518
519 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
520 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
521 if (Loc.isInvalid()) {
522 Loc = Container->getLocation();
523 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
524 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000525 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000526
527 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
528 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000529
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000530 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000531 SymbolRoleSet AccessorMethodRoles =
532 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000533 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
534 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000535 !hasUserDefined(MD, Container))
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000536 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000537 }
538 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
539 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000540 !hasUserDefined(MD, Container))
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000541 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000542 }
543 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
544 if (IvarD->getSynthesize()) {
545 // For synthesized ivars, use the location of its name in the
546 // corresponding @synthesize. If there isn't one, use the containing
547 // @implementation's location, rather than the property's location,
548 // otherwise the header file containing the @interface will have different
549 // indexing contents based on whether the @implementation was present or
550 // not in the translation unit.
551 SymbolRoleSet IvarRoles = 0;
552 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
553 if (D->getLocation().isInvalid()) {
554 IvarLoc = Container->getLocation();
555 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
556 } else if (D->getLocation() == IvarLoc) {
557 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
558 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000559 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000560 } else {
561 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
562 D->getDeclContext(), SymbolRoleSet());
563 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000564 }
565 return true;
566 }
567
568 bool VisitNamespaceDecl(const NamespaceDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000569 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000570 IndexCtx.indexDeclContext(D);
571 return true;
572 }
573
Alex Lorenz4ab51932017-05-15 10:56:31 +0000574 bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
575 TRY_DECL(D, IndexCtx.handleDecl(D));
576 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
577 IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
578 D->getLexicalDeclContext());
579 return true;
580 }
581
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000582 bool VisitUsingDecl(const UsingDecl *D) {
583 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
584 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
585
586 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
587 D->getLexicalDeclContext());
588 for (const auto *I : D->shadows())
589 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
590 D->getLexicalDeclContext(), SymbolRoleSet());
591 return true;
592 }
593
594 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
595 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
596 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
597
Alex Lorenzd65b3e42017-05-22 14:39:39 +0000598 // NNS for the local 'using namespace' directives is visited by the body
599 // visitor.
600 if (!D->getParentFunctionOrMethod())
601 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
602 D->getLexicalDeclContext());
603
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000604 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
605 D->getLocation(), Parent,
606 D->getLexicalDeclContext(),
607 SymbolRoleSet());
608 }
609
Ben Langmuirfd6e39c2017-08-16 23:12:21 +0000610 bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
611 TRY_DECL(D, IndexCtx.handleDecl(D));
612 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
613 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
614 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
615 D->getLexicalDeclContext());
616 return true;
617 }
618
619 bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
620 TRY_DECL(D, IndexCtx.handleDecl(D));
621 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
622 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
623 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
624 D->getLexicalDeclContext());
625 return true;
626 }
627
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000628 bool VisitClassTemplateSpecializationDecl(const
629 ClassTemplateSpecializationDecl *D) {
630 // FIXME: Notify subsequent callbacks if info comes from implicit
631 // instantiation.
Alex Lorenzb6e03aa2017-06-22 11:20:07 +0000632 llvm::PointerUnion<ClassTemplateDecl *,
633 ClassTemplatePartialSpecializationDecl *>
634 Template = D->getSpecializedTemplateOrPartial();
635 const Decl *SpecializationOf =
636 Template.is<ClassTemplateDecl *>()
637 ? (Decl *)Template.get<ClassTemplateDecl *>()
638 : Template.get<ClassTemplatePartialSpecializationDecl *>();
Alex Lorenz200dc122017-07-04 12:50:53 +0000639 if (!D->isThisDeclarationADefinition())
640 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
Alex Lorenzb6e03aa2017-06-22 11:20:07 +0000641 IndexCtx.indexTagDecl(
642 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
643 SpecializationOf));
Alex Lorenzf41b21e2017-04-25 15:13:42 +0000644 if (TypeSourceInfo *TSI = D->getTypeAsWritten())
645 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
646 D->getLexicalDeclContext());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000647 return true;
648 }
649
Alex Lorenz80cb5492017-05-22 16:50:54 +0000650 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
651 if (!D)
652 return false;
653 // We want to index the template parameters only once when indexing the
654 // canonical declaration.
655 if (const auto *FD = dyn_cast<FunctionDecl>(D))
656 return FD->getCanonicalDecl() == FD;
657 else if (const auto *TD = dyn_cast<TagDecl>(D))
658 return TD->getCanonicalDecl() == TD;
659 else if (const auto *VD = dyn_cast<VarDecl>(D))
660 return VD->getCanonicalDecl() == VD;
661 return true;
662 }
663
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000664 bool VisitTemplateDecl(const TemplateDecl *D) {
Alex Lorenz80cb5492017-05-22 16:50:54 +0000665
Alex Lorenz80cb5492017-05-22 16:50:54 +0000666 const NamedDecl *Parent = D->getTemplatedDecl();
Argyrios Kyrtzidis71b74eb2018-01-26 19:26:12 +0000667 if (!Parent)
668 return true;
669
670 // Index the default values for the template parameters.
Alex Lorenz80cb5492017-05-22 16:50:54 +0000671 if (D->getTemplateParameters() &&
672 shouldIndexTemplateParameterDefaultValue(Parent)) {
673 const TemplateParameterList *Params = D->getTemplateParameters();
674 for (const NamedDecl *TP : *Params) {
675 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
676 if (TTP->hasDefaultArgument())
677 IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
678 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
679 if (NTTP->hasDefaultArgument())
680 IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
681 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
682 if (TTPD->hasDefaultArgument())
683 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
Jan Korous330f0882017-10-10 21:09:49 +0000684 TP->getLexicalDeclContext());
Alex Lorenz80cb5492017-05-22 16:50:54 +0000685 }
686 }
687 }
688
Argyrios Kyrtzidis71b74eb2018-01-26 19:26:12 +0000689 return Visit(Parent);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000690 }
691
692 bool VisitFriendDecl(const FriendDecl *D) {
693 if (auto ND = D->getFriendDecl()) {
694 // FIXME: Ignore a class template in a dependent context, these are not
695 // linked properly with their redeclarations, ending up with duplicate
696 // USRs.
697 // See comment "Friend templates are visible in fairly strange ways." in
698 // SemaTemplate.cpp which precedes code that prevents the friend template
699 // from becoming visible from the enclosing context.
700 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
701 return true;
702 return Visit(ND);
703 }
704 if (auto Ty = D->getFriendType()) {
705 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
706 }
707 return true;
708 }
709
710 bool VisitImportDecl(const ImportDecl *D) {
711 return IndexCtx.importedModule(D);
712 }
Alex Lorenz60aac432017-06-15 20:50:43 +0000713
714 bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
715 IndexCtx.indexBody(D->getAssertExpr(),
716 dyn_cast<NamedDecl>(D->getDeclContext()),
717 D->getLexicalDeclContext());
718 return true;
719 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000720};
721
722} // anonymous namespace
723
724bool IndexingContext::indexDecl(const Decl *D) {
725 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
726 return true;
727
Fangrui Songd50f36e2018-07-09 21:49:06 +0000728 if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000729 return true;
730
731 IndexingDeclVisitor Visitor(*this);
732 bool ShouldContinue = Visitor.Visit(D);
733 if (!ShouldContinue)
734 return false;
735
736 if (!Visitor.Handled && isa<DeclContext>(D))
737 return indexDeclContext(cast<DeclContext>(D));
738
739 return true;
740}
741
742bool IndexingContext::indexDeclContext(const DeclContext *DC) {
743 for (const auto *I : DC->decls())
744 if (!indexDecl(I))
745 return false;
746 return true;
747}
748
749bool IndexingContext::indexTopLevelDecl(const Decl *D) {
750 if (D->getLocation().isInvalid())
751 return true;
752
753 if (isa<ObjCMethodDecl>(D))
754 return true; // Wait for the objc container.
755
756 return indexDecl(D);
757}
758
759bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
760 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
761 if (!indexTopLevelDecl(*I))
762 return false;
763 return true;
764}