blob: 7f940ef4c3656e0c2458d91c8cb33cb4d61b04c4 [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
Alex Lorenzd43f75b2017-05-12 16:32:26 +000055 void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
56 const NamedDecl *Parent,
57 const DeclContext *DC) {
58 const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();
59 switch (TALoc.getArgument().getKind()) {
60 case TemplateArgument::Expression:
61 IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
62 break;
63 case TemplateArgument::Type:
64 IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
65 break;
66 default:
67 break;
68 }
69 }
70
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000071 void handleDeclarator(const DeclaratorDecl *D,
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000072 const NamedDecl *Parent = nullptr,
73 bool isIBType = false) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000074 if (!Parent) Parent = D;
75
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000076 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
77 Parent->getLexicalDeclContext(),
78 /*isBase=*/false, isIBType);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000079 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
80 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
81 // Only index parameters in definitions, parameters in declarations are
82 // not useful.
83 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
84 auto *DC = Parm->getDeclContext();
85 if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
86 if (FD->isThisDeclarationADefinition())
87 IndexCtx.handleDecl(Parm);
88 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
89 if (MD->isThisDeclarationADefinition())
90 IndexCtx.handleDecl(Parm);
91 } else {
92 IndexCtx.handleDecl(Parm);
93 }
94 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
95 if (FD->isThisDeclarationADefinition()) {
David Majnemer59f77922016-06-24 04:05:48 +000096 for (auto PI : FD->parameters()) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000097 IndexCtx.handleDecl(PI);
98 }
99 }
100 }
Alex Lorenz365cb472017-05-22 15:17:44 +0000101 } else {
102 // Index the default parameter value for function definitions.
103 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
104 if (FD->isThisDeclarationADefinition()) {
105 for (const auto *PV : FD->parameters()) {
106 if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() &&
107 !PV->hasUnparsedDefaultArg())
108 IndexCtx.indexBody(PV->getDefaultArg(), D);
109 }
110 }
111 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000112 }
113 }
114
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000115 bool handleObjCMethod(const ObjCMethodDecl *D,
116 const ObjCPropertyDecl *AssociatedProp = nullptr) {
117 SmallVector<SymbolRelation, 4> Relations;
118 SmallVector<const ObjCMethodDecl*, 4> Overriden;
119
120 D->getOverriddenMethods(Overriden);
121 for(auto overridden: Overriden) {
122 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
123 overridden);
124 }
125 if (AssociatedProp)
126 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
127 AssociatedProp);
128
Argyrios Kyrtzidisaee15fb2017-01-26 02:11:50 +0000129 // getLocation() returns beginning token of a method declaration, but for
130 // indexing purposes we want to point to the base name.
131 SourceLocation MethodLoc = D->getSelectorStartLoc();
132 if (MethodLoc.isInvalid())
133 MethodLoc = D->getLocation();
134
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000135 SourceLocation AttrLoc;
136
137 // check for (getter=/setter=)
138 if (AssociatedProp) {
139 bool isGetter = !D->param_size();
140 AttrLoc = isGetter ?
141 AssociatedProp->getGetterNameLoc():
142 AssociatedProp->getSetterNameLoc();
143 }
144
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000145 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000146 if (D->isImplicit()) {
147 if (AttrLoc.isValid()) {
148 MethodLoc = AttrLoc;
149 } else {
150 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
151 }
152 } else if (AttrLoc.isValid()) {
153 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
154 D->getDeclContext(), 0);
155 }
156
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000157 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000158 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000159 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
160 for (const auto *I : D->parameters()) {
161 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
162 hasIBActionAndFirst = false;
163 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000164
165 if (D->isThisDeclarationADefinition()) {
166 const Stmt *Body = D->getBody();
167 if (Body) {
168 IndexCtx.indexBody(Body, D, D);
169 }
170 }
171 return true;
172 }
173
Alex Lorenza352ba02017-04-24 14:04:58 +0000174 /// Gather the declarations which the given declaration \D overrides in a
175 /// pseudo-override manner.
176 ///
177 /// Pseudo-overrides occur when a class template specialization declares
178 /// a declaration that has the same name as a similar declaration in the
179 /// non-specialized template.
180 void
181 gatherTemplatePseudoOverrides(const NamedDecl *D,
182 SmallVectorImpl<SymbolRelation> &Relations) {
183 if (!IndexCtx.getLangOpts().CPlusPlus)
184 return;
185 const auto *CTSD =
186 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
187 if (!CTSD)
188 return;
189 llvm::PointerUnion<ClassTemplateDecl *,
190 ClassTemplatePartialSpecializationDecl *>
191 Template = CTSD->getSpecializedTemplateOrPartial();
192 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
193 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
194 bool TypeOverride = isa<TypeDecl>(D);
195 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
196 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
197 ND = CTD->getTemplatedDecl();
198 if (ND->isImplicit())
199 continue;
200 // Types can override other types.
201 if (!TypeOverride) {
202 if (ND->getKind() != D->getKind())
203 continue;
204 } else if (!isa<TypeDecl>(ND))
205 continue;
206 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
207 const auto *DFD = cast<FunctionDecl>(D);
208 // Function overrides are approximated using the number of parameters.
209 if (FD->getStorageClass() != DFD->getStorageClass() ||
210 FD->getNumParams() != DFD->getNumParams())
211 continue;
212 }
213 Relations.emplace_back(
Alex Lorenz9e2fea12017-05-04 10:42:06 +0000214 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
Alex Lorenza352ba02017-04-24 14:04:58 +0000215 }
216 }
217 }
218
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000219 bool VisitFunctionDecl(const FunctionDecl *D) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000220 SymbolRoleSet Roles{};
221 SmallVector<SymbolRelation, 4> Relations;
222 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
223 if (CXXMD->isVirtual())
224 Roles |= (unsigned)SymbolRole::Dynamic;
225 for (auto I = CXXMD->begin_overridden_methods(),
226 E = CXXMD->end_overridden_methods(); I != E; ++I) {
227 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
228 }
229 }
Alex Lorenza352ba02017-04-24 14:04:58 +0000230 gatherTemplatePseudoOverrides(D, Relations);
Alex Lorenz5bf767c2017-04-25 14:22:29 +0000231 if (const auto *Base = D->getPrimaryTemplate())
232 Relations.push_back(
233 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
234 Base->getTemplatedDecl()));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000235
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000236 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000237 handleDeclarator(D);
238
239 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000240 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
241 Ctor->getParent(), Ctor->getDeclContext());
242
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000243 // Constructor initializers.
244 for (const auto *Init : Ctor->inits()) {
245 if (Init->isWritten()) {
246 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
247 if (const FieldDecl *Member = Init->getAnyMember())
248 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
249 (unsigned)SymbolRole::Write);
250 IndexCtx.indexBody(Init->getInit(), D, D);
251 }
252 }
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000253 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
254 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
255 IndexCtx.handleReference(Dtor->getParent(),
256 TypeNameInfo->getTypeLoc().getLocStart(),
257 Dtor->getParent(), Dtor->getDeclContext());
258 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000259 }
Alex Lorenzd43f75b2017-05-12 16:32:26 +0000260 // Template specialization arguments.
261 if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
262 D->getTemplateSpecializationArgsAsWritten()) {
263 for (const auto &Arg : TemplateArgInfo->arguments())
264 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
265 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000266
267 if (D->isThisDeclarationADefinition()) {
268 const Stmt *Body = D->getBody();
269 if (Body) {
270 IndexCtx.indexBody(Body, D, D);
271 }
272 }
273 return true;
274 }
275
276 bool VisitVarDecl(const VarDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000277 SmallVector<SymbolRelation, 4> Relations;
278 gatherTemplatePseudoOverrides(D, Relations);
279 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000280 handleDeclarator(D);
281 IndexCtx.indexBody(D->getInit(), D);
282 return true;
283 }
284
285 bool VisitFieldDecl(const FieldDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000286 SmallVector<SymbolRelation, 4> Relations;
287 gatherTemplatePseudoOverrides(D, Relations);
288 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000289 handleDeclarator(D);
290 if (D->isBitField())
291 IndexCtx.indexBody(D->getBitWidth(), D);
292 else if (D->hasInClassInitializer())
293 IndexCtx.indexBody(D->getInClassInitializer(), D);
294 return true;
295 }
296
297 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
298 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000299 // handled in VisitObjCPropertyImplDecl
300 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000301 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000302 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000303 handleDeclarator(D);
304 return true;
305 }
306
307 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
308 handleDeclarator(D);
309 return true;
310 }
311
312 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000313 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000314 IndexCtx.indexBody(D->getInitExpr(), D);
315 return true;
316 }
317
318 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000319 if (!D->isTransparentTag()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000320 SmallVector<SymbolRelation, 4> Relations;
321 gatherTemplatePseudoOverrides(D, Relations);
322 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000323 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
324 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000325 return true;
326 }
327
328 bool VisitTagDecl(const TagDecl *D) {
329 // Non-free standing tags are handled in indexTypeSourceInfo.
330 if (D->isFreeStanding()) {
331 if (D->isThisDeclarationADefinition()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000332 SmallVector<SymbolRelation, 4> Relations;
333 gatherTemplatePseudoOverrides(D, Relations);
334 IndexCtx.indexTagDecl(D, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000335 } else {
336 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
337 return IndexCtx.handleReference(D, D->getLocation(), Parent,
338 D->getLexicalDeclContext(),
339 SymbolRoleSet());
340 }
341 }
342 return true;
343 }
344
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000345 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000346 const ObjCContainerDecl *ContD,
347 SourceLocation SuperLoc) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000348 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
349 for (ObjCInterfaceDecl::protocol_iterator
350 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
351 SourceLocation Loc = *LI;
352 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000353 SymbolRoleSet roles{};
354 if (Loc == SuperLoc)
355 roles |= (SymbolRoleSet)SymbolRole::Implicit;
356 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000357 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
358 }
359 return true;
360 }
361
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000362 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
363 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000364 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000365 SourceLocation SuperLoc = D->getSuperClassLoc();
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000366 if (auto *SuperD = D->getSuperClass()) {
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000367 bool hasSuperTypedef = false;
368 if (auto *TInfo = D->getSuperClassTInfo()) {
369 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
370 if (auto *TD = TT->getDecl()) {
371 hasSuperTypedef = true;
372 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
373 SymbolRoleSet()));
374 }
375 }
376 }
377 SymbolRoleSet superRoles{};
378 if (hasSuperTypedef)
379 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
380 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000381 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
382 }
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000383 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
384 SuperLoc));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000385 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000386 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000387 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
388 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000389 }
390 return true;
391 }
392
393 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
394 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000395 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000396 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
397 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000398 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000399 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000400 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
401 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000402 }
403 return true;
404 }
405
406 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
407 const ObjCInterfaceDecl *Class = D->getClassInterface();
408 if (!Class)
409 return true;
410
411 if (Class->isImplicitInterfaceDecl())
412 IndexCtx.handleDecl(Class);
413
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000414 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000415
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000416 // Visit implicit @synthesize property implementations first as their
417 // location is reported at the name of the @implementation block. This
418 // serves no purpose other than to simplify the FileCheck-based tests.
419 for (const auto *I : D->property_impls()) {
420 if (I->getLocation().isInvalid())
421 IndexCtx.indexDecl(I);
422 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000423 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000424 if (!isa<ObjCPropertyImplDecl>(I) ||
425 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000426 IndexCtx.indexDecl(I);
427 }
428
429 return true;
430 }
431
432 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000433 if (!IndexCtx.shouldIndex(D))
434 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000435 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000436 if (!C)
437 return true;
438 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
439 SymbolRelation{
440 (unsigned)SymbolRole::RelationExtendedBy, D
441 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000442 SourceLocation CategoryLoc = D->getCategoryNameLoc();
443 if (!CategoryLoc.isValid())
444 CategoryLoc = D->getLocation();
445 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000446 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
447 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000448 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000449 return true;
450 }
451
452 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
453 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
454 if (!Cat)
455 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000456 const ObjCInterfaceDecl *C = D->getClassInterface();
457 if (C)
458 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
459 SymbolRoleSet()));
460 SourceLocation CategoryLoc = D->getCategoryNameLoc();
461 if (!CategoryLoc.isValid())
462 CategoryLoc = D->getLocation();
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000463 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000464 IndexCtx.indexDeclContext(D);
465 return true;
466 }
467
468 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
469 // Methods associated with a property, even user-declared ones, are
470 // handled when we handle the property.
471 if (D->isPropertyAccessor())
472 return true;
473
474 handleObjCMethod(D);
475 return true;
476 }
477
478 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
479 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
480 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000481 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000482 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
483 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000484 handleObjCMethod(MD, D);
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000485 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000486 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
487 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
488 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000489 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
490 return true;
491 }
492
493 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
494 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000495 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
496 SourceLocation Loc = D->getLocation();
497 SymbolRoleSet Roles = 0;
498 SmallVector<SymbolRelation, 1> Relations;
499
500 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
501 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
502 if (Loc.isInvalid()) {
503 Loc = Container->getLocation();
504 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
505 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000506 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000507
508 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
509 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000510
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000511 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000512 SymbolRoleSet AccessorMethodRoles =
513 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000514 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
515 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000516 !hasUserDefined(MD, Container))
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000517 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000518 }
519 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
520 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000521 !hasUserDefined(MD, Container))
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000522 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000523 }
524 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
525 if (IvarD->getSynthesize()) {
526 // For synthesized ivars, use the location of its name in the
527 // corresponding @synthesize. If there isn't one, use the containing
528 // @implementation's location, rather than the property's location,
529 // otherwise the header file containing the @interface will have different
530 // indexing contents based on whether the @implementation was present or
531 // not in the translation unit.
532 SymbolRoleSet IvarRoles = 0;
533 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
534 if (D->getLocation().isInvalid()) {
535 IvarLoc = Container->getLocation();
536 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
537 } else if (D->getLocation() == IvarLoc) {
538 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
539 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000540 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000541 } else {
542 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
543 D->getDeclContext(), SymbolRoleSet());
544 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000545 }
546 return true;
547 }
548
549 bool VisitNamespaceDecl(const NamespaceDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000550 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000551 IndexCtx.indexDeclContext(D);
552 return true;
553 }
554
Alex Lorenz4ab51932017-05-15 10:56:31 +0000555 bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
556 TRY_DECL(D, IndexCtx.handleDecl(D));
557 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
558 IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
559 D->getLexicalDeclContext());
560 return true;
561 }
562
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000563 bool VisitUsingDecl(const UsingDecl *D) {
564 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
565 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
566
567 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
568 D->getLexicalDeclContext());
569 for (const auto *I : D->shadows())
570 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
571 D->getLexicalDeclContext(), SymbolRoleSet());
572 return true;
573 }
574
575 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
576 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
577 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
578
Alex Lorenzd65b3e42017-05-22 14:39:39 +0000579 // NNS for the local 'using namespace' directives is visited by the body
580 // visitor.
581 if (!D->getParentFunctionOrMethod())
582 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
583 D->getLexicalDeclContext());
584
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000585 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
586 D->getLocation(), Parent,
587 D->getLexicalDeclContext(),
588 SymbolRoleSet());
589 }
590
591 bool VisitClassTemplateSpecializationDecl(const
592 ClassTemplateSpecializationDecl *D) {
593 // FIXME: Notify subsequent callbacks if info comes from implicit
594 // instantiation.
Alex Lorenzf6071c32017-04-20 10:43:22 +0000595 if (D->isThisDeclarationADefinition()) {
596 llvm::PointerUnion<ClassTemplateDecl *,
597 ClassTemplatePartialSpecializationDecl *>
598 Template = D->getSpecializedTemplateOrPartial();
599 const Decl *SpecializationOf =
600 Template.is<ClassTemplateDecl *>()
601 ? (Decl *)Template.get<ClassTemplateDecl *>()
602 : Template.get<ClassTemplatePartialSpecializationDecl *>();
603 IndexCtx.indexTagDecl(
604 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
605 SpecializationOf));
606 }
Alex Lorenzf41b21e2017-04-25 15:13:42 +0000607 if (TypeSourceInfo *TSI = D->getTypeAsWritten())
608 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
609 D->getLexicalDeclContext());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000610 return true;
611 }
612
613 bool VisitTemplateDecl(const TemplateDecl *D) {
614 // FIXME: Template parameters.
615 return Visit(D->getTemplatedDecl());
616 }
617
618 bool VisitFriendDecl(const FriendDecl *D) {
619 if (auto ND = D->getFriendDecl()) {
620 // FIXME: Ignore a class template in a dependent context, these are not
621 // linked properly with their redeclarations, ending up with duplicate
622 // USRs.
623 // See comment "Friend templates are visible in fairly strange ways." in
624 // SemaTemplate.cpp which precedes code that prevents the friend template
625 // from becoming visible from the enclosing context.
626 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
627 return true;
628 return Visit(ND);
629 }
630 if (auto Ty = D->getFriendType()) {
631 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
632 }
633 return true;
634 }
635
636 bool VisitImportDecl(const ImportDecl *D) {
637 return IndexCtx.importedModule(D);
638 }
639};
640
641} // anonymous namespace
642
643bool IndexingContext::indexDecl(const Decl *D) {
644 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
645 return true;
646
647 if (isTemplateImplicitInstantiation(D))
648 return true;
649
650 IndexingDeclVisitor Visitor(*this);
651 bool ShouldContinue = Visitor.Visit(D);
652 if (!ShouldContinue)
653 return false;
654
655 if (!Visitor.Handled && isa<DeclContext>(D))
656 return indexDeclContext(cast<DeclContext>(D));
657
658 return true;
659}
660
661bool IndexingContext::indexDeclContext(const DeclContext *DC) {
662 for (const auto *I : DC->decls())
663 if (!indexDecl(I))
664 return false;
665 return true;
666}
667
668bool IndexingContext::indexTopLevelDecl(const Decl *D) {
669 if (D->getLocation().isInvalid())
670 return true;
671
672 if (isa<ObjCMethodDecl>(D))
673 return true; // Wait for the objc container.
674
675 return indexDecl(D);
676}
677
678bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
679 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
680 if (!indexTopLevelDecl(*I))
681 return false;
682 return true;
683}