blob: 9bf19270e8de3a154666d5f9a1e3f3e6a0019619 [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 Kyrtzidis34a0c1a2016-03-03 05:33:54 +000017#define TRY_TO(CALL_EXPR) \
18 do { \
19 if (!CALL_EXPR) \
20 return false; \
21 } while (0)
22
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000023namespace {
24
25class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
26 IndexingContext &IndexCtx;
27
28public:
29 explicit IndexingDeclVisitor(IndexingContext &indexCtx)
30 : IndexCtx(indexCtx) { }
31
32 bool Handled = true;
33
34 bool VisitDecl(const Decl *D) {
35 Handled = false;
36 return true;
37 }
38
39 /// \brief Returns true if the given method has been defined explicitly by the
40 /// user.
41 static bool hasUserDefined(const ObjCMethodDecl *D,
42 const ObjCImplDecl *Container) {
43 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
44 D->isInstanceMethod());
45 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
46 }
47
48 void handleDeclarator(const DeclaratorDecl *D,
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000049 const NamedDecl *Parent = nullptr,
50 bool isIBType = false) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000051 if (!Parent) Parent = D;
52
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000053 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
54 Parent->getLexicalDeclContext(),
55 /*isBase=*/false, isIBType);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000056 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
57 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
58 // Only index parameters in definitions, parameters in declarations are
59 // not useful.
60 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
61 auto *DC = Parm->getDeclContext();
62 if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
63 if (FD->isThisDeclarationADefinition())
64 IndexCtx.handleDecl(Parm);
65 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
66 if (MD->isThisDeclarationADefinition())
67 IndexCtx.handleDecl(Parm);
68 } else {
69 IndexCtx.handleDecl(Parm);
70 }
71 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
72 if (FD->isThisDeclarationADefinition()) {
David Majnemer59f77922016-06-24 04:05:48 +000073 for (auto PI : FD->parameters()) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000074 IndexCtx.handleDecl(PI);
75 }
76 }
77 }
78 }
79 }
80
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +000081 bool handleObjCMethod(const ObjCMethodDecl *D,
82 const ObjCPropertyDecl *AssociatedProp = nullptr) {
83 SmallVector<SymbolRelation, 4> Relations;
84 SmallVector<const ObjCMethodDecl*, 4> Overriden;
85
86 D->getOverriddenMethods(Overriden);
87 for(auto overridden: Overriden) {
88 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
89 overridden);
90 }
91 if (AssociatedProp)
92 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
93 AssociatedProp);
94
Argyrios Kyrtzidisaee15fb2017-01-26 02:11:50 +000095 // getLocation() returns beginning token of a method declaration, but for
96 // indexing purposes we want to point to the base name.
97 SourceLocation MethodLoc = D->getSelectorStartLoc();
98 if (MethodLoc.isInvalid())
99 MethodLoc = D->getLocation();
100
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000101 SourceLocation AttrLoc;
102
103 // check for (getter=/setter=)
104 if (AssociatedProp) {
105 bool isGetter = !D->param_size();
106 AttrLoc = isGetter ?
107 AssociatedProp->getGetterNameLoc():
108 AssociatedProp->getSetterNameLoc();
109 }
110
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000111 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000112 if (D->isImplicit()) {
113 if (AttrLoc.isValid()) {
114 MethodLoc = AttrLoc;
115 } else {
116 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
117 }
118 } else if (AttrLoc.isValid()) {
119 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
120 D->getDeclContext(), 0);
121 }
122
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000123 if (!IndexCtx.handleDecl(D, MethodLoc, Roles, Relations))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000124 return false;
125 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000126 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
127 for (const auto *I : D->parameters()) {
128 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
129 hasIBActionAndFirst = false;
130 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000131
132 if (D->isThisDeclarationADefinition()) {
133 const Stmt *Body = D->getBody();
134 if (Body) {
135 IndexCtx.indexBody(Body, D, D);
136 }
137 }
138 return true;
139 }
140
141 bool VisitFunctionDecl(const FunctionDecl *D) {
142 if (D->isDeleted())
143 return true;
144
145 SymbolRoleSet Roles{};
146 SmallVector<SymbolRelation, 4> Relations;
147 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
148 if (CXXMD->isVirtual())
149 Roles |= (unsigned)SymbolRole::Dynamic;
150 for (auto I = CXXMD->begin_overridden_methods(),
151 E = CXXMD->end_overridden_methods(); I != E; ++I) {
152 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
153 }
154 }
155
156 if (!IndexCtx.handleDecl(D, Roles, Relations))
157 return false;
158 handleDeclarator(D);
159
160 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000161 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
162 Ctor->getParent(), Ctor->getDeclContext());
163
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000164 // Constructor initializers.
165 for (const auto *Init : Ctor->inits()) {
166 if (Init->isWritten()) {
167 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
168 if (const FieldDecl *Member = Init->getAnyMember())
169 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
170 (unsigned)SymbolRole::Write);
171 IndexCtx.indexBody(Init->getInit(), D, D);
172 }
173 }
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000174 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
175 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
176 IndexCtx.handleReference(Dtor->getParent(),
177 TypeNameInfo->getTypeLoc().getLocStart(),
178 Dtor->getParent(), Dtor->getDeclContext());
179 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000180 }
181
182 if (D->isThisDeclarationADefinition()) {
183 const Stmt *Body = D->getBody();
184 if (Body) {
185 IndexCtx.indexBody(Body, D, D);
186 }
187 }
188 return true;
189 }
190
191 bool VisitVarDecl(const VarDecl *D) {
192 if (!IndexCtx.handleDecl(D))
193 return false;
194 handleDeclarator(D);
195 IndexCtx.indexBody(D->getInit(), D);
196 return true;
197 }
198
199 bool VisitFieldDecl(const FieldDecl *D) {
200 if (!IndexCtx.handleDecl(D))
201 return false;
202 handleDeclarator(D);
203 if (D->isBitField())
204 IndexCtx.indexBody(D->getBitWidth(), D);
205 else if (D->hasInClassInitializer())
206 IndexCtx.indexBody(D->getInClassInitializer(), D);
207 return true;
208 }
209
210 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
211 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000212 // handled in VisitObjCPropertyImplDecl
213 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000214 }
215 if (!IndexCtx.handleDecl(D))
216 return false;
217 handleDeclarator(D);
218 return true;
219 }
220
221 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
222 handleDeclarator(D);
223 return true;
224 }
225
226 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
227 if (!IndexCtx.handleDecl(D))
228 return false;
229 IndexCtx.indexBody(D->getInitExpr(), D);
230 return true;
231 }
232
233 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000234 if (!D->isTransparentTag()) {
Argyrios Kyrtzidis3b25c912017-03-21 16:56:02 +0000235 if (!IndexCtx.handleDecl(D))
236 return false;
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 Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000276 TRY_TO(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 Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000307 TRY_TO(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
326 if (!IndexCtx.handleDecl(D))
327 return false;
328
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000329 // Visit implicit @synthesize property implementations first as their
330 // location is reported at the name of the @implementation block. This
331 // serves no purpose other than to simplify the FileCheck-based tests.
332 for (const auto *I : D->property_impls()) {
333 if (I->getLocation().isInvalid())
334 IndexCtx.indexDecl(I);
335 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000336 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000337 if (!isa<ObjCPropertyImplDecl>(I) ||
338 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000339 IndexCtx.indexDecl(I);
340 }
341
342 return true;
343 }
344
345 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000346 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000347 if (!C)
348 return true;
349 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
350 SymbolRelation{
351 (unsigned)SymbolRole::RelationExtendedBy, D
352 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000353 SourceLocation CategoryLoc = D->getCategoryNameLoc();
354 if (!CategoryLoc.isValid())
355 CategoryLoc = D->getLocation();
356 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000357 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
358 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000359 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000360 return true;
361 }
362
363 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
364 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
365 if (!Cat)
366 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000367 const ObjCInterfaceDecl *C = D->getClassInterface();
368 if (C)
369 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
370 SymbolRoleSet()));
371 SourceLocation CategoryLoc = D->getCategoryNameLoc();
372 if (!CategoryLoc.isValid())
373 CategoryLoc = D->getLocation();
374 if (!IndexCtx.handleDecl(D, CategoryLoc))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000375 return false;
376 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 Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000397 if (!IndexCtx.handleDecl(D))
398 return false;
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000399 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
400 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
401 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000402 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
403 return true;
404 }
405
406 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
407 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000408 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
409 SourceLocation Loc = D->getLocation();
410 SymbolRoleSet Roles = 0;
411 SmallVector<SymbolRelation, 1> Relations;
412
413 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
414 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
415 if (Loc.isInvalid()) {
416 Loc = Container->getLocation();
417 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
418 }
419 if (!IndexCtx.handleDecl(D, Loc, Roles, Relations))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000420 return false;
421
422 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
423 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000424
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000425 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000426 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
427 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000428 !hasUserDefined(MD, Container))
429 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
430 Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000431 }
432 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
433 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000434 !hasUserDefined(MD, Container))
435 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
436 Container);
437 }
438 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
439 if (IvarD->getSynthesize()) {
440 // For synthesized ivars, use the location of its name in the
441 // corresponding @synthesize. If there isn't one, use the containing
442 // @implementation's location, rather than the property's location,
443 // otherwise the header file containing the @interface will have different
444 // indexing contents based on whether the @implementation was present or
445 // not in the translation unit.
446 SymbolRoleSet IvarRoles = 0;
447 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
448 if (D->getLocation().isInvalid()) {
449 IvarLoc = Container->getLocation();
450 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
451 } else if (D->getLocation() == IvarLoc) {
452 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
453 }
454 if(!IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles))
455 return false;
456 } else {
457 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
458 D->getDeclContext(), SymbolRoleSet());
459 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000460 }
461 return true;
462 }
463
464 bool VisitNamespaceDecl(const NamespaceDecl *D) {
465 if (!IndexCtx.handleDecl(D))
466 return false;
467 IndexCtx.indexDeclContext(D);
468 return true;
469 }
470
471 bool VisitUsingDecl(const UsingDecl *D) {
472 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
473 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
474
475 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
476 D->getLexicalDeclContext());
477 for (const auto *I : D->shadows())
478 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
479 D->getLexicalDeclContext(), SymbolRoleSet());
480 return true;
481 }
482
483 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
484 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
485 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
486
487 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
488 D->getLexicalDeclContext());
489 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
490 D->getLocation(), Parent,
491 D->getLexicalDeclContext(),
492 SymbolRoleSet());
493 }
494
495 bool VisitClassTemplateSpecializationDecl(const
496 ClassTemplateSpecializationDecl *D) {
497 // FIXME: Notify subsequent callbacks if info comes from implicit
498 // instantiation.
Alex Lorenzf6071c32017-04-20 10:43:22 +0000499 if (D->isThisDeclarationADefinition()) {
500 llvm::PointerUnion<ClassTemplateDecl *,
501 ClassTemplatePartialSpecializationDecl *>
502 Template = D->getSpecializedTemplateOrPartial();
503 const Decl *SpecializationOf =
504 Template.is<ClassTemplateDecl *>()
505 ? (Decl *)Template.get<ClassTemplateDecl *>()
506 : Template.get<ClassTemplatePartialSpecializationDecl *>();
507 IndexCtx.indexTagDecl(
508 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
509 SpecializationOf));
510 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000511 return true;
512 }
513
514 bool VisitTemplateDecl(const TemplateDecl *D) {
515 // FIXME: Template parameters.
516 return Visit(D->getTemplatedDecl());
517 }
518
519 bool VisitFriendDecl(const FriendDecl *D) {
520 if (auto ND = D->getFriendDecl()) {
521 // FIXME: Ignore a class template in a dependent context, these are not
522 // linked properly with their redeclarations, ending up with duplicate
523 // USRs.
524 // See comment "Friend templates are visible in fairly strange ways." in
525 // SemaTemplate.cpp which precedes code that prevents the friend template
526 // from becoming visible from the enclosing context.
527 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
528 return true;
529 return Visit(ND);
530 }
531 if (auto Ty = D->getFriendType()) {
532 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
533 }
534 return true;
535 }
536
537 bool VisitImportDecl(const ImportDecl *D) {
538 return IndexCtx.importedModule(D);
539 }
540};
541
542} // anonymous namespace
543
544bool IndexingContext::indexDecl(const Decl *D) {
545 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
546 return true;
547
548 if (isTemplateImplicitInstantiation(D))
549 return true;
550
551 IndexingDeclVisitor Visitor(*this);
552 bool ShouldContinue = Visitor.Visit(D);
553 if (!ShouldContinue)
554 return false;
555
556 if (!Visitor.Handled && isa<DeclContext>(D))
557 return indexDeclContext(cast<DeclContext>(D));
558
559 return true;
560}
561
562bool IndexingContext::indexDeclContext(const DeclContext *DC) {
563 for (const auto *I : DC->decls())
564 if (!indexDecl(I))
565 return false;
566 return true;
567}
568
569bool IndexingContext::indexTopLevelDecl(const Decl *D) {
570 if (D->getLocation().isInvalid())
571 return true;
572
573 if (isa<ObjCMethodDecl>(D))
574 return true; // Wait for the objc container.
575
576 return indexDecl(D);
577}
578
579bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
580 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
581 if (!indexTopLevelDecl(*I))
582 return false;
583 return true;
584}