1 //===- 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
14 using namespace clang;
15 using namespace index;
16
17 #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
24 #define TRY_TO(CALL_EXPR) \
25 do { \
26 if (!CALL_EXPR) \
27 return false; \
28 } while (0)
29
30 namespace {
31
32 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
33 IndexingContext &IndexCtx;
34
35 public:
IndexingDeclVisitor(IndexingContext & indexCtx)36 explicit IndexingDeclVisitor(IndexingContext &indexCtx)
37 : IndexCtx(indexCtx) { }
38
39 bool Handled = true;
40
VisitDecl(const Decl * D)41 bool VisitDecl(const Decl *D) {
42 Handled = false;
43 return true;
44 }
45
46 /// Returns true if the given method has been defined explicitly by the
47 /// user.
hasUserDefined(const ObjCMethodDecl * D,const ObjCImplDecl * Container)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
handleTemplateArgumentLoc(const TemplateArgumentLoc & TALoc,const NamedDecl * Parent,const DeclContext * DC)55 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 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;
77 default:
78 break;
79 }
80 }
81
handleDeclarator(const DeclaratorDecl * D,const NamedDecl * Parent=nullptr,bool isIBType=false)82 void handleDeclarator(const DeclaratorDecl *D,
83 const NamedDecl *Parent = nullptr,
84 bool isIBType = false) {
85 if (!Parent) Parent = D;
86
87 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
88 Parent->getLexicalDeclContext(),
89 /*isBase=*/false, isIBType);
90 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()) {
107 for (auto PI : FD->parameters()) {
108 IndexCtx.handleDecl(PI);
109 }
110 }
111 }
112 } 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 }
123 }
124 }
125
handleObjCMethod(const ObjCMethodDecl * D,const ObjCPropertyDecl * AssociatedProp=nullptr)126 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
140 // 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
146 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
156 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
157 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
168 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
169 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
170 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
171 for (const auto *I : D->parameters()) {
172 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
173 hasIBActionAndFirst = false;
174 }
175
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
185 /// 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
gatherTemplatePseudoOverrides(const NamedDecl * D,SmallVectorImpl<SymbolRelation> & Relations)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(
225 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
226 }
227 }
228 }
229
VisitFunctionDecl(const FunctionDecl * D)230 bool VisitFunctionDecl(const FunctionDecl *D) {
231 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 (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
237 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
238 }
239 }
240 gatherTemplatePseudoOverrides(D, Relations);
241 if (const auto *Base = D->getPrimaryTemplate())
242 Relations.push_back(
243 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
244 Base->getTemplatedDecl()));
245
246 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
247 handleDeclarator(D);
248
249 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
250 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
251 Ctor->getParent(), Ctor->getDeclContext());
252
253 // Constructor initializers.
254 for (const auto *Init : Ctor->inits()) {
255 if (Init->isWritten()) {
256 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
257 if (const FieldDecl *Member = Init->getAnyMember())
258 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
259 (unsigned)SymbolRole::Write);
260 IndexCtx.indexBody(Init->getInit(), D, D);
261 }
262 }
263 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
264 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
265 IndexCtx.handleReference(Dtor->getParent(),
266 TypeNameInfo->getTypeLoc().getBeginLoc(),
267 Dtor->getParent(), Dtor->getDeclContext());
268 }
269 } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
270 IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
271 Guide->getLocation(), Guide,
272 Guide->getDeclContext());
273 }
274 // Template specialization arguments.
275 if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
276 D->getTemplateSpecializationArgsAsWritten()) {
277 for (const auto &Arg : TemplateArgInfo->arguments())
278 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
279 }
280
281 if (D->isThisDeclarationADefinition()) {
282 const Stmt *Body = D->getBody();
283 if (Body) {
284 IndexCtx.indexBody(Body, D, D);
285 }
286 }
287 return true;
288 }
289
VisitVarDecl(const VarDecl * D)290 bool VisitVarDecl(const VarDecl *D) {
291 SmallVector<SymbolRelation, 4> Relations;
292 gatherTemplatePseudoOverrides(D, Relations);
293 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
294 handleDeclarator(D);
295 IndexCtx.indexBody(D->getInit(), D);
296 return true;
297 }
298
VisitDecompositionDecl(const DecompositionDecl * D)299 bool VisitDecompositionDecl(const DecompositionDecl *D) {
300 for (const auto *Binding : D->bindings())
301 TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
302 return Base::VisitDecompositionDecl(D);
303 }
304
VisitFieldDecl(const FieldDecl * D)305 bool VisitFieldDecl(const FieldDecl *D) {
306 SmallVector<SymbolRelation, 4> Relations;
307 gatherTemplatePseudoOverrides(D, Relations);
308 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
309 handleDeclarator(D);
310 if (D->isBitField())
311 IndexCtx.indexBody(D->getBitWidth(), D);
312 else if (D->hasInClassInitializer())
313 IndexCtx.indexBody(D->getInClassInitializer(), D);
314 return true;
315 }
316
VisitObjCIvarDecl(const ObjCIvarDecl * D)317 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
318 if (D->getSynthesize()) {
319 // handled in VisitObjCPropertyImplDecl
320 return true;
321 }
322 TRY_DECL(D, IndexCtx.handleDecl(D));
323 handleDeclarator(D);
324 return true;
325 }
326
VisitMSPropertyDecl(const MSPropertyDecl * D)327 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
328 handleDeclarator(D);
329 return true;
330 }
331
VisitEnumConstantDecl(const EnumConstantDecl * D)332 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
333 TRY_DECL(D, IndexCtx.handleDecl(D));
334 IndexCtx.indexBody(D->getInitExpr(), D);
335 return true;
336 }
337
VisitTypedefNameDecl(const TypedefNameDecl * D)338 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
339 if (!D->isTransparentTag()) {
340 SmallVector<SymbolRelation, 4> Relations;
341 gatherTemplatePseudoOverrides(D, Relations);
342 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
343 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
344 }
345 return true;
346 }
347
VisitTagDecl(const TagDecl * D)348 bool VisitTagDecl(const TagDecl *D) {
349 // Non-free standing tags are handled in indexTypeSourceInfo.
350 if (D->isFreeStanding()) {
351 if (D->isThisDeclarationADefinition()) {
352 SmallVector<SymbolRelation, 4> Relations;
353 gatherTemplatePseudoOverrides(D, Relations);
354 IndexCtx.indexTagDecl(D, Relations);
355 } else {
356 SmallVector<SymbolRelation, 1> Relations;
357 gatherTemplatePseudoOverrides(D, Relations);
358 return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
359 Relations, D->getLexicalDeclContext());
360 }
361 }
362 return true;
363 }
364
handleReferencedProtocols(const ObjCProtocolList & ProtList,const ObjCContainerDecl * ContD,SourceLocation SuperLoc)365 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
366 const ObjCContainerDecl *ContD,
367 SourceLocation SuperLoc) {
368 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
369 for (ObjCInterfaceDecl::protocol_iterator
370 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
371 SourceLocation Loc = *LI;
372 ObjCProtocolDecl *PD = *I;
373 SymbolRoleSet roles{};
374 if (Loc == SuperLoc)
375 roles |= (SymbolRoleSet)SymbolRole::Implicit;
376 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
377 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
378 }
379 return true;
380 }
381
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)382 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
383 if (D->isThisDeclarationADefinition()) {
384 TRY_DECL(D, IndexCtx.handleDecl(D));
385 SourceLocation SuperLoc = D->getSuperClassLoc();
386 if (auto *SuperD = D->getSuperClass()) {
387 bool hasSuperTypedef = false;
388 if (auto *TInfo = D->getSuperClassTInfo()) {
389 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
390 if (auto *TD = TT->getDecl()) {
391 hasSuperTypedef = true;
392 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
393 SymbolRoleSet()));
394 }
395 }
396 }
397 SymbolRoleSet superRoles{};
398 if (hasSuperTypedef)
399 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
400 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
401 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
402 }
403 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
404 SuperLoc));
405 TRY_TO(IndexCtx.indexDeclContext(D));
406 } else {
407 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
408 D->getDeclContext(), SymbolRoleSet());
409 }
410 return true;
411 }
412
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)413 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
414 if (D->isThisDeclarationADefinition()) {
415 TRY_DECL(D, IndexCtx.handleDecl(D));
416 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
417 /*superLoc=*/SourceLocation()));
418 TRY_TO(IndexCtx.indexDeclContext(D));
419 } else {
420 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
421 D->getDeclContext(), SymbolRoleSet());
422 }
423 return true;
424 }
425
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)426 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
427 const ObjCInterfaceDecl *Class = D->getClassInterface();
428 if (!Class)
429 return true;
430
431 if (Class->isImplicitInterfaceDecl())
432 IndexCtx.handleDecl(Class);
433
434 TRY_DECL(D, IndexCtx.handleDecl(D));
435
436 // Visit implicit @synthesize property implementations first as their
437 // location is reported at the name of the @implementation block. This
438 // serves no purpose other than to simplify the FileCheck-based tests.
439 for (const auto *I : D->property_impls()) {
440 if (I->getLocation().isInvalid())
441 IndexCtx.indexDecl(I);
442 }
443 for (const auto *I : D->decls()) {
444 if (!isa<ObjCPropertyImplDecl>(I) ||
445 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
446 IndexCtx.indexDecl(I);
447 }
448
449 return true;
450 }
451
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)452 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
453 if (!IndexCtx.shouldIndex(D))
454 return true;
455 const ObjCInterfaceDecl *C = D->getClassInterface();
456 if (!C)
457 return true;
458 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
459 SymbolRelation{
460 (unsigned)SymbolRole::RelationExtendedBy, D
461 }));
462 SourceLocation CategoryLoc = D->getCategoryNameLoc();
463 if (!CategoryLoc.isValid())
464 CategoryLoc = D->getLocation();
465 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
466 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
467 /*superLoc=*/SourceLocation()));
468 TRY_TO(IndexCtx.indexDeclContext(D));
469 return true;
470 }
471
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)472 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
473 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
474 if (!Cat)
475 return true;
476 const ObjCInterfaceDecl *C = D->getClassInterface();
477 if (C)
478 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
479 SymbolRoleSet()));
480 SourceLocation CategoryLoc = D->getCategoryNameLoc();
481 if (!CategoryLoc.isValid())
482 CategoryLoc = D->getLocation();
483 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
484 IndexCtx.indexDeclContext(D);
485 return true;
486 }
487
VisitObjCMethodDecl(const ObjCMethodDecl * D)488 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
489 // Methods associated with a property, even user-declared ones, are
490 // handled when we handle the property.
491 if (D->isPropertyAccessor())
492 return true;
493
494 handleObjCMethod(D);
495 return true;
496 }
497
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)498 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
499 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
500 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
501 handleObjCMethod(MD, D);
502 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
503 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
504 handleObjCMethod(MD, D);
505 TRY_DECL(D, IndexCtx.handleDecl(D));
506 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
507 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
508 D->getLexicalDeclContext(), false, true);
509 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
510 return true;
511 }
512
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)513 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
514 ObjCPropertyDecl *PD = D->getPropertyDecl();
515 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
516 SourceLocation Loc = D->getLocation();
517 SymbolRoleSet Roles = 0;
518 SmallVector<SymbolRelation, 1> Relations;
519
520 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
521 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
522 if (Loc.isInvalid()) {
523 Loc = Container->getLocation();
524 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
525 }
526 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
527
528 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
529 return true;
530
531 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
532 SymbolRoleSet AccessorMethodRoles =
533 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
534 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
535 if (MD->isPropertyAccessor() &&
536 !hasUserDefined(MD, Container))
537 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
538 }
539 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
540 if (MD->isPropertyAccessor() &&
541 !hasUserDefined(MD, Container))
542 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
543 }
544 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
545 if (IvarD->getSynthesize()) {
546 // For synthesized ivars, use the location of its name in the
547 // corresponding @synthesize. If there isn't one, use the containing
548 // @implementation's location, rather than the property's location,
549 // otherwise the header file containing the @interface will have different
550 // indexing contents based on whether the @implementation was present or
551 // not in the translation unit.
552 SymbolRoleSet IvarRoles = 0;
553 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
554 if (D->getLocation().isInvalid()) {
555 IvarLoc = Container->getLocation();
556 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
557 } else if (D->getLocation() == IvarLoc) {
558 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
559 }
560 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
561 } else {
562 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
563 D->getDeclContext(), SymbolRoleSet());
564 }
565 }
566 return true;
567 }
568
VisitNamespaceDecl(const NamespaceDecl * D)569 bool VisitNamespaceDecl(const NamespaceDecl *D) {
570 TRY_DECL(D, IndexCtx.handleDecl(D));
571 IndexCtx.indexDeclContext(D);
572 return true;
573 }
574
VisitNamespaceAliasDecl(const NamespaceAliasDecl * D)575 bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
576 TRY_DECL(D, IndexCtx.handleDecl(D));
577 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
578 IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
579 D->getLexicalDeclContext());
580 return true;
581 }
582
VisitUsingDecl(const UsingDecl * D)583 bool VisitUsingDecl(const UsingDecl *D) {
584 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
585 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
586
587 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
588 D->getLexicalDeclContext());
589 for (const auto *I : D->shadows())
590 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
591 D->getLexicalDeclContext(), SymbolRoleSet());
592 return true;
593 }
594
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)595 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
596 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
597 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
598
599 // NNS for the local 'using namespace' directives is visited by the body
600 // visitor.
601 if (!D->getParentFunctionOrMethod())
602 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
603 D->getLexicalDeclContext());
604
605 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
606 D->getLocation(), Parent,
607 D->getLexicalDeclContext(),
608 SymbolRoleSet());
609 }
610
VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl * D)611 bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
612 TRY_DECL(D, IndexCtx.handleDecl(D));
613 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
614 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
615 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
616 D->getLexicalDeclContext());
617 return true;
618 }
619
VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl * D)620 bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
621 TRY_DECL(D, IndexCtx.handleDecl(D));
622 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
623 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
624 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
625 D->getLexicalDeclContext());
626 return true;
627 }
628
VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)629 bool VisitClassTemplateSpecializationDecl(const
630 ClassTemplateSpecializationDecl *D) {
631 // FIXME: Notify subsequent callbacks if info comes from implicit
632 // instantiation.
633 llvm::PointerUnion<ClassTemplateDecl *,
634 ClassTemplatePartialSpecializationDecl *>
635 Template = D->getSpecializedTemplateOrPartial();
636 const Decl *SpecializationOf =
637 Template.is<ClassTemplateDecl *>()
638 ? (Decl *)Template.get<ClassTemplateDecl *>()
639 : Template.get<ClassTemplatePartialSpecializationDecl *>();
640 if (!D->isThisDeclarationADefinition())
641 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
642 IndexCtx.indexTagDecl(
643 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
644 SpecializationOf));
645 if (TypeSourceInfo *TSI = D->getTypeAsWritten())
646 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
647 D->getLexicalDeclContext());
648 return true;
649 }
650
shouldIndexTemplateParameterDefaultValue(const NamedDecl * D)651 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
652 if (!D)
653 return false;
654 // We want to index the template parameters only once when indexing the
655 // canonical declaration.
656 if (const auto *FD = dyn_cast<FunctionDecl>(D))
657 return FD->getCanonicalDecl() == FD;
658 else if (const auto *TD = dyn_cast<TagDecl>(D))
659 return TD->getCanonicalDecl() == TD;
660 else if (const auto *VD = dyn_cast<VarDecl>(D))
661 return VD->getCanonicalDecl() == VD;
662 return true;
663 }
664
VisitTemplateDecl(const TemplateDecl * D)665 bool VisitTemplateDecl(const TemplateDecl *D) {
666
667 const NamedDecl *Parent = D->getTemplatedDecl();
668 if (!Parent)
669 return true;
670
671 // Index the default values for the template parameters.
672 if (D->getTemplateParameters() &&
673 shouldIndexTemplateParameterDefaultValue(Parent)) {
674 const TemplateParameterList *Params = D->getTemplateParameters();
675 for (const NamedDecl *TP : *Params) {
676 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
677 if (TTP->hasDefaultArgument())
678 IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
679 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
680 if (NTTP->hasDefaultArgument())
681 IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
682 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
683 if (TTPD->hasDefaultArgument())
684 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
685 TP->getLexicalDeclContext());
686 }
687 }
688 }
689
690 return Visit(Parent);
691 }
692
VisitFriendDecl(const FriendDecl * D)693 bool VisitFriendDecl(const FriendDecl *D) {
694 if (auto ND = D->getFriendDecl()) {
695 // FIXME: Ignore a class template in a dependent context, these are not
696 // linked properly with their redeclarations, ending up with duplicate
697 // USRs.
698 // See comment "Friend templates are visible in fairly strange ways." in
699 // SemaTemplate.cpp which precedes code that prevents the friend template
700 // from becoming visible from the enclosing context.
701 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
702 return true;
703 return Visit(ND);
704 }
705 if (auto Ty = D->getFriendType()) {
706 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
707 }
708 return true;
709 }
710
VisitImportDecl(const ImportDecl * D)711 bool VisitImportDecl(const ImportDecl *D) {
712 return IndexCtx.importedModule(D);
713 }
714
VisitStaticAssertDecl(const StaticAssertDecl * D)715 bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
716 IndexCtx.indexBody(D->getAssertExpr(),
717 dyn_cast<NamedDecl>(D->getDeclContext()),
718 D->getLexicalDeclContext());
719 return true;
720 }
721 };
722
723 } // anonymous namespace
724
indexDecl(const Decl * D)725 bool IndexingContext::indexDecl(const Decl *D) {
726 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
727 return true;
728
729 if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
730 return true;
731
732 IndexingDeclVisitor Visitor(*this);
733 bool ShouldContinue = Visitor.Visit(D);
734 if (!ShouldContinue)
735 return false;
736
737 if (!Visitor.Handled && isa<DeclContext>(D))
738 return indexDeclContext(cast<DeclContext>(D));
739
740 return true;
741 }
742
indexDeclContext(const DeclContext * DC)743 bool IndexingContext::indexDeclContext(const DeclContext *DC) {
744 for (const auto *I : DC->decls())
745 if (!indexDecl(I))
746 return false;
747 return true;
748 }
749
indexTopLevelDecl(const Decl * D)750 bool IndexingContext::indexTopLevelDecl(const Decl *D) {
751 if (D->getLocation().isInvalid())
752 return true;
753
754 if (isa<ObjCMethodDecl>(D))
755 return true; // Wait for the objc container.
756
757 return indexDecl(D);
758 }
759
indexDeclGroupRef(DeclGroupRef DG)760 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
761 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
762 if (!indexTopLevelDecl(*I))
763 return false;
764 return true;
765 }
766