blob: 581e3a27404aff984ba7bafa6757ff2abc6a27bf [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)) {
161 // Constructor initializers.
162 for (const auto *Init : Ctor->inits()) {
163 if (Init->isWritten()) {
164 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
165 if (const FieldDecl *Member = Init->getAnyMember())
166 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
167 (unsigned)SymbolRole::Write);
168 IndexCtx.indexBody(Init->getInit(), D, D);
169 }
170 }
171 }
172
173 if (D->isThisDeclarationADefinition()) {
174 const Stmt *Body = D->getBody();
175 if (Body) {
176 IndexCtx.indexBody(Body, D, D);
177 }
178 }
179 return true;
180 }
181
182 bool VisitVarDecl(const VarDecl *D) {
183 if (!IndexCtx.handleDecl(D))
184 return false;
185 handleDeclarator(D);
186 IndexCtx.indexBody(D->getInit(), D);
187 return true;
188 }
189
190 bool VisitFieldDecl(const FieldDecl *D) {
191 if (!IndexCtx.handleDecl(D))
192 return false;
193 handleDeclarator(D);
194 if (D->isBitField())
195 IndexCtx.indexBody(D->getBitWidth(), D);
196 else if (D->hasInClassInitializer())
197 IndexCtx.indexBody(D->getInClassInitializer(), D);
198 return true;
199 }
200
201 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
202 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000203 // handled in VisitObjCPropertyImplDecl
204 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000205 }
206 if (!IndexCtx.handleDecl(D))
207 return false;
208 handleDeclarator(D);
209 return true;
210 }
211
212 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
213 handleDeclarator(D);
214 return true;
215 }
216
217 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
218 if (!IndexCtx.handleDecl(D))
219 return false;
220 IndexCtx.indexBody(D->getInitExpr(), D);
221 return true;
222 }
223
224 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
225 if (!IndexCtx.handleDecl(D))
226 return false;
227 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
228 return true;
229 }
230
231 bool VisitTagDecl(const TagDecl *D) {
232 // Non-free standing tags are handled in indexTypeSourceInfo.
233 if (D->isFreeStanding()) {
234 if (D->isThisDeclarationADefinition()) {
235 IndexCtx.indexTagDecl(D);
236 } else {
237 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
238 return IndexCtx.handleReference(D, D->getLocation(), Parent,
239 D->getLexicalDeclContext(),
240 SymbolRoleSet());
241 }
242 }
243 return true;
244 }
245
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000246 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000247 const ObjCContainerDecl *ContD,
248 SourceLocation SuperLoc) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000249 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
250 for (ObjCInterfaceDecl::protocol_iterator
251 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
252 SourceLocation Loc = *LI;
253 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000254 SymbolRoleSet roles{};
255 if (Loc == SuperLoc)
256 roles |= (SymbolRoleSet)SymbolRole::Implicit;
257 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000258 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
259 }
260 return true;
261 }
262
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000263 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
264 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000265 TRY_TO(IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000266 SourceLocation SuperLoc = D->getSuperClassLoc();
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000267 if (auto *SuperD = D->getSuperClass()) {
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000268 bool hasSuperTypedef = false;
269 if (auto *TInfo = D->getSuperClassTInfo()) {
270 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
271 if (auto *TD = TT->getDecl()) {
272 hasSuperTypedef = true;
273 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
274 SymbolRoleSet()));
275 }
276 }
277 }
278 SymbolRoleSet superRoles{};
279 if (hasSuperTypedef)
280 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
281 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000282 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
283 }
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000284 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
285 SuperLoc));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000286 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000287 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000288 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
289 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000290 }
291 return true;
292 }
293
294 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
295 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000296 TRY_TO(IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000297 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
298 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000299 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000300 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000301 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
302 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000303 }
304 return true;
305 }
306
307 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
308 const ObjCInterfaceDecl *Class = D->getClassInterface();
309 if (!Class)
310 return true;
311
312 if (Class->isImplicitInterfaceDecl())
313 IndexCtx.handleDecl(Class);
314
315 if (!IndexCtx.handleDecl(D))
316 return false;
317
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000318 // Visit implicit @synthesize property implementations first as their
319 // location is reported at the name of the @implementation block. This
320 // serves no purpose other than to simplify the FileCheck-based tests.
321 for (const auto *I : D->property_impls()) {
322 if (I->getLocation().isInvalid())
323 IndexCtx.indexDecl(I);
324 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000325 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000326 if (!isa<ObjCPropertyImplDecl>(I) ||
327 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000328 IndexCtx.indexDecl(I);
329 }
330
331 return true;
332 }
333
334 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000335 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000336 if (!C)
337 return true;
338 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
339 SymbolRelation{
340 (unsigned)SymbolRole::RelationExtendedBy, D
341 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000342 SourceLocation CategoryLoc = D->getCategoryNameLoc();
343 if (!CategoryLoc.isValid())
344 CategoryLoc = D->getLocation();
345 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000346 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
347 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000348 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000349 return true;
350 }
351
352 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
353 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
354 if (!Cat)
355 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000356 const ObjCInterfaceDecl *C = D->getClassInterface();
357 if (C)
358 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
359 SymbolRoleSet()));
360 SourceLocation CategoryLoc = D->getCategoryNameLoc();
361 if (!CategoryLoc.isValid())
362 CategoryLoc = D->getLocation();
363 if (!IndexCtx.handleDecl(D, CategoryLoc))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000364 return false;
365 IndexCtx.indexDeclContext(D);
366 return true;
367 }
368
369 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
370 // Methods associated with a property, even user-declared ones, are
371 // handled when we handle the property.
372 if (D->isPropertyAccessor())
373 return true;
374
375 handleObjCMethod(D);
376 return true;
377 }
378
379 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
380 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
381 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000382 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000383 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
384 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000385 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000386 if (!IndexCtx.handleDecl(D))
387 return false;
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000388 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
389 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
390 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000391 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
392 return true;
393 }
394
395 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
396 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000397 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
398 SourceLocation Loc = D->getLocation();
399 SymbolRoleSet Roles = 0;
400 SmallVector<SymbolRelation, 1> Relations;
401
402 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
403 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
404 if (Loc.isInvalid()) {
405 Loc = Container->getLocation();
406 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
407 }
408 if (!IndexCtx.handleDecl(D, Loc, Roles, Relations))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000409 return false;
410
411 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
412 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000413
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000414 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000415 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
416 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000417 !hasUserDefined(MD, Container))
418 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
419 Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000420 }
421 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
422 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000423 !hasUserDefined(MD, Container))
424 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
425 Container);
426 }
427 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
428 if (IvarD->getSynthesize()) {
429 // For synthesized ivars, use the location of its name in the
430 // corresponding @synthesize. If there isn't one, use the containing
431 // @implementation's location, rather than the property's location,
432 // otherwise the header file containing the @interface will have different
433 // indexing contents based on whether the @implementation was present or
434 // not in the translation unit.
435 SymbolRoleSet IvarRoles = 0;
436 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
437 if (D->getLocation().isInvalid()) {
438 IvarLoc = Container->getLocation();
439 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
440 } else if (D->getLocation() == IvarLoc) {
441 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
442 }
443 if(!IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles))
444 return false;
445 } else {
446 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
447 D->getDeclContext(), SymbolRoleSet());
448 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000449 }
450 return true;
451 }
452
453 bool VisitNamespaceDecl(const NamespaceDecl *D) {
454 if (!IndexCtx.handleDecl(D))
455 return false;
456 IndexCtx.indexDeclContext(D);
457 return true;
458 }
459
460 bool VisitUsingDecl(const UsingDecl *D) {
461 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
462 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
463
464 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
465 D->getLexicalDeclContext());
466 for (const auto *I : D->shadows())
467 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
468 D->getLexicalDeclContext(), SymbolRoleSet());
469 return true;
470 }
471
472 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
473 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
474 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
475
476 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
477 D->getLexicalDeclContext());
478 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
479 D->getLocation(), Parent,
480 D->getLexicalDeclContext(),
481 SymbolRoleSet());
482 }
483
484 bool VisitClassTemplateSpecializationDecl(const
485 ClassTemplateSpecializationDecl *D) {
486 // FIXME: Notify subsequent callbacks if info comes from implicit
487 // instantiation.
488 if (D->isThisDeclarationADefinition())
489 IndexCtx.indexTagDecl(D);
490 return true;
491 }
492
493 bool VisitTemplateDecl(const TemplateDecl *D) {
494 // FIXME: Template parameters.
495 return Visit(D->getTemplatedDecl());
496 }
497
498 bool VisitFriendDecl(const FriendDecl *D) {
499 if (auto ND = D->getFriendDecl()) {
500 // FIXME: Ignore a class template in a dependent context, these are not
501 // linked properly with their redeclarations, ending up with duplicate
502 // USRs.
503 // See comment "Friend templates are visible in fairly strange ways." in
504 // SemaTemplate.cpp which precedes code that prevents the friend template
505 // from becoming visible from the enclosing context.
506 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
507 return true;
508 return Visit(ND);
509 }
510 if (auto Ty = D->getFriendType()) {
511 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
512 }
513 return true;
514 }
515
516 bool VisitImportDecl(const ImportDecl *D) {
517 return IndexCtx.importedModule(D);
518 }
519};
520
521} // anonymous namespace
522
523bool IndexingContext::indexDecl(const Decl *D) {
524 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
525 return true;
526
527 if (isTemplateImplicitInstantiation(D))
528 return true;
529
530 IndexingDeclVisitor Visitor(*this);
531 bool ShouldContinue = Visitor.Visit(D);
532 if (!ShouldContinue)
533 return false;
534
535 if (!Visitor.Handled && isa<DeclContext>(D))
536 return indexDeclContext(cast<DeclContext>(D));
537
538 return true;
539}
540
541bool IndexingContext::indexDeclContext(const DeclContext *DC) {
542 for (const auto *I : DC->decls())
543 if (!indexDecl(I))
544 return false;
545 return true;
546}
547
548bool IndexingContext::indexTopLevelDecl(const Decl *D) {
549 if (D->getLocation().isInvalid())
550 return true;
551
552 if (isa<ObjCMethodDecl>(D))
553 return true; // Wait for the objc container.
554
555 return indexDecl(D);
556}
557
558bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
559 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
560 if (!indexTopLevelDecl(*I))
561 return false;
562 return true;
563}