blob: 7de70a10b6924c0aebfd38296b2cf5d481dc08a2 [file] [log] [blame]
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +00001//===- IndexDecl.cpp - Indexing declarations ------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "IndexingContext.h"
11#include "clang/Index/IndexDataConsumer.h"
12#include "clang/AST/DeclVisitor.h"
13
14using namespace clang;
15using namespace index;
16
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +000017#define TRY_DECL(D,CALL_EXPR) \
18 do { \
19 if (!IndexCtx.shouldIndex(D)) return true; \
20 if (!CALL_EXPR) \
21 return false; \
22 } while (0)
23
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +000024#define TRY_TO(CALL_EXPR) \
25 do { \
26 if (!CALL_EXPR) \
27 return false; \
28 } while (0)
29
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000030namespace {
31
32class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
33 IndexingContext &IndexCtx;
34
35public:
36 explicit IndexingDeclVisitor(IndexingContext &indexCtx)
37 : IndexCtx(indexCtx) { }
38
39 bool Handled = true;
40
41 bool VisitDecl(const Decl *D) {
42 Handled = false;
43 return true;
44 }
45
46 /// \brief Returns true if the given method has been defined explicitly by the
47 /// user.
48 static bool hasUserDefined(const ObjCMethodDecl *D,
49 const ObjCImplDecl *Container) {
50 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
51 D->isInstanceMethod());
52 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
53 }
54
55 void handleDeclarator(const DeclaratorDecl *D,
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000056 const NamedDecl *Parent = nullptr,
57 bool isIBType = false) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000058 if (!Parent) Parent = D;
59
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000060 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
61 Parent->getLexicalDeclContext(),
62 /*isBase=*/false, isIBType);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000063 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
64 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
65 // Only index parameters in definitions, parameters in declarations are
66 // not useful.
67 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
68 auto *DC = Parm->getDeclContext();
69 if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
70 if (FD->isThisDeclarationADefinition())
71 IndexCtx.handleDecl(Parm);
72 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
73 if (MD->isThisDeclarationADefinition())
74 IndexCtx.handleDecl(Parm);
75 } else {
76 IndexCtx.handleDecl(Parm);
77 }
78 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
79 if (FD->isThisDeclarationADefinition()) {
David Majnemer59f77922016-06-24 04:05:48 +000080 for (auto PI : FD->parameters()) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000081 IndexCtx.handleDecl(PI);
82 }
83 }
84 }
85 }
86 }
87
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +000088 bool handleObjCMethod(const ObjCMethodDecl *D,
89 const ObjCPropertyDecl *AssociatedProp = nullptr) {
90 SmallVector<SymbolRelation, 4> Relations;
91 SmallVector<const ObjCMethodDecl*, 4> Overriden;
92
93 D->getOverriddenMethods(Overriden);
94 for(auto overridden: Overriden) {
95 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
96 overridden);
97 }
98 if (AssociatedProp)
99 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
100 AssociatedProp);
101
Argyrios Kyrtzidisaee15fb2017-01-26 02:11:50 +0000102 // getLocation() returns beginning token of a method declaration, but for
103 // indexing purposes we want to point to the base name.
104 SourceLocation MethodLoc = D->getSelectorStartLoc();
105 if (MethodLoc.isInvalid())
106 MethodLoc = D->getLocation();
107
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000108 SourceLocation AttrLoc;
109
110 // check for (getter=/setter=)
111 if (AssociatedProp) {
112 bool isGetter = !D->param_size();
113 AttrLoc = isGetter ?
114 AssociatedProp->getGetterNameLoc():
115 AssociatedProp->getSetterNameLoc();
116 }
117
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000118 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000119 if (D->isImplicit()) {
120 if (AttrLoc.isValid()) {
121 MethodLoc = AttrLoc;
122 } else {
123 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
124 }
125 } else if (AttrLoc.isValid()) {
126 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
127 D->getDeclContext(), 0);
128 }
129
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000130 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000131 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000132 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
133 for (const auto *I : D->parameters()) {
134 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
135 hasIBActionAndFirst = false;
136 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000137
138 if (D->isThisDeclarationADefinition()) {
139 const Stmt *Body = D->getBody();
140 if (Body) {
141 IndexCtx.indexBody(Body, D, D);
142 }
143 }
144 return true;
145 }
146
Alex Lorenza352ba02017-04-24 14:04:58 +0000147 /// Gather the declarations which the given declaration \D overrides in a
148 /// pseudo-override manner.
149 ///
150 /// Pseudo-overrides occur when a class template specialization declares
151 /// a declaration that has the same name as a similar declaration in the
152 /// non-specialized template.
153 void
154 gatherTemplatePseudoOverrides(const NamedDecl *D,
155 SmallVectorImpl<SymbolRelation> &Relations) {
156 if (!IndexCtx.getLangOpts().CPlusPlus)
157 return;
158 const auto *CTSD =
159 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
160 if (!CTSD)
161 return;
162 llvm::PointerUnion<ClassTemplateDecl *,
163 ClassTemplatePartialSpecializationDecl *>
164 Template = CTSD->getSpecializedTemplateOrPartial();
165 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
166 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
167 bool TypeOverride = isa<TypeDecl>(D);
168 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
169 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
170 ND = CTD->getTemplatedDecl();
171 if (ND->isImplicit())
172 continue;
173 // Types can override other types.
174 if (!TypeOverride) {
175 if (ND->getKind() != D->getKind())
176 continue;
177 } else if (!isa<TypeDecl>(ND))
178 continue;
179 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
180 const auto *DFD = cast<FunctionDecl>(D);
181 // Function overrides are approximated using the number of parameters.
182 if (FD->getStorageClass() != DFD->getStorageClass() ||
183 FD->getNumParams() != DFD->getNumParams())
184 continue;
185 }
186 Relations.emplace_back(
Alex Lorenz9e2fea12017-05-04 10:42:06 +0000187 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
Alex Lorenza352ba02017-04-24 14:04:58 +0000188 }
189 }
190 }
191
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000192 bool VisitFunctionDecl(const FunctionDecl *D) {
193 if (D->isDeleted())
194 return true;
195
196 SymbolRoleSet Roles{};
197 SmallVector<SymbolRelation, 4> Relations;
198 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
199 if (CXXMD->isVirtual())
200 Roles |= (unsigned)SymbolRole::Dynamic;
201 for (auto I = CXXMD->begin_overridden_methods(),
202 E = CXXMD->end_overridden_methods(); I != E; ++I) {
203 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
204 }
205 }
Alex Lorenza352ba02017-04-24 14:04:58 +0000206 gatherTemplatePseudoOverrides(D, Relations);
Alex Lorenz5bf767c2017-04-25 14:22:29 +0000207 if (const auto *Base = D->getPrimaryTemplate())
208 Relations.push_back(
209 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
210 Base->getTemplatedDecl()));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000211
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000212 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000213 handleDeclarator(D);
214
215 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000216 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
217 Ctor->getParent(), Ctor->getDeclContext());
218
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000219 // Constructor initializers.
220 for (const auto *Init : Ctor->inits()) {
221 if (Init->isWritten()) {
222 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
223 if (const FieldDecl *Member = Init->getAnyMember())
224 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
225 (unsigned)SymbolRole::Write);
226 IndexCtx.indexBody(Init->getInit(), D, D);
227 }
228 }
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000229 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
230 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
231 IndexCtx.handleReference(Dtor->getParent(),
232 TypeNameInfo->getTypeLoc().getLocStart(),
233 Dtor->getParent(), Dtor->getDeclContext());
234 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000235 }
236
237 if (D->isThisDeclarationADefinition()) {
238 const Stmt *Body = D->getBody();
239 if (Body) {
240 IndexCtx.indexBody(Body, D, D);
241 }
242 }
243 return true;
244 }
245
246 bool VisitVarDecl(const VarDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000247 SmallVector<SymbolRelation, 4> Relations;
248 gatherTemplatePseudoOverrides(D, Relations);
249 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000250 handleDeclarator(D);
251 IndexCtx.indexBody(D->getInit(), D);
252 return true;
253 }
254
255 bool VisitFieldDecl(const FieldDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000256 SmallVector<SymbolRelation, 4> Relations;
257 gatherTemplatePseudoOverrides(D, Relations);
258 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000259 handleDeclarator(D);
260 if (D->isBitField())
261 IndexCtx.indexBody(D->getBitWidth(), D);
262 else if (D->hasInClassInitializer())
263 IndexCtx.indexBody(D->getInClassInitializer(), D);
264 return true;
265 }
266
267 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
268 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000269 // handled in VisitObjCPropertyImplDecl
270 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000271 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000272 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000273 handleDeclarator(D);
274 return true;
275 }
276
277 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
278 handleDeclarator(D);
279 return true;
280 }
281
282 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000283 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000284 IndexCtx.indexBody(D->getInitExpr(), D);
285 return true;
286 }
287
288 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000289 if (!D->isTransparentTag()) {
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 Kyrtzidisf9326122017-04-21 05:42:40 +0000293 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
294 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000295 return true;
296 }
297
298 bool VisitTagDecl(const TagDecl *D) {
299 // Non-free standing tags are handled in indexTypeSourceInfo.
300 if (D->isFreeStanding()) {
301 if (D->isThisDeclarationADefinition()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000302 SmallVector<SymbolRelation, 4> Relations;
303 gatherTemplatePseudoOverrides(D, Relations);
304 IndexCtx.indexTagDecl(D, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000305 } else {
306 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
307 return IndexCtx.handleReference(D, D->getLocation(), Parent,
308 D->getLexicalDeclContext(),
309 SymbolRoleSet());
310 }
311 }
312 return true;
313 }
314
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000315 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000316 const ObjCContainerDecl *ContD,
317 SourceLocation SuperLoc) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000318 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
319 for (ObjCInterfaceDecl::protocol_iterator
320 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
321 SourceLocation Loc = *LI;
322 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000323 SymbolRoleSet roles{};
324 if (Loc == SuperLoc)
325 roles |= (SymbolRoleSet)SymbolRole::Implicit;
326 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000327 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
328 }
329 return true;
330 }
331
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000332 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
333 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000334 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000335 SourceLocation SuperLoc = D->getSuperClassLoc();
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000336 if (auto *SuperD = D->getSuperClass()) {
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000337 bool hasSuperTypedef = false;
338 if (auto *TInfo = D->getSuperClassTInfo()) {
339 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
340 if (auto *TD = TT->getDecl()) {
341 hasSuperTypedef = true;
342 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
343 SymbolRoleSet()));
344 }
345 }
346 }
347 SymbolRoleSet superRoles{};
348 if (hasSuperTypedef)
349 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
350 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000351 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
352 }
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000353 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
354 SuperLoc));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000355 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000356 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000357 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
358 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000359 }
360 return true;
361 }
362
363 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
364 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000365 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000366 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
367 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000368 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000369 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000370 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
371 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000372 }
373 return true;
374 }
375
376 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
377 const ObjCInterfaceDecl *Class = D->getClassInterface();
378 if (!Class)
379 return true;
380
381 if (Class->isImplicitInterfaceDecl())
382 IndexCtx.handleDecl(Class);
383
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000384 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000385
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000386 // Visit implicit @synthesize property implementations first as their
387 // location is reported at the name of the @implementation block. This
388 // serves no purpose other than to simplify the FileCheck-based tests.
389 for (const auto *I : D->property_impls()) {
390 if (I->getLocation().isInvalid())
391 IndexCtx.indexDecl(I);
392 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000393 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000394 if (!isa<ObjCPropertyImplDecl>(I) ||
395 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000396 IndexCtx.indexDecl(I);
397 }
398
399 return true;
400 }
401
402 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000403 if (!IndexCtx.shouldIndex(D))
404 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000405 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000406 if (!C)
407 return true;
408 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
409 SymbolRelation{
410 (unsigned)SymbolRole::RelationExtendedBy, D
411 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000412 SourceLocation CategoryLoc = D->getCategoryNameLoc();
413 if (!CategoryLoc.isValid())
414 CategoryLoc = D->getLocation();
415 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000416 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
417 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000418 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000419 return true;
420 }
421
422 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
423 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
424 if (!Cat)
425 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000426 const ObjCInterfaceDecl *C = D->getClassInterface();
427 if (C)
428 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
429 SymbolRoleSet()));
430 SourceLocation CategoryLoc = D->getCategoryNameLoc();
431 if (!CategoryLoc.isValid())
432 CategoryLoc = D->getLocation();
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000433 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000434 IndexCtx.indexDeclContext(D);
435 return true;
436 }
437
438 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
439 // Methods associated with a property, even user-declared ones, are
440 // handled when we handle the property.
441 if (D->isPropertyAccessor())
442 return true;
443
444 handleObjCMethod(D);
445 return true;
446 }
447
448 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
449 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
450 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000451 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000452 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
453 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000454 handleObjCMethod(MD, D);
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000455 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000456 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
457 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
458 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000459 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
460 return true;
461 }
462
463 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
464 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000465 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
466 SourceLocation Loc = D->getLocation();
467 SymbolRoleSet Roles = 0;
468 SmallVector<SymbolRelation, 1> Relations;
469
470 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
471 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
472 if (Loc.isInvalid()) {
473 Loc = Container->getLocation();
474 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
475 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000476 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000477
478 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
479 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000480
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000481 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000482 SymbolRoleSet AccessorMethodRoles =
483 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000484 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
485 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000486 !hasUserDefined(MD, Container))
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000487 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000488 }
489 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
490 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000491 !hasUserDefined(MD, Container))
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000492 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000493 }
494 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
495 if (IvarD->getSynthesize()) {
496 // For synthesized ivars, use the location of its name in the
497 // corresponding @synthesize. If there isn't one, use the containing
498 // @implementation's location, rather than the property's location,
499 // otherwise the header file containing the @interface will have different
500 // indexing contents based on whether the @implementation was present or
501 // not in the translation unit.
502 SymbolRoleSet IvarRoles = 0;
503 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
504 if (D->getLocation().isInvalid()) {
505 IvarLoc = Container->getLocation();
506 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
507 } else if (D->getLocation() == IvarLoc) {
508 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
509 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000510 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000511 } else {
512 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
513 D->getDeclContext(), SymbolRoleSet());
514 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000515 }
516 return true;
517 }
518
519 bool VisitNamespaceDecl(const NamespaceDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000520 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000521 IndexCtx.indexDeclContext(D);
522 return true;
523 }
524
525 bool VisitUsingDecl(const UsingDecl *D) {
526 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
527 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
528
529 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
530 D->getLexicalDeclContext());
531 for (const auto *I : D->shadows())
532 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
533 D->getLexicalDeclContext(), SymbolRoleSet());
534 return true;
535 }
536
537 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
538 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
539 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
540
541 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
542 D->getLexicalDeclContext());
543 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
544 D->getLocation(), Parent,
545 D->getLexicalDeclContext(),
546 SymbolRoleSet());
547 }
548
549 bool VisitClassTemplateSpecializationDecl(const
550 ClassTemplateSpecializationDecl *D) {
551 // FIXME: Notify subsequent callbacks if info comes from implicit
552 // instantiation.
Alex Lorenzf6071c32017-04-20 10:43:22 +0000553 if (D->isThisDeclarationADefinition()) {
554 llvm::PointerUnion<ClassTemplateDecl *,
555 ClassTemplatePartialSpecializationDecl *>
556 Template = D->getSpecializedTemplateOrPartial();
557 const Decl *SpecializationOf =
558 Template.is<ClassTemplateDecl *>()
559 ? (Decl *)Template.get<ClassTemplateDecl *>()
560 : Template.get<ClassTemplatePartialSpecializationDecl *>();
561 IndexCtx.indexTagDecl(
562 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
563 SpecializationOf));
564 }
Alex Lorenzf41b21e2017-04-25 15:13:42 +0000565 if (TypeSourceInfo *TSI = D->getTypeAsWritten())
566 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
567 D->getLexicalDeclContext());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000568 return true;
569 }
570
571 bool VisitTemplateDecl(const TemplateDecl *D) {
572 // FIXME: Template parameters.
573 return Visit(D->getTemplatedDecl());
574 }
575
576 bool VisitFriendDecl(const FriendDecl *D) {
577 if (auto ND = D->getFriendDecl()) {
578 // FIXME: Ignore a class template in a dependent context, these are not
579 // linked properly with their redeclarations, ending up with duplicate
580 // USRs.
581 // See comment "Friend templates are visible in fairly strange ways." in
582 // SemaTemplate.cpp which precedes code that prevents the friend template
583 // from becoming visible from the enclosing context.
584 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
585 return true;
586 return Visit(ND);
587 }
588 if (auto Ty = D->getFriendType()) {
589 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
590 }
591 return true;
592 }
593
594 bool VisitImportDecl(const ImportDecl *D) {
595 return IndexCtx.importedModule(D);
596 }
597};
598
599} // anonymous namespace
600
601bool IndexingContext::indexDecl(const Decl *D) {
602 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
603 return true;
604
605 if (isTemplateImplicitInstantiation(D))
606 return true;
607
608 IndexingDeclVisitor Visitor(*this);
609 bool ShouldContinue = Visitor.Visit(D);
610 if (!ShouldContinue)
611 return false;
612
613 if (!Visitor.Handled && isa<DeclContext>(D))
614 return indexDeclContext(cast<DeclContext>(D));
615
616 return true;
617}
618
619bool IndexingContext::indexDeclContext(const DeclContext *DC) {
620 for (const auto *I : DC->decls())
621 if (!indexDecl(I))
622 return false;
623 return true;
624}
625
626bool IndexingContext::indexTopLevelDecl(const Decl *D) {
627 if (D->getLocation().isInvalid())
628 return true;
629
630 if (isa<ObjCMethodDecl>(D))
631 return true; // Wait for the objc container.
632
633 return indexDecl(D);
634}
635
636bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
637 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
638 if (!indexTopLevelDecl(*I))
639 return false;
640 return true;
641}