blob: a60d2f699fec7a51984f302d80a2907e4f41ec1d [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(
187 SymbolRoleSet(SymbolRole::RelationOverrideOf) |
188 SymbolRoleSet(SymbolRole::RelationSpecializationOf),
189 ND);
190 }
191 }
192 }
193
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000194 bool VisitFunctionDecl(const FunctionDecl *D) {
195 if (D->isDeleted())
196 return true;
197
198 SymbolRoleSet Roles{};
199 SmallVector<SymbolRelation, 4> Relations;
200 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
201 if (CXXMD->isVirtual())
202 Roles |= (unsigned)SymbolRole::Dynamic;
203 for (auto I = CXXMD->begin_overridden_methods(),
204 E = CXXMD->end_overridden_methods(); I != E; ++I) {
205 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
206 }
207 }
Alex Lorenza352ba02017-04-24 14:04:58 +0000208 gatherTemplatePseudoOverrides(D, Relations);
Alex Lorenz5bf767c2017-04-25 14:22:29 +0000209 if (const auto *Base = D->getPrimaryTemplate())
210 Relations.push_back(
211 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
212 Base->getTemplatedDecl()));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000213
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000214 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000215 handleDeclarator(D);
216
217 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000218 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
219 Ctor->getParent(), Ctor->getDeclContext());
220
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000221 // Constructor initializers.
222 for (const auto *Init : Ctor->inits()) {
223 if (Init->isWritten()) {
224 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
225 if (const FieldDecl *Member = Init->getAnyMember())
226 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
227 (unsigned)SymbolRole::Write);
228 IndexCtx.indexBody(Init->getInit(), D, D);
229 }
230 }
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000231 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
232 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
233 IndexCtx.handleReference(Dtor->getParent(),
234 TypeNameInfo->getTypeLoc().getLocStart(),
235 Dtor->getParent(), Dtor->getDeclContext());
236 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000237 }
238
239 if (D->isThisDeclarationADefinition()) {
240 const Stmt *Body = D->getBody();
241 if (Body) {
242 IndexCtx.indexBody(Body, D, D);
243 }
244 }
245 return true;
246 }
247
248 bool VisitVarDecl(const VarDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000249 SmallVector<SymbolRelation, 4> Relations;
250 gatherTemplatePseudoOverrides(D, Relations);
251 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000252 handleDeclarator(D);
253 IndexCtx.indexBody(D->getInit(), D);
254 return true;
255 }
256
257 bool VisitFieldDecl(const FieldDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000258 SmallVector<SymbolRelation, 4> Relations;
259 gatherTemplatePseudoOverrides(D, Relations);
260 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000261 handleDeclarator(D);
262 if (D->isBitField())
263 IndexCtx.indexBody(D->getBitWidth(), D);
264 else if (D->hasInClassInitializer())
265 IndexCtx.indexBody(D->getInClassInitializer(), D);
266 return true;
267 }
268
269 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
270 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000271 // handled in VisitObjCPropertyImplDecl
272 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000273 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000274 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000275 handleDeclarator(D);
276 return true;
277 }
278
279 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
280 handleDeclarator(D);
281 return true;
282 }
283
284 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000285 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000286 IndexCtx.indexBody(D->getInitExpr(), D);
287 return true;
288 }
289
290 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000291 if (!D->isTransparentTag()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000292 SmallVector<SymbolRelation, 4> Relations;
293 gatherTemplatePseudoOverrides(D, Relations);
294 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000295 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
296 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000297 return true;
298 }
299
300 bool VisitTagDecl(const TagDecl *D) {
301 // Non-free standing tags are handled in indexTypeSourceInfo.
302 if (D->isFreeStanding()) {
303 if (D->isThisDeclarationADefinition()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000304 SmallVector<SymbolRelation, 4> Relations;
305 gatherTemplatePseudoOverrides(D, Relations);
306 IndexCtx.indexTagDecl(D, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000307 } else {
308 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
309 return IndexCtx.handleReference(D, D->getLocation(), Parent,
310 D->getLexicalDeclContext(),
311 SymbolRoleSet());
312 }
313 }
314 return true;
315 }
316
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000317 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000318 const ObjCContainerDecl *ContD,
319 SourceLocation SuperLoc) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000320 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
321 for (ObjCInterfaceDecl::protocol_iterator
322 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
323 SourceLocation Loc = *LI;
324 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000325 SymbolRoleSet roles{};
326 if (Loc == SuperLoc)
327 roles |= (SymbolRoleSet)SymbolRole::Implicit;
328 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000329 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
330 }
331 return true;
332 }
333
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000334 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
335 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000336 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000337 SourceLocation SuperLoc = D->getSuperClassLoc();
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000338 if (auto *SuperD = D->getSuperClass()) {
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000339 bool hasSuperTypedef = false;
340 if (auto *TInfo = D->getSuperClassTInfo()) {
341 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
342 if (auto *TD = TT->getDecl()) {
343 hasSuperTypedef = true;
344 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
345 SymbolRoleSet()));
346 }
347 }
348 }
349 SymbolRoleSet superRoles{};
350 if (hasSuperTypedef)
351 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
352 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000353 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
354 }
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000355 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
356 SuperLoc));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000357 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000358 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000359 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
360 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000361 }
362 return true;
363 }
364
365 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
366 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000367 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000368 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
369 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000370 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000371 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000372 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
373 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000374 }
375 return true;
376 }
377
378 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
379 const ObjCInterfaceDecl *Class = D->getClassInterface();
380 if (!Class)
381 return true;
382
383 if (Class->isImplicitInterfaceDecl())
384 IndexCtx.handleDecl(Class);
385
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000386 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000387
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000388 // Visit implicit @synthesize property implementations first as their
389 // location is reported at the name of the @implementation block. This
390 // serves no purpose other than to simplify the FileCheck-based tests.
391 for (const auto *I : D->property_impls()) {
392 if (I->getLocation().isInvalid())
393 IndexCtx.indexDecl(I);
394 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000395 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000396 if (!isa<ObjCPropertyImplDecl>(I) ||
397 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000398 IndexCtx.indexDecl(I);
399 }
400
401 return true;
402 }
403
404 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000405 if (!IndexCtx.shouldIndex(D))
406 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000407 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000408 if (!C)
409 return true;
410 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
411 SymbolRelation{
412 (unsigned)SymbolRole::RelationExtendedBy, D
413 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000414 SourceLocation CategoryLoc = D->getCategoryNameLoc();
415 if (!CategoryLoc.isValid())
416 CategoryLoc = D->getLocation();
417 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000418 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
419 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000420 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000421 return true;
422 }
423
424 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
425 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
426 if (!Cat)
427 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000428 const ObjCInterfaceDecl *C = D->getClassInterface();
429 if (C)
430 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
431 SymbolRoleSet()));
432 SourceLocation CategoryLoc = D->getCategoryNameLoc();
433 if (!CategoryLoc.isValid())
434 CategoryLoc = D->getLocation();
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000435 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000436 IndexCtx.indexDeclContext(D);
437 return true;
438 }
439
440 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
441 // Methods associated with a property, even user-declared ones, are
442 // handled when we handle the property.
443 if (D->isPropertyAccessor())
444 return true;
445
446 handleObjCMethod(D);
447 return true;
448 }
449
450 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
451 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
452 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000453 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000454 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
455 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000456 handleObjCMethod(MD, D);
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000457 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000458 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
459 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
460 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000461 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
462 return true;
463 }
464
465 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
466 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000467 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
468 SourceLocation Loc = D->getLocation();
469 SymbolRoleSet Roles = 0;
470 SmallVector<SymbolRelation, 1> Relations;
471
472 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
473 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
474 if (Loc.isInvalid()) {
475 Loc = Container->getLocation();
476 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
477 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000478 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000479
480 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
481 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000482
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000483 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
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))
487 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
488 Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000489 }
490 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
491 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000492 !hasUserDefined(MD, Container))
493 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
494 Container);
495 }
496 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
497 if (IvarD->getSynthesize()) {
498 // For synthesized ivars, use the location of its name in the
499 // corresponding @synthesize. If there isn't one, use the containing
500 // @implementation's location, rather than the property's location,
501 // otherwise the header file containing the @interface will have different
502 // indexing contents based on whether the @implementation was present or
503 // not in the translation unit.
504 SymbolRoleSet IvarRoles = 0;
505 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
506 if (D->getLocation().isInvalid()) {
507 IvarLoc = Container->getLocation();
508 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
509 } else if (D->getLocation() == IvarLoc) {
510 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
511 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000512 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000513 } else {
514 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
515 D->getDeclContext(), SymbolRoleSet());
516 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000517 }
518 return true;
519 }
520
521 bool VisitNamespaceDecl(const NamespaceDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000522 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000523 IndexCtx.indexDeclContext(D);
524 return true;
525 }
526
527 bool VisitUsingDecl(const UsingDecl *D) {
528 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
529 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
530
531 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
532 D->getLexicalDeclContext());
533 for (const auto *I : D->shadows())
534 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
535 D->getLexicalDeclContext(), SymbolRoleSet());
536 return true;
537 }
538
539 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
540 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
541 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
542
543 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
544 D->getLexicalDeclContext());
545 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
546 D->getLocation(), Parent,
547 D->getLexicalDeclContext(),
548 SymbolRoleSet());
549 }
550
551 bool VisitClassTemplateSpecializationDecl(const
552 ClassTemplateSpecializationDecl *D) {
553 // FIXME: Notify subsequent callbacks if info comes from implicit
554 // instantiation.
Alex Lorenzf6071c32017-04-20 10:43:22 +0000555 if (D->isThisDeclarationADefinition()) {
556 llvm::PointerUnion<ClassTemplateDecl *,
557 ClassTemplatePartialSpecializationDecl *>
558 Template = D->getSpecializedTemplateOrPartial();
559 const Decl *SpecializationOf =
560 Template.is<ClassTemplateDecl *>()
561 ? (Decl *)Template.get<ClassTemplateDecl *>()
562 : Template.get<ClassTemplatePartialSpecializationDecl *>();
563 IndexCtx.indexTagDecl(
564 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
565 SpecializationOf));
566 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000567 return true;
568 }
569
570 bool VisitTemplateDecl(const TemplateDecl *D) {
571 // FIXME: Template parameters.
572 return Visit(D->getTemplatedDecl());
573 }
574
575 bool VisitFriendDecl(const FriendDecl *D) {
576 if (auto ND = D->getFriendDecl()) {
577 // FIXME: Ignore a class template in a dependent context, these are not
578 // linked properly with their redeclarations, ending up with duplicate
579 // USRs.
580 // See comment "Friend templates are visible in fairly strange ways." in
581 // SemaTemplate.cpp which precedes code that prevents the friend template
582 // from becoming visible from the enclosing context.
583 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
584 return true;
585 return Visit(ND);
586 }
587 if (auto Ty = D->getFriendType()) {
588 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
589 }
590 return true;
591 }
592
593 bool VisitImportDecl(const ImportDecl *D) {
594 return IndexCtx.importedModule(D);
595 }
596};
597
598} // anonymous namespace
599
600bool IndexingContext::indexDecl(const Decl *D) {
601 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
602 return true;
603
604 if (isTemplateImplicitInstantiation(D))
605 return true;
606
607 IndexingDeclVisitor Visitor(*this);
608 bool ShouldContinue = Visitor.Visit(D);
609 if (!ShouldContinue)
610 return false;
611
612 if (!Visitor.Handled && isa<DeclContext>(D))
613 return indexDeclContext(cast<DeclContext>(D));
614
615 return true;
616}
617
618bool IndexingContext::indexDeclContext(const DeclContext *DC) {
619 for (const auto *I : DC->decls())
620 if (!indexDecl(I))
621 return false;
622 return true;
623}
624
625bool IndexingContext::indexTopLevelDecl(const Decl *D) {
626 if (D->getLocation().isInvalid())
627 return true;
628
629 if (isa<ObjCMethodDecl>(D))
630 return true; // Wait for the objc container.
631
632 return indexDecl(D);
633}
634
635bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
636 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
637 if (!indexTopLevelDecl(*I))
638 return false;
639 return true;
640}