blob: 8028f8892f0d9f9f0763e5591b84be4e24d07fcf [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
147 bool VisitFunctionDecl(const FunctionDecl *D) {
148 if (D->isDeleted())
149 return true;
150
151 SymbolRoleSet Roles{};
152 SmallVector<SymbolRelation, 4> Relations;
153 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
154 if (CXXMD->isVirtual())
155 Roles |= (unsigned)SymbolRole::Dynamic;
156 for (auto I = CXXMD->begin_overridden_methods(),
157 E = CXXMD->end_overridden_methods(); I != E; ++I) {
158 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
159 }
160 }
161
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000162 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000163 handleDeclarator(D);
164
165 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000166 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
167 Ctor->getParent(), Ctor->getDeclContext());
168
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000169 // Constructor initializers.
170 for (const auto *Init : Ctor->inits()) {
171 if (Init->isWritten()) {
172 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
173 if (const FieldDecl *Member = Init->getAnyMember())
174 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
175 (unsigned)SymbolRole::Write);
176 IndexCtx.indexBody(Init->getInit(), D, D);
177 }
178 }
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000179 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
180 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
181 IndexCtx.handleReference(Dtor->getParent(),
182 TypeNameInfo->getTypeLoc().getLocStart(),
183 Dtor->getParent(), Dtor->getDeclContext());
184 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000185 }
186
187 if (D->isThisDeclarationADefinition()) {
188 const Stmt *Body = D->getBody();
189 if (Body) {
190 IndexCtx.indexBody(Body, D, D);
191 }
192 }
193 return true;
194 }
195
196 bool VisitVarDecl(const VarDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000197 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000198 handleDeclarator(D);
199 IndexCtx.indexBody(D->getInit(), D);
200 return true;
201 }
202
203 bool VisitFieldDecl(const FieldDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000204 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000205 handleDeclarator(D);
206 if (D->isBitField())
207 IndexCtx.indexBody(D->getBitWidth(), D);
208 else if (D->hasInClassInitializer())
209 IndexCtx.indexBody(D->getInClassInitializer(), D);
210 return true;
211 }
212
213 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
214 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000215 // handled in VisitObjCPropertyImplDecl
216 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000217 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000218 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000219 handleDeclarator(D);
220 return true;
221 }
222
223 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
224 handleDeclarator(D);
225 return true;
226 }
227
228 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000229 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000230 IndexCtx.indexBody(D->getInitExpr(), D);
231 return true;
232 }
233
234 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000235 if (!D->isTransparentTag()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000236 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000237 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
238 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000239 return true;
240 }
241
242 bool VisitTagDecl(const TagDecl *D) {
243 // Non-free standing tags are handled in indexTypeSourceInfo.
244 if (D->isFreeStanding()) {
245 if (D->isThisDeclarationADefinition()) {
246 IndexCtx.indexTagDecl(D);
247 } else {
248 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
249 return IndexCtx.handleReference(D, D->getLocation(), Parent,
250 D->getLexicalDeclContext(),
251 SymbolRoleSet());
252 }
253 }
254 return true;
255 }
256
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000257 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000258 const ObjCContainerDecl *ContD,
259 SourceLocation SuperLoc) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000260 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
261 for (ObjCInterfaceDecl::protocol_iterator
262 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
263 SourceLocation Loc = *LI;
264 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000265 SymbolRoleSet roles{};
266 if (Loc == SuperLoc)
267 roles |= (SymbolRoleSet)SymbolRole::Implicit;
268 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000269 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
270 }
271 return true;
272 }
273
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000274 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
275 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000276 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000277 SourceLocation SuperLoc = D->getSuperClassLoc();
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000278 if (auto *SuperD = D->getSuperClass()) {
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000279 bool hasSuperTypedef = false;
280 if (auto *TInfo = D->getSuperClassTInfo()) {
281 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
282 if (auto *TD = TT->getDecl()) {
283 hasSuperTypedef = true;
284 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
285 SymbolRoleSet()));
286 }
287 }
288 }
289 SymbolRoleSet superRoles{};
290 if (hasSuperTypedef)
291 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
292 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000293 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
294 }
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000295 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
296 SuperLoc));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000297 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000298 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000299 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
300 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000301 }
302 return true;
303 }
304
305 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
306 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000307 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000308 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
309 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000310 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000311 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000312 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
313 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000314 }
315 return true;
316 }
317
318 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
319 const ObjCInterfaceDecl *Class = D->getClassInterface();
320 if (!Class)
321 return true;
322
323 if (Class->isImplicitInterfaceDecl())
324 IndexCtx.handleDecl(Class);
325
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000326 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000327
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000328 // Visit implicit @synthesize property implementations first as their
329 // location is reported at the name of the @implementation block. This
330 // serves no purpose other than to simplify the FileCheck-based tests.
331 for (const auto *I : D->property_impls()) {
332 if (I->getLocation().isInvalid())
333 IndexCtx.indexDecl(I);
334 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000335 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000336 if (!isa<ObjCPropertyImplDecl>(I) ||
337 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000338 IndexCtx.indexDecl(I);
339 }
340
341 return true;
342 }
343
344 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000345 if (!IndexCtx.shouldIndex(D))
346 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000347 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000348 if (!C)
349 return true;
350 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
351 SymbolRelation{
352 (unsigned)SymbolRole::RelationExtendedBy, D
353 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000354 SourceLocation CategoryLoc = D->getCategoryNameLoc();
355 if (!CategoryLoc.isValid())
356 CategoryLoc = D->getLocation();
357 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000358 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
359 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000360 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000361 return true;
362 }
363
364 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
365 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
366 if (!Cat)
367 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000368 const ObjCInterfaceDecl *C = D->getClassInterface();
369 if (C)
370 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
371 SymbolRoleSet()));
372 SourceLocation CategoryLoc = D->getCategoryNameLoc();
373 if (!CategoryLoc.isValid())
374 CategoryLoc = D->getLocation();
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000375 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000376 IndexCtx.indexDeclContext(D);
377 return true;
378 }
379
380 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
381 // Methods associated with a property, even user-declared ones, are
382 // handled when we handle the property.
383 if (D->isPropertyAccessor())
384 return true;
385
386 handleObjCMethod(D);
387 return true;
388 }
389
390 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
391 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
392 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000393 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000394 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
395 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000396 handleObjCMethod(MD, D);
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000397 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000398 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
399 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
400 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000401 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
402 return true;
403 }
404
405 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
406 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000407 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
408 SourceLocation Loc = D->getLocation();
409 SymbolRoleSet Roles = 0;
410 SmallVector<SymbolRelation, 1> Relations;
411
412 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
413 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
414 if (Loc.isInvalid()) {
415 Loc = Container->getLocation();
416 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
417 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000418 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000419
420 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
421 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000422
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000423 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000424 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
425 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000426 !hasUserDefined(MD, Container))
427 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
428 Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000429 }
430 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
431 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000432 !hasUserDefined(MD, Container))
433 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
434 Container);
435 }
436 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
437 if (IvarD->getSynthesize()) {
438 // For synthesized ivars, use the location of its name in the
439 // corresponding @synthesize. If there isn't one, use the containing
440 // @implementation's location, rather than the property's location,
441 // otherwise the header file containing the @interface will have different
442 // indexing contents based on whether the @implementation was present or
443 // not in the translation unit.
444 SymbolRoleSet IvarRoles = 0;
445 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
446 if (D->getLocation().isInvalid()) {
447 IvarLoc = Container->getLocation();
448 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
449 } else if (D->getLocation() == IvarLoc) {
450 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
451 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000452 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000453 } else {
454 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
455 D->getDeclContext(), SymbolRoleSet());
456 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000457 }
458 return true;
459 }
460
461 bool VisitNamespaceDecl(const NamespaceDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000462 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000463 IndexCtx.indexDeclContext(D);
464 return true;
465 }
466
467 bool VisitUsingDecl(const UsingDecl *D) {
468 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
469 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
470
471 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
472 D->getLexicalDeclContext());
473 for (const auto *I : D->shadows())
474 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
475 D->getLexicalDeclContext(), SymbolRoleSet());
476 return true;
477 }
478
479 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
480 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
481 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
482
483 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
484 D->getLexicalDeclContext());
485 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
486 D->getLocation(), Parent,
487 D->getLexicalDeclContext(),
488 SymbolRoleSet());
489 }
490
491 bool VisitClassTemplateSpecializationDecl(const
492 ClassTemplateSpecializationDecl *D) {
493 // FIXME: Notify subsequent callbacks if info comes from implicit
494 // instantiation.
Alex Lorenzf6071c32017-04-20 10:43:22 +0000495 if (D->isThisDeclarationADefinition()) {
496 llvm::PointerUnion<ClassTemplateDecl *,
497 ClassTemplatePartialSpecializationDecl *>
498 Template = D->getSpecializedTemplateOrPartial();
499 const Decl *SpecializationOf =
500 Template.is<ClassTemplateDecl *>()
501 ? (Decl *)Template.get<ClassTemplateDecl *>()
502 : Template.get<ClassTemplatePartialSpecializationDecl *>();
503 IndexCtx.indexTagDecl(
504 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
505 SpecializationOf));
506 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000507 return true;
508 }
509
510 bool VisitTemplateDecl(const TemplateDecl *D) {
511 // FIXME: Template parameters.
512 return Visit(D->getTemplatedDecl());
513 }
514
515 bool VisitFriendDecl(const FriendDecl *D) {
516 if (auto ND = D->getFriendDecl()) {
517 // FIXME: Ignore a class template in a dependent context, these are not
518 // linked properly with their redeclarations, ending up with duplicate
519 // USRs.
520 // See comment "Friend templates are visible in fairly strange ways." in
521 // SemaTemplate.cpp which precedes code that prevents the friend template
522 // from becoming visible from the enclosing context.
523 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
524 return true;
525 return Visit(ND);
526 }
527 if (auto Ty = D->getFriendType()) {
528 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
529 }
530 return true;
531 }
532
533 bool VisitImportDecl(const ImportDecl *D) {
534 return IndexCtx.importedModule(D);
535 }
536};
537
538} // anonymous namespace
539
540bool IndexingContext::indexDecl(const Decl *D) {
541 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
542 return true;
543
544 if (isTemplateImplicitInstantiation(D))
545 return true;
546
547 IndexingDeclVisitor Visitor(*this);
548 bool ShouldContinue = Visitor.Visit(D);
549 if (!ShouldContinue)
550 return false;
551
552 if (!Visitor.Handled && isa<DeclContext>(D))
553 return indexDeclContext(cast<DeclContext>(D));
554
555 return true;
556}
557
558bool IndexingContext::indexDeclContext(const DeclContext *DC) {
559 for (const auto *I : DC->decls())
560 if (!indexDecl(I))
561 return false;
562 return true;
563}
564
565bool IndexingContext::indexTopLevelDecl(const Decl *D) {
566 if (D->getLocation().isInvalid())
567 return true;
568
569 if (isa<ObjCMethodDecl>(D))
570 return true; // Wait for the objc container.
571
572 return indexDecl(D);
573}
574
575bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
576 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
577 if (!indexTopLevelDecl(*I))
578 return false;
579 return true;
580}