blob: ba65889a6f90215d9e339ed682ccfc9eab64be5d [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);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000209
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000210 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000211 handleDeclarator(D);
212
213 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000214 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
215 Ctor->getParent(), Ctor->getDeclContext());
216
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000217 // Constructor initializers.
218 for (const auto *Init : Ctor->inits()) {
219 if (Init->isWritten()) {
220 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
221 if (const FieldDecl *Member = Init->getAnyMember())
222 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
223 (unsigned)SymbolRole::Write);
224 IndexCtx.indexBody(Init->getInit(), D, D);
225 }
226 }
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000227 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
228 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
229 IndexCtx.handleReference(Dtor->getParent(),
230 TypeNameInfo->getTypeLoc().getLocStart(),
231 Dtor->getParent(), Dtor->getDeclContext());
232 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000233 }
234
235 if (D->isThisDeclarationADefinition()) {
236 const Stmt *Body = D->getBody();
237 if (Body) {
238 IndexCtx.indexBody(Body, D, D);
239 }
240 }
241 return true;
242 }
243
244 bool VisitVarDecl(const VarDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000245 SmallVector<SymbolRelation, 4> Relations;
246 gatherTemplatePseudoOverrides(D, Relations);
247 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000248 handleDeclarator(D);
249 IndexCtx.indexBody(D->getInit(), D);
250 return true;
251 }
252
253 bool VisitFieldDecl(const FieldDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000254 SmallVector<SymbolRelation, 4> Relations;
255 gatherTemplatePseudoOverrides(D, Relations);
256 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000257 handleDeclarator(D);
258 if (D->isBitField())
259 IndexCtx.indexBody(D->getBitWidth(), D);
260 else if (D->hasInClassInitializer())
261 IndexCtx.indexBody(D->getInClassInitializer(), D);
262 return true;
263 }
264
265 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
266 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000267 // handled in VisitObjCPropertyImplDecl
268 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000269 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000270 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000271 handleDeclarator(D);
272 return true;
273 }
274
275 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
276 handleDeclarator(D);
277 return true;
278 }
279
280 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000281 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000282 IndexCtx.indexBody(D->getInitExpr(), D);
283 return true;
284 }
285
286 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000287 if (!D->isTransparentTag()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000288 SmallVector<SymbolRelation, 4> Relations;
289 gatherTemplatePseudoOverrides(D, Relations);
290 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000291 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
292 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000293 return true;
294 }
295
296 bool VisitTagDecl(const TagDecl *D) {
297 // Non-free standing tags are handled in indexTypeSourceInfo.
298 if (D->isFreeStanding()) {
299 if (D->isThisDeclarationADefinition()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000300 SmallVector<SymbolRelation, 4> Relations;
301 gatherTemplatePseudoOverrides(D, Relations);
302 IndexCtx.indexTagDecl(D, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000303 } else {
304 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
305 return IndexCtx.handleReference(D, D->getLocation(), Parent,
306 D->getLexicalDeclContext(),
307 SymbolRoleSet());
308 }
309 }
310 return true;
311 }
312
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000313 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000314 const ObjCContainerDecl *ContD,
315 SourceLocation SuperLoc) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000316 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
317 for (ObjCInterfaceDecl::protocol_iterator
318 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
319 SourceLocation Loc = *LI;
320 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000321 SymbolRoleSet roles{};
322 if (Loc == SuperLoc)
323 roles |= (SymbolRoleSet)SymbolRole::Implicit;
324 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000325 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
326 }
327 return true;
328 }
329
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000330 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
331 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000332 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000333 SourceLocation SuperLoc = D->getSuperClassLoc();
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000334 if (auto *SuperD = D->getSuperClass()) {
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000335 bool hasSuperTypedef = false;
336 if (auto *TInfo = D->getSuperClassTInfo()) {
337 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
338 if (auto *TD = TT->getDecl()) {
339 hasSuperTypedef = true;
340 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
341 SymbolRoleSet()));
342 }
343 }
344 }
345 SymbolRoleSet superRoles{};
346 if (hasSuperTypedef)
347 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
348 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000349 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
350 }
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000351 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
352 SuperLoc));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000353 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000354 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000355 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
356 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000357 }
358 return true;
359 }
360
361 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
362 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000363 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000364 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
365 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000366 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000367 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000368 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
369 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000370 }
371 return true;
372 }
373
374 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
375 const ObjCInterfaceDecl *Class = D->getClassInterface();
376 if (!Class)
377 return true;
378
379 if (Class->isImplicitInterfaceDecl())
380 IndexCtx.handleDecl(Class);
381
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000382 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000383
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000384 // Visit implicit @synthesize property implementations first as their
385 // location is reported at the name of the @implementation block. This
386 // serves no purpose other than to simplify the FileCheck-based tests.
387 for (const auto *I : D->property_impls()) {
388 if (I->getLocation().isInvalid())
389 IndexCtx.indexDecl(I);
390 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000391 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000392 if (!isa<ObjCPropertyImplDecl>(I) ||
393 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000394 IndexCtx.indexDecl(I);
395 }
396
397 return true;
398 }
399
400 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000401 if (!IndexCtx.shouldIndex(D))
402 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000403 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000404 if (!C)
405 return true;
406 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
407 SymbolRelation{
408 (unsigned)SymbolRole::RelationExtendedBy, D
409 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000410 SourceLocation CategoryLoc = D->getCategoryNameLoc();
411 if (!CategoryLoc.isValid())
412 CategoryLoc = D->getLocation();
413 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000414 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
415 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000416 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000417 return true;
418 }
419
420 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
421 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
422 if (!Cat)
423 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000424 const ObjCInterfaceDecl *C = D->getClassInterface();
425 if (C)
426 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
427 SymbolRoleSet()));
428 SourceLocation CategoryLoc = D->getCategoryNameLoc();
429 if (!CategoryLoc.isValid())
430 CategoryLoc = D->getLocation();
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000431 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000432 IndexCtx.indexDeclContext(D);
433 return true;
434 }
435
436 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
437 // Methods associated with a property, even user-declared ones, are
438 // handled when we handle the property.
439 if (D->isPropertyAccessor())
440 return true;
441
442 handleObjCMethod(D);
443 return true;
444 }
445
446 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
447 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
448 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000449 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000450 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
451 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000452 handleObjCMethod(MD, D);
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000453 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000454 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
455 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
456 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000457 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
458 return true;
459 }
460
461 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
462 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000463 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
464 SourceLocation Loc = D->getLocation();
465 SymbolRoleSet Roles = 0;
466 SmallVector<SymbolRelation, 1> Relations;
467
468 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
469 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
470 if (Loc.isInvalid()) {
471 Loc = Container->getLocation();
472 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
473 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000474 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000475
476 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
477 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000478
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000479 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000480 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
481 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000482 !hasUserDefined(MD, Container))
483 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
484 Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000485 }
486 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
487 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000488 !hasUserDefined(MD, Container))
489 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {},
490 Container);
491 }
492 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
493 if (IvarD->getSynthesize()) {
494 // For synthesized ivars, use the location of its name in the
495 // corresponding @synthesize. If there isn't one, use the containing
496 // @implementation's location, rather than the property's location,
497 // otherwise the header file containing the @interface will have different
498 // indexing contents based on whether the @implementation was present or
499 // not in the translation unit.
500 SymbolRoleSet IvarRoles = 0;
501 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
502 if (D->getLocation().isInvalid()) {
503 IvarLoc = Container->getLocation();
504 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
505 } else if (D->getLocation() == IvarLoc) {
506 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
507 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000508 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000509 } else {
510 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
511 D->getDeclContext(), SymbolRoleSet());
512 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000513 }
514 return true;
515 }
516
517 bool VisitNamespaceDecl(const NamespaceDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000518 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000519 IndexCtx.indexDeclContext(D);
520 return true;
521 }
522
523 bool VisitUsingDecl(const UsingDecl *D) {
524 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
525 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
526
527 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
528 D->getLexicalDeclContext());
529 for (const auto *I : D->shadows())
530 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
531 D->getLexicalDeclContext(), SymbolRoleSet());
532 return true;
533 }
534
535 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
536 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
537 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
538
539 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
540 D->getLexicalDeclContext());
541 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
542 D->getLocation(), Parent,
543 D->getLexicalDeclContext(),
544 SymbolRoleSet());
545 }
546
547 bool VisitClassTemplateSpecializationDecl(const
548 ClassTemplateSpecializationDecl *D) {
549 // FIXME: Notify subsequent callbacks if info comes from implicit
550 // instantiation.
Alex Lorenzf6071c32017-04-20 10:43:22 +0000551 if (D->isThisDeclarationADefinition()) {
552 llvm::PointerUnion<ClassTemplateDecl *,
553 ClassTemplatePartialSpecializationDecl *>
554 Template = D->getSpecializedTemplateOrPartial();
555 const Decl *SpecializationOf =
556 Template.is<ClassTemplateDecl *>()
557 ? (Decl *)Template.get<ClassTemplateDecl *>()
558 : Template.get<ClassTemplatePartialSpecializationDecl *>();
559 IndexCtx.indexTagDecl(
560 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
561 SpecializationOf));
562 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000563 return true;
564 }
565
566 bool VisitTemplateDecl(const TemplateDecl *D) {
567 // FIXME: Template parameters.
568 return Visit(D->getTemplatedDecl());
569 }
570
571 bool VisitFriendDecl(const FriendDecl *D) {
572 if (auto ND = D->getFriendDecl()) {
573 // FIXME: Ignore a class template in a dependent context, these are not
574 // linked properly with their redeclarations, ending up with duplicate
575 // USRs.
576 // See comment "Friend templates are visible in fairly strange ways." in
577 // SemaTemplate.cpp which precedes code that prevents the friend template
578 // from becoming visible from the enclosing context.
579 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
580 return true;
581 return Visit(ND);
582 }
583 if (auto Ty = D->getFriendType()) {
584 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
585 }
586 return true;
587 }
588
589 bool VisitImportDecl(const ImportDecl *D) {
590 return IndexCtx.importedModule(D);
591 }
592};
593
594} // anonymous namespace
595
596bool IndexingContext::indexDecl(const Decl *D) {
597 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
598 return true;
599
600 if (isTemplateImplicitInstantiation(D))
601 return true;
602
603 IndexingDeclVisitor Visitor(*this);
604 bool ShouldContinue = Visitor.Visit(D);
605 if (!ShouldContinue)
606 return false;
607
608 if (!Visitor.Handled && isa<DeclContext>(D))
609 return indexDeclContext(cast<DeclContext>(D));
610
611 return true;
612}
613
614bool IndexingContext::indexDeclContext(const DeclContext *DC) {
615 for (const auto *I : DC->decls())
616 if (!indexDecl(I))
617 return false;
618 return true;
619}
620
621bool IndexingContext::indexTopLevelDecl(const Decl *D) {
622 if (D->getLocation().isInvalid())
623 return true;
624
625 if (isa<ObjCMethodDecl>(D))
626 return true; // Wait for the objc container.
627
628 return indexDecl(D);
629}
630
631bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
632 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
633 if (!indexTopLevelDecl(*I))
634 return false;
635 return true;
636}