blob: 2162c039c48b86f5873b5bf58386846e3067aebe [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;
Alex Lorenz80cb5492017-05-22 16:50:54 +000066 case TemplateArgument::Template:
67 case TemplateArgument::TemplateExpansion:
68 IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
69 Parent, DC);
70 if (const TemplateDecl *TD = TALoc.getArgument()
71 .getAsTemplateOrTemplatePattern()
72 .getAsTemplateDecl()) {
73 if (const NamedDecl *TTD = TD->getTemplatedDecl())
74 IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
75 }
76 break;
Alex Lorenzd43f75b2017-05-12 16:32:26 +000077 default:
78 break;
79 }
80 }
81
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000082 void handleDeclarator(const DeclaratorDecl *D,
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000083 const NamedDecl *Parent = nullptr,
84 bool isIBType = false) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000085 if (!Parent) Parent = D;
86
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +000087 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
88 Parent->getLexicalDeclContext(),
89 /*isBase=*/false, isIBType);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000090 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
91 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
92 // Only index parameters in definitions, parameters in declarations are
93 // not useful.
94 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
95 auto *DC = Parm->getDeclContext();
96 if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
97 if (FD->isThisDeclarationADefinition())
98 IndexCtx.handleDecl(Parm);
99 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
100 if (MD->isThisDeclarationADefinition())
101 IndexCtx.handleDecl(Parm);
102 } else {
103 IndexCtx.handleDecl(Parm);
104 }
105 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
106 if (FD->isThisDeclarationADefinition()) {
David Majnemer59f77922016-06-24 04:05:48 +0000107 for (auto PI : FD->parameters()) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000108 IndexCtx.handleDecl(PI);
109 }
110 }
111 }
Alex Lorenz365cb472017-05-22 15:17:44 +0000112 } else {
113 // Index the default parameter value for function definitions.
114 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
115 if (FD->isThisDeclarationADefinition()) {
116 for (const auto *PV : FD->parameters()) {
117 if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() &&
118 !PV->hasUnparsedDefaultArg())
119 IndexCtx.indexBody(PV->getDefaultArg(), D);
120 }
121 }
122 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000123 }
124 }
125
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000126 bool handleObjCMethod(const ObjCMethodDecl *D,
127 const ObjCPropertyDecl *AssociatedProp = nullptr) {
128 SmallVector<SymbolRelation, 4> Relations;
129 SmallVector<const ObjCMethodDecl*, 4> Overriden;
130
131 D->getOverriddenMethods(Overriden);
132 for(auto overridden: Overriden) {
133 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
134 overridden);
135 }
136 if (AssociatedProp)
137 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
138 AssociatedProp);
139
Argyrios Kyrtzidisaee15fb2017-01-26 02:11:50 +0000140 // getLocation() returns beginning token of a method declaration, but for
141 // indexing purposes we want to point to the base name.
142 SourceLocation MethodLoc = D->getSelectorStartLoc();
143 if (MethodLoc.isInvalid())
144 MethodLoc = D->getLocation();
145
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000146 SourceLocation AttrLoc;
147
148 // check for (getter=/setter=)
149 if (AssociatedProp) {
150 bool isGetter = !D->param_size();
151 AttrLoc = isGetter ?
152 AssociatedProp->getGetterNameLoc():
153 AssociatedProp->getSetterNameLoc();
154 }
155
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000156 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000157 if (D->isImplicit()) {
158 if (AttrLoc.isValid()) {
159 MethodLoc = AttrLoc;
160 } else {
161 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
162 }
163 } else if (AttrLoc.isValid()) {
164 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
165 D->getDeclContext(), 0);
166 }
167
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000168 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000169 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000170 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
171 for (const auto *I : D->parameters()) {
172 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
173 hasIBActionAndFirst = false;
174 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000175
176 if (D->isThisDeclarationADefinition()) {
177 const Stmt *Body = D->getBody();
178 if (Body) {
179 IndexCtx.indexBody(Body, D, D);
180 }
181 }
182 return true;
183 }
184
Alex Lorenza352ba02017-04-24 14:04:58 +0000185 /// Gather the declarations which the given declaration \D overrides in a
186 /// pseudo-override manner.
187 ///
188 /// Pseudo-overrides occur when a class template specialization declares
189 /// a declaration that has the same name as a similar declaration in the
190 /// non-specialized template.
191 void
192 gatherTemplatePseudoOverrides(const NamedDecl *D,
193 SmallVectorImpl<SymbolRelation> &Relations) {
194 if (!IndexCtx.getLangOpts().CPlusPlus)
195 return;
196 const auto *CTSD =
197 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
198 if (!CTSD)
199 return;
200 llvm::PointerUnion<ClassTemplateDecl *,
201 ClassTemplatePartialSpecializationDecl *>
202 Template = CTSD->getSpecializedTemplateOrPartial();
203 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
204 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
205 bool TypeOverride = isa<TypeDecl>(D);
206 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
207 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
208 ND = CTD->getTemplatedDecl();
209 if (ND->isImplicit())
210 continue;
211 // Types can override other types.
212 if (!TypeOverride) {
213 if (ND->getKind() != D->getKind())
214 continue;
215 } else if (!isa<TypeDecl>(ND))
216 continue;
217 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
218 const auto *DFD = cast<FunctionDecl>(D);
219 // Function overrides are approximated using the number of parameters.
220 if (FD->getStorageClass() != DFD->getStorageClass() ||
221 FD->getNumParams() != DFD->getNumParams())
222 continue;
223 }
224 Relations.emplace_back(
Alex Lorenz9e2fea12017-05-04 10:42:06 +0000225 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
Alex Lorenza352ba02017-04-24 14:04:58 +0000226 }
227 }
228 }
229
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000230 bool VisitFunctionDecl(const FunctionDecl *D) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000231 SymbolRoleSet Roles{};
232 SmallVector<SymbolRelation, 4> Relations;
233 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
234 if (CXXMD->isVirtual())
235 Roles |= (unsigned)SymbolRole::Dynamic;
236 for (auto I = CXXMD->begin_overridden_methods(),
237 E = CXXMD->end_overridden_methods(); I != E; ++I) {
238 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
239 }
240 }
Alex Lorenza352ba02017-04-24 14:04:58 +0000241 gatherTemplatePseudoOverrides(D, Relations);
Alex Lorenz5bf767c2017-04-25 14:22:29 +0000242 if (const auto *Base = D->getPrimaryTemplate())
243 Relations.push_back(
244 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
245 Base->getTemplatedDecl()));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000246
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000247 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000248 handleDeclarator(D);
249
250 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000251 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
252 Ctor->getParent(), Ctor->getDeclContext());
253
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000254 // Constructor initializers.
255 for (const auto *Init : Ctor->inits()) {
256 if (Init->isWritten()) {
257 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
258 if (const FieldDecl *Member = Init->getAnyMember())
259 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
260 (unsigned)SymbolRole::Write);
261 IndexCtx.indexBody(Init->getInit(), D, D);
262 }
263 }
Argyrios Kyrtzidis573624a2017-03-17 23:41:59 +0000264 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
265 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
266 IndexCtx.handleReference(Dtor->getParent(),
267 TypeNameInfo->getTypeLoc().getLocStart(),
268 Dtor->getParent(), Dtor->getDeclContext());
269 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000270 }
Alex Lorenzd43f75b2017-05-12 16:32:26 +0000271 // Template specialization arguments.
272 if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
273 D->getTemplateSpecializationArgsAsWritten()) {
274 for (const auto &Arg : TemplateArgInfo->arguments())
275 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
276 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000277
278 if (D->isThisDeclarationADefinition()) {
279 const Stmt *Body = D->getBody();
280 if (Body) {
281 IndexCtx.indexBody(Body, D, D);
282 }
283 }
284 return true;
285 }
286
287 bool VisitVarDecl(const VarDecl *D) {
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 Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000291 handleDeclarator(D);
292 IndexCtx.indexBody(D->getInit(), D);
293 return true;
294 }
295
Alex Lorenz8a656c92017-06-15 21:19:01 +0000296 bool VisitDecompositionDecl(const DecompositionDecl *D) {
297 for (const auto *Binding : D->bindings())
298 TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
299 return Base::VisitDecompositionDecl(D);
300 }
301
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000302 bool VisitFieldDecl(const FieldDecl *D) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000303 SmallVector<SymbolRelation, 4> Relations;
304 gatherTemplatePseudoOverrides(D, Relations);
305 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000306 handleDeclarator(D);
307 if (D->isBitField())
308 IndexCtx.indexBody(D->getBitWidth(), D);
309 else if (D->hasInClassInitializer())
310 IndexCtx.indexBody(D->getInClassInitializer(), D);
311 return true;
312 }
313
314 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
315 if (D->getSynthesize()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000316 // handled in VisitObjCPropertyImplDecl
317 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000318 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000319 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000320 handleDeclarator(D);
321 return true;
322 }
323
324 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
325 handleDeclarator(D);
326 return true;
327 }
328
329 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000330 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000331 IndexCtx.indexBody(D->getInitExpr(), D);
332 return true;
333 }
334
335 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000336 if (!D->isTransparentTag()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000337 SmallVector<SymbolRelation, 4> Relations;
338 gatherTemplatePseudoOverrides(D, Relations);
339 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
Argyrios Kyrtzidisf9326122017-04-21 05:42:40 +0000340 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
341 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000342 return true;
343 }
344
345 bool VisitTagDecl(const TagDecl *D) {
346 // Non-free standing tags are handled in indexTypeSourceInfo.
347 if (D->isFreeStanding()) {
348 if (D->isThisDeclarationADefinition()) {
Alex Lorenza352ba02017-04-24 14:04:58 +0000349 SmallVector<SymbolRelation, 4> Relations;
350 gatherTemplatePseudoOverrides(D, Relations);
351 IndexCtx.indexTagDecl(D, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000352 } else {
353 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
354 return IndexCtx.handleReference(D, D->getLocation(), Parent,
355 D->getLexicalDeclContext(),
356 SymbolRoleSet());
357 }
358 }
359 return true;
360 }
361
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000362 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000363 const ObjCContainerDecl *ContD,
364 SourceLocation SuperLoc) {
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000365 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
366 for (ObjCInterfaceDecl::protocol_iterator
367 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
368 SourceLocation Loc = *LI;
369 ObjCProtocolDecl *PD = *I;
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000370 SymbolRoleSet roles{};
371 if (Loc == SuperLoc)
372 roles |= (SymbolRoleSet)SymbolRole::Implicit;
373 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000374 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
375 }
376 return true;
377 }
378
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000379 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
380 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000381 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000382 SourceLocation SuperLoc = D->getSuperClassLoc();
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000383 if (auto *SuperD = D->getSuperClass()) {
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000384 bool hasSuperTypedef = false;
385 if (auto *TInfo = D->getSuperClassTInfo()) {
386 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
387 if (auto *TD = TT->getDecl()) {
388 hasSuperTypedef = true;
389 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
390 SymbolRoleSet()));
391 }
392 }
393 }
394 SymbolRoleSet superRoles{};
395 if (hasSuperTypedef)
396 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
397 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000398 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
399 }
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000400 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
401 SuperLoc));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000402 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000403 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000404 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
405 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000406 }
407 return true;
408 }
409
410 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
411 if (D->isThisDeclarationADefinition()) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000412 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000413 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
414 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis34a0c1a2016-03-03 05:33:54 +0000415 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000416 } else {
Argyrios Kyrtzidis542f38f2016-03-09 02:12:46 +0000417 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
418 D->getDeclContext(), SymbolRoleSet());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000419 }
420 return true;
421 }
422
423 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
424 const ObjCInterfaceDecl *Class = D->getClassInterface();
425 if (!Class)
426 return true;
427
428 if (Class->isImplicitInterfaceDecl())
429 IndexCtx.handleDecl(Class);
430
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000431 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000432
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000433 // Visit implicit @synthesize property implementations first as their
434 // location is reported at the name of the @implementation block. This
435 // serves no purpose other than to simplify the FileCheck-based tests.
436 for (const auto *I : D->property_impls()) {
437 if (I->getLocation().isInvalid())
438 IndexCtx.indexDecl(I);
439 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000440 for (const auto *I : D->decls()) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000441 if (!isa<ObjCPropertyImplDecl>(I) ||
442 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000443 IndexCtx.indexDecl(I);
444 }
445
446 return true;
447 }
448
449 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000450 if (!IndexCtx.shouldIndex(D))
451 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000452 const ObjCInterfaceDecl *C = D->getClassInterface();
Argyrios Kyrtzidis38004312017-01-11 21:08:31 +0000453 if (!C)
454 return true;
455 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
456 SymbolRelation{
457 (unsigned)SymbolRole::RelationExtendedBy, D
458 }));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000459 SourceLocation CategoryLoc = D->getCategoryNameLoc();
460 if (!CategoryLoc.isValid())
461 CategoryLoc = D->getLocation();
462 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidis266cfa32017-03-04 17:54:53 +0000463 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
464 /*superLoc=*/SourceLocation()));
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000465 TRY_TO(IndexCtx.indexDeclContext(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000466 return true;
467 }
468
469 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
470 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
471 if (!Cat)
472 return true;
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000473 const ObjCInterfaceDecl *C = D->getClassInterface();
474 if (C)
475 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
476 SymbolRoleSet()));
477 SourceLocation CategoryLoc = D->getCategoryNameLoc();
478 if (!CategoryLoc.isValid())
479 CategoryLoc = D->getLocation();
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000480 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000481 IndexCtx.indexDeclContext(D);
482 return true;
483 }
484
485 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
486 // Methods associated with a property, even user-declared ones, are
487 // handled when we handle the property.
488 if (D->isPropertyAccessor())
489 return true;
490
491 handleObjCMethod(D);
492 return true;
493 }
494
495 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
496 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
497 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000498 handleObjCMethod(MD, D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000499 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
500 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
Argyrios Kyrtzidis806faaf2016-10-25 21:11:22 +0000501 handleObjCMethod(MD, D);
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000502 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000503 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
504 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
505 D->getLexicalDeclContext(), false, true);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000506 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
507 return true;
508 }
509
510 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
511 ObjCPropertyDecl *PD = D->getPropertyDecl();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000512 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
513 SourceLocation Loc = D->getLocation();
514 SymbolRoleSet Roles = 0;
515 SmallVector<SymbolRelation, 1> Relations;
516
517 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
518 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
519 if (Loc.isInvalid()) {
520 Loc = Container->getLocation();
521 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
522 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000523 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000524
525 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
526 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000527
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000528 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000529 SymbolRoleSet AccessorMethodRoles =
530 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000531 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
532 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000533 !hasUserDefined(MD, Container))
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000534 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000535 }
536 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
537 if (MD->isPropertyAccessor() &&
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000538 !hasUserDefined(MD, Container))
Argyrios Kyrtzidise5947072017-04-27 15:05:18 +0000539 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000540 }
541 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
542 if (IvarD->getSynthesize()) {
543 // For synthesized ivars, use the location of its name in the
544 // corresponding @synthesize. If there isn't one, use the containing
545 // @implementation's location, rather than the property's location,
546 // otherwise the header file containing the @interface will have different
547 // indexing contents based on whether the @implementation was present or
548 // not in the translation unit.
549 SymbolRoleSet IvarRoles = 0;
550 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
551 if (D->getLocation().isInvalid()) {
552 IvarLoc = Container->getLocation();
553 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
554 } else if (D->getLocation() == IvarLoc) {
555 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
556 }
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000557 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000558 } else {
559 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
560 D->getDeclContext(), SymbolRoleSet());
561 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000562 }
563 return true;
564 }
565
566 bool VisitNamespaceDecl(const NamespaceDecl *D) {
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +0000567 TRY_DECL(D, IndexCtx.handleDecl(D));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000568 IndexCtx.indexDeclContext(D);
569 return true;
570 }
571
Alex Lorenz4ab51932017-05-15 10:56:31 +0000572 bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
573 TRY_DECL(D, IndexCtx.handleDecl(D));
574 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
575 IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
576 D->getLexicalDeclContext());
577 return true;
578 }
579
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000580 bool VisitUsingDecl(const UsingDecl *D) {
581 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
582 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
583
584 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
585 D->getLexicalDeclContext());
586 for (const auto *I : D->shadows())
587 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
588 D->getLexicalDeclContext(), SymbolRoleSet());
589 return true;
590 }
591
592 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
593 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
594 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
595
Alex Lorenzd65b3e42017-05-22 14:39:39 +0000596 // NNS for the local 'using namespace' directives is visited by the body
597 // visitor.
598 if (!D->getParentFunctionOrMethod())
599 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
600 D->getLexicalDeclContext());
601
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000602 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
603 D->getLocation(), Parent,
604 D->getLexicalDeclContext(),
605 SymbolRoleSet());
606 }
607
608 bool VisitClassTemplateSpecializationDecl(const
609 ClassTemplateSpecializationDecl *D) {
610 // FIXME: Notify subsequent callbacks if info comes from implicit
611 // instantiation.
Alex Lorenzf6071c32017-04-20 10:43:22 +0000612 if (D->isThisDeclarationADefinition()) {
613 llvm::PointerUnion<ClassTemplateDecl *,
614 ClassTemplatePartialSpecializationDecl *>
615 Template = D->getSpecializedTemplateOrPartial();
616 const Decl *SpecializationOf =
617 Template.is<ClassTemplateDecl *>()
618 ? (Decl *)Template.get<ClassTemplateDecl *>()
619 : Template.get<ClassTemplatePartialSpecializationDecl *>();
620 IndexCtx.indexTagDecl(
621 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
622 SpecializationOf));
623 }
Alex Lorenzf41b21e2017-04-25 15:13:42 +0000624 if (TypeSourceInfo *TSI = D->getTypeAsWritten())
625 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
626 D->getLexicalDeclContext());
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000627 return true;
628 }
629
Alex Lorenz80cb5492017-05-22 16:50:54 +0000630 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
631 if (!D)
632 return false;
633 // We want to index the template parameters only once when indexing the
634 // canonical declaration.
635 if (const auto *FD = dyn_cast<FunctionDecl>(D))
636 return FD->getCanonicalDecl() == FD;
637 else if (const auto *TD = dyn_cast<TagDecl>(D))
638 return TD->getCanonicalDecl() == TD;
639 else if (const auto *VD = dyn_cast<VarDecl>(D))
640 return VD->getCanonicalDecl() == VD;
641 return true;
642 }
643
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000644 bool VisitTemplateDecl(const TemplateDecl *D) {
645 // FIXME: Template parameters.
Alex Lorenz80cb5492017-05-22 16:50:54 +0000646
647 // Index the default values for the template parameters.
648 const NamedDecl *Parent = D->getTemplatedDecl();
649 if (D->getTemplateParameters() &&
650 shouldIndexTemplateParameterDefaultValue(Parent)) {
651 const TemplateParameterList *Params = D->getTemplateParameters();
652 for (const NamedDecl *TP : *Params) {
653 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
654 if (TTP->hasDefaultArgument())
655 IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
656 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
657 if (NTTP->hasDefaultArgument())
658 IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
659 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
660 if (TTPD->hasDefaultArgument())
661 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
662 /*DC=*/nullptr);
663 }
664 }
665 }
666
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000667 return Visit(D->getTemplatedDecl());
668 }
669
670 bool VisitFriendDecl(const FriendDecl *D) {
671 if (auto ND = D->getFriendDecl()) {
672 // FIXME: Ignore a class template in a dependent context, these are not
673 // linked properly with their redeclarations, ending up with duplicate
674 // USRs.
675 // See comment "Friend templates are visible in fairly strange ways." in
676 // SemaTemplate.cpp which precedes code that prevents the friend template
677 // from becoming visible from the enclosing context.
678 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
679 return true;
680 return Visit(ND);
681 }
682 if (auto Ty = D->getFriendType()) {
683 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
684 }
685 return true;
686 }
687
688 bool VisitImportDecl(const ImportDecl *D) {
689 return IndexCtx.importedModule(D);
690 }
Alex Lorenz60aac432017-06-15 20:50:43 +0000691
692 bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
693 IndexCtx.indexBody(D->getAssertExpr(),
694 dyn_cast<NamedDecl>(D->getDeclContext()),
695 D->getLexicalDeclContext());
696 return true;
697 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000698};
699
700} // anonymous namespace
701
702bool IndexingContext::indexDecl(const Decl *D) {
703 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
704 return true;
705
706 if (isTemplateImplicitInstantiation(D))
707 return true;
708
709 IndexingDeclVisitor Visitor(*this);
710 bool ShouldContinue = Visitor.Visit(D);
711 if (!ShouldContinue)
712 return false;
713
714 if (!Visitor.Handled && isa<DeclContext>(D))
715 return indexDeclContext(cast<DeclContext>(D));
716
717 return true;
718}
719
720bool IndexingContext::indexDeclContext(const DeclContext *DC) {
721 for (const auto *I : DC->decls())
722 if (!indexDecl(I))
723 return false;
724 return true;
725}
726
727bool IndexingContext::indexTopLevelDecl(const Decl *D) {
728 if (D->getLocation().isInvalid())
729 return true;
730
731 if (isa<ObjCMethodDecl>(D))
732 return true; // Wait for the objc container.
733
734 return indexDecl(D);
735}
736
737bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
738 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
739 if (!indexTopLevelDecl(*I))
740 return false;
741 return true;
742}