1 //===- IndexDecl.cpp - Indexing declarations ------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "IndexingContext.h"
10 #include "clang/AST/ASTConcept.h"
11 #include "clang/AST/Attr.h"
12 #include "clang/AST/Decl.h"
13 #include "clang/AST/DeclTemplate.h"
14 #include "clang/AST/DeclVisitor.h"
15 #include "clang/Index/IndexDataConsumer.h"
16 #include "clang/Index/IndexSymbol.h"
18 using namespace clang
;
19 using namespace index
;
21 #define TRY_DECL(D,CALL_EXPR) \
23 if (!IndexCtx.shouldIndex(D)) return true; \
28 #define TRY_TO(CALL_EXPR) \
36 class IndexingDeclVisitor
: public ConstDeclVisitor
<IndexingDeclVisitor
, bool> {
37 IndexingContext
&IndexCtx
;
40 explicit IndexingDeclVisitor(IndexingContext
&indexCtx
)
41 : IndexCtx(indexCtx
) { }
45 bool VisitDecl(const Decl
*D
) {
50 void handleTemplateArgumentLoc(const TemplateArgumentLoc
&TALoc
,
51 const NamedDecl
*Parent
,
52 const DeclContext
*DC
) {
53 const TemplateArgumentLocInfo
&LocInfo
= TALoc
.getLocInfo();
54 switch (TALoc
.getArgument().getKind()) {
55 case TemplateArgument::Expression
:
56 IndexCtx
.indexBody(LocInfo
.getAsExpr(), Parent
, DC
);
58 case TemplateArgument::Type
:
59 IndexCtx
.indexTypeSourceInfo(LocInfo
.getAsTypeSourceInfo(), Parent
, DC
);
61 case TemplateArgument::Template
:
62 case TemplateArgument::TemplateExpansion
:
63 IndexCtx
.indexNestedNameSpecifierLoc(TALoc
.getTemplateQualifierLoc(),
65 if (const TemplateDecl
*TD
= TALoc
.getArgument()
66 .getAsTemplateOrTemplatePattern()
67 .getAsTemplateDecl()) {
68 if (const NamedDecl
*TTD
= TD
->getTemplatedDecl())
69 IndexCtx
.handleReference(TTD
, TALoc
.getTemplateNameLoc(), Parent
, DC
);
77 /// Returns true if the given method has been defined explicitly by the
79 static bool hasUserDefined(const ObjCMethodDecl
*D
,
80 const ObjCImplDecl
*Container
) {
81 const ObjCMethodDecl
*MD
= Container
->getMethod(D
->getSelector(),
82 D
->isInstanceMethod());
83 return MD
&& !MD
->isImplicit() && MD
->isThisDeclarationADefinition() &&
84 !MD
->isSynthesizedAccessorStub();
88 void handleDeclarator(const DeclaratorDecl
*D
,
89 const NamedDecl
*Parent
= nullptr,
90 bool isIBType
= false) {
91 if (!Parent
) Parent
= D
;
93 IndexCtx
.indexTypeSourceInfo(D
->getTypeSourceInfo(), Parent
,
94 Parent
->getLexicalDeclContext(),
95 /*isBase=*/false, isIBType
);
96 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), Parent
);
97 auto IndexDefaultParmeterArgument
= [&](const ParmVarDecl
*Parm
,
98 const NamedDecl
*Parent
) {
99 if (Parm
->hasDefaultArg() && !Parm
->hasUninstantiatedDefaultArg() &&
100 !Parm
->hasUnparsedDefaultArg())
101 IndexCtx
.indexBody(Parm
->getDefaultArg(), Parent
);
103 if (IndexCtx
.shouldIndexFunctionLocalSymbols()) {
104 if (const ParmVarDecl
*Parm
= dyn_cast
<ParmVarDecl
>(D
)) {
105 auto *DC
= Parm
->getDeclContext();
106 if (auto *FD
= dyn_cast
<FunctionDecl
>(DC
)) {
107 if (IndexCtx
.shouldIndexParametersInDeclarations() ||
108 FD
->isThisDeclarationADefinition())
109 IndexCtx
.handleDecl(Parm
);
110 } else if (auto *MD
= dyn_cast
<ObjCMethodDecl
>(DC
)) {
111 if (MD
->isThisDeclarationADefinition())
112 IndexCtx
.handleDecl(Parm
);
114 IndexCtx
.handleDecl(Parm
);
116 } else if (const FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(D
)) {
117 if (IndexCtx
.shouldIndexParametersInDeclarations() ||
118 FD
->isThisDeclarationADefinition()) {
119 for (const auto *PI
: FD
->parameters()) {
120 IndexDefaultParmeterArgument(PI
, D
);
121 IndexCtx
.handleDecl(PI
);
126 // Index the default parameter value for function definitions.
127 if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
128 if (FD
->isThisDeclarationADefinition()) {
129 for (const auto *PV
: FD
->parameters()) {
130 IndexDefaultParmeterArgument(PV
, D
);
135 if (auto *C
= D
->getTrailingRequiresClause())
136 IndexCtx
.indexBody(C
, Parent
);
139 bool handleObjCMethod(const ObjCMethodDecl
*D
,
140 const ObjCPropertyDecl
*AssociatedProp
= nullptr) {
141 SmallVector
<SymbolRelation
, 4> Relations
;
142 SmallVector
<const ObjCMethodDecl
*, 4> Overriden
;
144 D
->getOverriddenMethods(Overriden
);
145 for(auto overridden
: Overriden
) {
146 Relations
.emplace_back((unsigned) SymbolRole::RelationOverrideOf
,
150 Relations
.emplace_back((unsigned)SymbolRole::RelationAccessorOf
,
153 // getLocation() returns beginning token of a method declaration, but for
154 // indexing purposes we want to point to the base name.
155 SourceLocation MethodLoc
= D
->getSelectorStartLoc();
156 if (MethodLoc
.isInvalid())
157 MethodLoc
= D
->getLocation();
159 SourceLocation AttrLoc
;
161 // check for (getter=/setter=)
162 if (AssociatedProp
) {
163 bool isGetter
= !D
->param_size();
165 AssociatedProp
->getGetterNameLoc():
166 AssociatedProp
->getSetterNameLoc();
169 SymbolRoleSet Roles
= (SymbolRoleSet
)SymbolRole::Dynamic
;
170 if (D
->isImplicit()) {
171 if (AttrLoc
.isValid()) {
174 Roles
|= (SymbolRoleSet
)SymbolRole::Implicit
;
176 } else if (AttrLoc
.isValid()) {
177 IndexCtx
.handleReference(D
, AttrLoc
, cast
<NamedDecl
>(D
->getDeclContext()),
178 D
->getDeclContext(), 0);
181 TRY_DECL(D
, IndexCtx
.handleDecl(D
, MethodLoc
, Roles
, Relations
));
182 IndexCtx
.indexTypeSourceInfo(D
->getReturnTypeSourceInfo(), D
);
183 bool hasIBActionAndFirst
= D
->hasAttr
<IBActionAttr
>();
184 for (const auto *I
: D
->parameters()) {
185 handleDeclarator(I
, D
, /*isIBType=*/hasIBActionAndFirst
);
186 hasIBActionAndFirst
= false;
189 if (D
->isThisDeclarationADefinition()) {
190 const Stmt
*Body
= D
->getBody();
192 IndexCtx
.indexBody(Body
, D
, D
);
198 /// Gather the declarations which the given declaration \D overrides in a
199 /// pseudo-override manner.
201 /// Pseudo-overrides occur when a class template specialization declares
202 /// a declaration that has the same name as a similar declaration in the
203 /// non-specialized template.
205 gatherTemplatePseudoOverrides(const NamedDecl
*D
,
206 SmallVectorImpl
<SymbolRelation
> &Relations
) {
207 if (!IndexCtx
.getLangOpts().CPlusPlus
)
210 dyn_cast
<ClassTemplateSpecializationDecl
>(D
->getLexicalDeclContext());
213 llvm::PointerUnion
<ClassTemplateDecl
*,
214 ClassTemplatePartialSpecializationDecl
*>
215 Template
= CTSD
->getSpecializedTemplateOrPartial();
216 if (const auto *CTD
= Template
.dyn_cast
<ClassTemplateDecl
*>()) {
217 const CXXRecordDecl
*Pattern
= CTD
->getTemplatedDecl();
218 bool TypeOverride
= isa
<TypeDecl
>(D
);
219 for (const NamedDecl
*ND
: Pattern
->lookup(D
->getDeclName())) {
220 if (const auto *CTD
= dyn_cast
<ClassTemplateDecl
>(ND
))
221 ND
= CTD
->getTemplatedDecl();
222 if (ND
->isImplicit())
224 // Types can override other types.
226 if (ND
->getKind() != D
->getKind())
228 } else if (!isa
<TypeDecl
>(ND
))
230 if (const auto *FD
= dyn_cast
<FunctionDecl
>(ND
)) {
231 const auto *DFD
= cast
<FunctionDecl
>(D
);
232 // Function overrides are approximated using the number of parameters.
233 if (FD
->getStorageClass() != DFD
->getStorageClass() ||
234 FD
->getNumParams() != DFD
->getNumParams())
237 Relations
.emplace_back(
238 SymbolRoleSet(SymbolRole::RelationSpecializationOf
), ND
);
243 bool VisitFunctionDecl(const FunctionDecl
*D
) {
244 SymbolRoleSet Roles
{};
245 SmallVector
<SymbolRelation
, 4> Relations
;
246 if (auto *CXXMD
= dyn_cast
<CXXMethodDecl
>(D
)) {
247 if (CXXMD
->isVirtual())
248 Roles
|= (unsigned)SymbolRole::Dynamic
;
249 for (const CXXMethodDecl
*O
: CXXMD
->overridden_methods()) {
250 Relations
.emplace_back((unsigned)SymbolRole::RelationOverrideOf
, O
);
253 gatherTemplatePseudoOverrides(D
, Relations
);
254 if (const auto *Base
= D
->getPrimaryTemplate())
256 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf
),
257 Base
->getTemplatedDecl()));
259 TRY_DECL(D
, IndexCtx
.handleDecl(D
, Roles
, Relations
));
262 if (const CXXConstructorDecl
*Ctor
= dyn_cast
<CXXConstructorDecl
>(D
)) {
263 IndexCtx
.handleReference(Ctor
->getParent(), Ctor
->getLocation(),
264 Ctor
->getParent(), Ctor
->getDeclContext(),
265 (unsigned)SymbolRole::NameReference
);
267 // Constructor initializers.
268 for (const auto *Init
: Ctor
->inits()) {
269 if (Init
->isWritten()) {
270 IndexCtx
.indexTypeSourceInfo(Init
->getTypeSourceInfo(), D
);
271 if (const FieldDecl
*Member
= Init
->getAnyMember())
272 IndexCtx
.handleReference(Member
, Init
->getMemberLocation(), D
, D
,
273 (unsigned)SymbolRole::Write
);
274 IndexCtx
.indexBody(Init
->getInit(), D
, D
);
277 } else if (const CXXDestructorDecl
*Dtor
= dyn_cast
<CXXDestructorDecl
>(D
)) {
278 if (auto TypeNameInfo
= Dtor
->getNameInfo().getNamedTypeInfo()) {
279 IndexCtx
.handleReference(Dtor
->getParent(),
280 TypeNameInfo
->getTypeLoc().getBeginLoc(),
281 Dtor
->getParent(), Dtor
->getDeclContext(),
282 (unsigned)SymbolRole::NameReference
);
284 } else if (const auto *Guide
= dyn_cast
<CXXDeductionGuideDecl
>(D
)) {
285 IndexCtx
.handleReference(Guide
->getDeducedTemplate()->getTemplatedDecl(),
286 Guide
->getLocation(), Guide
,
287 Guide
->getDeclContext());
289 // Template specialization arguments.
290 if (const ASTTemplateArgumentListInfo
*TemplateArgInfo
=
291 D
->getTemplateSpecializationArgsAsWritten()) {
292 for (const auto &Arg
: TemplateArgInfo
->arguments())
293 handleTemplateArgumentLoc(Arg
, D
, D
->getLexicalDeclContext());
296 if (D
->isThisDeclarationADefinition()) {
297 const Stmt
*Body
= D
->getBody();
299 IndexCtx
.indexBody(Body
, D
, D
);
305 bool VisitVarDecl(const VarDecl
*D
) {
306 SmallVector
<SymbolRelation
, 4> Relations
;
307 gatherTemplatePseudoOverrides(D
, Relations
);
308 TRY_DECL(D
, IndexCtx
.handleDecl(D
, SymbolRoleSet(), Relations
));
310 IndexCtx
.indexBody(D
->getInit(), D
);
314 bool VisitDecompositionDecl(const DecompositionDecl
*D
) {
315 for (const auto *Binding
: D
->bindings())
316 TRY_DECL(Binding
, IndexCtx
.handleDecl(Binding
));
317 return Base::VisitDecompositionDecl(D
);
320 bool VisitFieldDecl(const FieldDecl
*D
) {
321 SmallVector
<SymbolRelation
, 4> Relations
;
322 gatherTemplatePseudoOverrides(D
, Relations
);
323 TRY_DECL(D
, IndexCtx
.handleDecl(D
, SymbolRoleSet(), Relations
));
326 IndexCtx
.indexBody(D
->getBitWidth(), D
);
327 else if (D
->hasInClassInitializer())
328 IndexCtx
.indexBody(D
->getInClassInitializer(), D
);
332 bool VisitObjCIvarDecl(const ObjCIvarDecl
*D
) {
333 if (D
->getSynthesize()) {
334 // handled in VisitObjCPropertyImplDecl
337 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
342 bool VisitMSPropertyDecl(const MSPropertyDecl
*D
) {
343 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
348 bool VisitEnumConstantDecl(const EnumConstantDecl
*D
) {
349 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
350 IndexCtx
.indexBody(D
->getInitExpr(), D
);
354 bool VisitTypedefNameDecl(const TypedefNameDecl
*D
) {
355 if (!D
->isTransparentTag()) {
356 SmallVector
<SymbolRelation
, 4> Relations
;
357 gatherTemplatePseudoOverrides(D
, Relations
);
358 TRY_DECL(D
, IndexCtx
.handleDecl(D
, SymbolRoleSet(), Relations
));
359 IndexCtx
.indexTypeSourceInfo(D
->getTypeSourceInfo(), D
);
364 bool VisitTagDecl(const TagDecl
*D
) {
365 // Non-free standing tags are handled in indexTypeSourceInfo.
366 if (D
->isFreeStanding()) {
367 if (D
->isThisDeclarationADefinition()) {
368 SmallVector
<SymbolRelation
, 4> Relations
;
369 gatherTemplatePseudoOverrides(D
, Relations
);
370 IndexCtx
.indexTagDecl(D
, Relations
);
372 SmallVector
<SymbolRelation
, 1> Relations
;
373 gatherTemplatePseudoOverrides(D
, Relations
);
374 return IndexCtx
.handleDecl(D
, D
->getLocation(), SymbolRoleSet(),
375 Relations
, D
->getLexicalDeclContext());
381 bool VisitEnumDecl(const EnumDecl
*ED
) {
382 TRY_TO(VisitTagDecl(ED
));
383 // Indexing for enumdecl itself is handled inside TagDecl, we just want to
384 // visit integer-base here, which is different than other TagDecl bases.
385 if (auto *TSI
= ED
->getIntegerTypeSourceInfo())
386 IndexCtx
.indexTypeSourceInfo(TSI
, ED
, ED
, /*isBase=*/true);
390 bool handleReferencedProtocols(const ObjCProtocolList
&ProtList
,
391 const ObjCContainerDecl
*ContD
,
392 SourceLocation SuperLoc
) {
393 ObjCInterfaceDecl::protocol_loc_iterator LI
= ProtList
.loc_begin();
394 for (ObjCInterfaceDecl::protocol_iterator
395 I
= ProtList
.begin(), E
= ProtList
.end(); I
!= E
; ++I
, ++LI
) {
396 SourceLocation Loc
= *LI
;
397 ObjCProtocolDecl
*PD
= *I
;
398 SymbolRoleSet roles
{};
400 roles
|= (SymbolRoleSet
)SymbolRole::Implicit
;
401 TRY_TO(IndexCtx
.handleReference(PD
, Loc
, ContD
, ContD
, roles
,
402 SymbolRelation
{(unsigned)SymbolRole::RelationBaseOf
, ContD
}));
407 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl
*D
) {
408 if (D
->isThisDeclarationADefinition()) {
409 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
410 SourceLocation SuperLoc
= D
->getSuperClassLoc();
411 if (auto *SuperD
= D
->getSuperClass()) {
412 bool hasSuperTypedef
= false;
413 if (auto *TInfo
= D
->getSuperClassTInfo()) {
414 if (auto *TT
= TInfo
->getType()->getAs
<TypedefType
>()) {
415 if (auto *TD
= TT
->getDecl()) {
416 hasSuperTypedef
= true;
417 TRY_TO(IndexCtx
.handleReference(TD
, SuperLoc
, D
, D
,
422 SymbolRoleSet superRoles
{};
424 superRoles
|= (SymbolRoleSet
)SymbolRole::Implicit
;
425 TRY_TO(IndexCtx
.handleReference(SuperD
, SuperLoc
, D
, D
, superRoles
,
426 SymbolRelation
{(unsigned)SymbolRole::RelationBaseOf
, D
}));
428 TRY_TO(handleReferencedProtocols(D
->getReferencedProtocols(), D
,
430 TRY_TO(IndexCtx
.indexDeclContext(D
));
432 return IndexCtx
.handleReference(D
, D
->getLocation(), nullptr,
433 D
->getDeclContext(), SymbolRoleSet());
438 bool VisitObjCProtocolDecl(const ObjCProtocolDecl
*D
) {
439 if (D
->isThisDeclarationADefinition()) {
440 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
441 TRY_TO(handleReferencedProtocols(D
->getReferencedProtocols(), D
,
442 /*SuperLoc=*/SourceLocation()));
443 TRY_TO(IndexCtx
.indexDeclContext(D
));
445 return IndexCtx
.handleReference(D
, D
->getLocation(), nullptr,
446 D
->getDeclContext(), SymbolRoleSet());
451 bool VisitObjCImplementationDecl(const ObjCImplementationDecl
*D
) {
452 const ObjCInterfaceDecl
*Class
= D
->getClassInterface();
456 if (Class
->isImplicitInterfaceDecl())
457 IndexCtx
.handleDecl(Class
);
459 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
461 // Visit implicit @synthesize property implementations first as their
462 // location is reported at the name of the @implementation block. This
463 // serves no purpose other than to simplify the FileCheck-based tests.
464 for (const auto *I
: D
->property_impls()) {
465 if (I
->getLocation().isInvalid())
466 IndexCtx
.indexDecl(I
);
468 for (const auto *I
: D
->decls()) {
469 if (!isa
<ObjCPropertyImplDecl
>(I
) ||
470 cast
<ObjCPropertyImplDecl
>(I
)->getLocation().isValid())
471 IndexCtx
.indexDecl(I
);
477 bool VisitObjCCategoryDecl(const ObjCCategoryDecl
*D
) {
478 if (!IndexCtx
.shouldIndex(D
))
480 const ObjCInterfaceDecl
*C
= D
->getClassInterface();
483 TRY_TO(IndexCtx
.handleReference(C
, D
->getLocation(), D
, D
, SymbolRoleSet(),
485 (unsigned)SymbolRole::RelationExtendedBy
, D
487 SourceLocation CategoryLoc
= D
->getCategoryNameLoc();
488 if (!CategoryLoc
.isValid())
489 CategoryLoc
= D
->getLocation();
490 TRY_TO(IndexCtx
.handleDecl(D
, CategoryLoc
));
491 TRY_TO(handleReferencedProtocols(D
->getReferencedProtocols(), D
,
492 /*SuperLoc=*/SourceLocation()));
493 TRY_TO(IndexCtx
.indexDeclContext(D
));
497 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl
*D
) {
498 const ObjCCategoryDecl
*Cat
= D
->getCategoryDecl();
501 const ObjCInterfaceDecl
*C
= D
->getClassInterface();
503 TRY_TO(IndexCtx
.handleReference(C
, D
->getLocation(), D
, D
,
505 SourceLocation CategoryLoc
= D
->getCategoryNameLoc();
506 if (!CategoryLoc
.isValid())
507 CategoryLoc
= D
->getLocation();
508 TRY_DECL(D
, IndexCtx
.handleDecl(D
, CategoryLoc
));
509 IndexCtx
.indexDeclContext(D
);
513 bool VisitObjCMethodDecl(const ObjCMethodDecl
*D
) {
514 // Methods associated with a property, even user-declared ones, are
515 // handled when we handle the property.
516 if (D
->isPropertyAccessor())
523 bool VisitObjCPropertyDecl(const ObjCPropertyDecl
*D
) {
524 if (ObjCMethodDecl
*MD
= D
->getGetterMethodDecl())
525 if (MD
->getLexicalDeclContext() == D
->getLexicalDeclContext())
526 handleObjCMethod(MD
, D
);
527 if (ObjCMethodDecl
*MD
= D
->getSetterMethodDecl())
528 if (MD
->getLexicalDeclContext() == D
->getLexicalDeclContext())
529 handleObjCMethod(MD
, D
);
530 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
531 if (IBOutletCollectionAttr
*attr
= D
->getAttr
<IBOutletCollectionAttr
>())
532 IndexCtx
.indexTypeSourceInfo(attr
->getInterfaceLoc(), D
,
533 D
->getLexicalDeclContext(), false, true);
534 IndexCtx
.indexTypeSourceInfo(D
->getTypeSourceInfo(), D
);
538 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl
*D
) {
539 ObjCPropertyDecl
*PD
= D
->getPropertyDecl();
540 auto *Container
= cast
<ObjCImplDecl
>(D
->getDeclContext());
541 SourceLocation Loc
= D
->getLocation();
542 SymbolRoleSet Roles
= 0;
543 SmallVector
<SymbolRelation
, 1> Relations
;
545 if (ObjCIvarDecl
*ID
= D
->getPropertyIvarDecl())
546 Relations
.push_back({(SymbolRoleSet
)SymbolRole::RelationAccessorOf
, ID
});
547 if (Loc
.isInvalid()) {
548 Loc
= Container
->getLocation();
549 Roles
|= (SymbolRoleSet
)SymbolRole::Implicit
;
551 TRY_DECL(D
, IndexCtx
.handleDecl(D
, Loc
, Roles
, Relations
));
553 if (D
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
)
556 assert(D
->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize
);
557 SymbolRoleSet AccessorMethodRoles
=
558 SymbolRoleSet(SymbolRole::Dynamic
) | SymbolRoleSet(SymbolRole::Implicit
);
559 if (ObjCMethodDecl
*MD
= PD
->getGetterMethodDecl()) {
560 if (MD
->isPropertyAccessor() && !hasUserDefined(MD
, Container
))
561 IndexCtx
.handleDecl(MD
, Loc
, AccessorMethodRoles
, {}, Container
);
563 if (ObjCMethodDecl
*MD
= PD
->getSetterMethodDecl()) {
564 if (MD
->isPropertyAccessor() && !hasUserDefined(MD
, Container
))
565 IndexCtx
.handleDecl(MD
, Loc
, AccessorMethodRoles
, {}, Container
);
567 if (ObjCIvarDecl
*IvarD
= D
->getPropertyIvarDecl()) {
568 if (IvarD
->getSynthesize()) {
569 // For synthesized ivars, use the location of its name in the
570 // corresponding @synthesize. If there isn't one, use the containing
571 // @implementation's location, rather than the property's location,
572 // otherwise the header file containing the @interface will have different
573 // indexing contents based on whether the @implementation was present or
574 // not in the translation unit.
575 SymbolRoleSet IvarRoles
= 0;
576 SourceLocation IvarLoc
= D
->getPropertyIvarDeclLoc();
577 if (D
->getLocation().isInvalid()) {
578 IvarLoc
= Container
->getLocation();
579 IvarRoles
= (SymbolRoleSet
)SymbolRole::Implicit
;
580 } else if (D
->getLocation() == IvarLoc
) {
581 IvarRoles
= (SymbolRoleSet
)SymbolRole::Implicit
;
583 TRY_DECL(IvarD
, IndexCtx
.handleDecl(IvarD
, IvarLoc
, IvarRoles
));
585 IndexCtx
.handleReference(IvarD
, D
->getPropertyIvarDeclLoc(), nullptr,
586 D
->getDeclContext(), SymbolRoleSet());
592 bool VisitNamespaceDecl(const NamespaceDecl
*D
) {
593 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
594 IndexCtx
.indexDeclContext(D
);
598 bool VisitNamespaceAliasDecl(const NamespaceAliasDecl
*D
) {
599 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
600 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), D
);
601 IndexCtx
.handleReference(D
->getAliasedNamespace(), D
->getTargetNameLoc(), D
,
602 D
->getLexicalDeclContext());
606 bool VisitUsingDecl(const UsingDecl
*D
) {
607 IndexCtx
.handleDecl(D
);
609 const DeclContext
*DC
= D
->getDeclContext()->getRedeclContext();
610 const NamedDecl
*Parent
= dyn_cast
<NamedDecl
>(DC
);
611 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), Parent
,
612 D
->getLexicalDeclContext());
613 for (const auto *I
: D
->shadows()) {
614 // Skip unresolved using decls - we already have a decl for the using
615 // itself, so there's not much point adding another decl or reference to
616 // refer to the same location.
617 if (isa
<UnresolvedUsingIfExistsDecl
>(I
->getUnderlyingDecl()))
620 IndexCtx
.handleReference(I
->getUnderlyingDecl(), D
->getLocation(), Parent
,
621 D
->getLexicalDeclContext(), SymbolRoleSet());
626 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl
*D
) {
627 const DeclContext
*DC
= D
->getDeclContext()->getRedeclContext();
628 const NamedDecl
*Parent
= dyn_cast
<NamedDecl
>(DC
);
630 // NNS for the local 'using namespace' directives is visited by the body
632 if (!D
->getParentFunctionOrMethod())
633 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), Parent
,
634 D
->getLexicalDeclContext());
636 return IndexCtx
.handleReference(D
->getNominatedNamespaceAsWritten(),
637 D
->getLocation(), Parent
,
638 D
->getLexicalDeclContext(),
642 bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl
*D
) {
643 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
644 const DeclContext
*DC
= D
->getDeclContext()->getRedeclContext();
645 const NamedDecl
*Parent
= dyn_cast
<NamedDecl
>(DC
);
646 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), Parent
,
647 D
->getLexicalDeclContext());
651 bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl
*D
) {
652 TRY_DECL(D
, IndexCtx
.handleDecl(D
));
653 const DeclContext
*DC
= D
->getDeclContext()->getRedeclContext();
654 const NamedDecl
*Parent
= dyn_cast
<NamedDecl
>(DC
);
655 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), Parent
,
656 D
->getLexicalDeclContext());
660 bool VisitClassTemplateSpecializationDecl(const
661 ClassTemplateSpecializationDecl
*D
) {
662 // FIXME: Notify subsequent callbacks if info comes from implicit
664 llvm::PointerUnion
<ClassTemplateDecl
*,
665 ClassTemplatePartialSpecializationDecl
*>
666 Template
= D
->getSpecializedTemplateOrPartial();
667 const Decl
*SpecializationOf
=
668 Template
.is
<ClassTemplateDecl
*>()
669 ? (Decl
*)Template
.get
<ClassTemplateDecl
*>()
670 : Template
.get
<ClassTemplatePartialSpecializationDecl
*>();
671 if (!D
->isThisDeclarationADefinition())
672 IndexCtx
.indexNestedNameSpecifierLoc(D
->getQualifierLoc(), D
);
673 IndexCtx
.indexTagDecl(
674 D
, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf
),
676 if (TypeSourceInfo
*TSI
= D
->getTypeAsWritten())
677 IndexCtx
.indexTypeSourceInfo(TSI
, /*Parent=*/nullptr,
678 D
->getLexicalDeclContext());
682 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl
*D
) {
683 // We want to index the template parameters only once when indexing the
684 // canonical declaration.
687 if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
))
688 return FD
->getCanonicalDecl() == FD
;
689 else if (const auto *TD
= dyn_cast
<TagDecl
>(D
))
690 return TD
->getCanonicalDecl() == TD
;
691 else if (const auto *VD
= dyn_cast
<VarDecl
>(D
))
692 return VD
->getCanonicalDecl() == VD
;
696 void indexTemplateParameters(TemplateParameterList
*Params
,
697 const NamedDecl
*Parent
) {
698 for (const NamedDecl
*TP
: *Params
) {
699 if (IndexCtx
.shouldIndexTemplateParameters())
700 IndexCtx
.handleDecl(TP
);
701 if (const auto *TTP
= dyn_cast
<TemplateTypeParmDecl
>(TP
)) {
702 if (TTP
->hasDefaultArgument())
703 IndexCtx
.indexTypeSourceInfo(TTP
->getDefaultArgumentInfo(), Parent
);
704 if (auto *C
= TTP
->getTypeConstraint())
705 IndexCtx
.handleReference(C
->getNamedConcept(), C
->getConceptNameLoc(),
706 Parent
, TTP
->getLexicalDeclContext());
707 } else if (const auto *NTTP
= dyn_cast
<NonTypeTemplateParmDecl
>(TP
)) {
708 IndexCtx
.indexTypeSourceInfo(NTTP
->getTypeSourceInfo(), Parent
);
709 if (NTTP
->hasDefaultArgument())
710 IndexCtx
.indexBody(NTTP
->getDefaultArgument(), Parent
);
711 } else if (const auto *TTPD
= dyn_cast
<TemplateTemplateParmDecl
>(TP
)) {
712 if (TTPD
->hasDefaultArgument())
713 handleTemplateArgumentLoc(TTPD
->getDefaultArgument(), Parent
,
714 TP
->getLexicalDeclContext());
717 if (auto *R
= Params
->getRequiresClause())
718 IndexCtx
.indexBody(R
, Parent
);
721 bool VisitTemplateDecl(const TemplateDecl
*D
) {
722 const NamedDecl
*Parent
= D
->getTemplatedDecl();
726 // Index the default values for the template parameters.
727 auto *Params
= D
->getTemplateParameters();
728 if (Params
&& shouldIndexTemplateParameterDefaultValue(Parent
)) {
729 indexTemplateParameters(Params
, Parent
);
732 return Visit(Parent
);
735 bool VisitConceptDecl(const ConceptDecl
*D
) {
736 if (auto *Params
= D
->getTemplateParameters())
737 indexTemplateParameters(Params
, D
);
738 if (auto *E
= D
->getConstraintExpr())
739 IndexCtx
.indexBody(E
, D
);
740 return IndexCtx
.handleDecl(D
);
743 bool VisitFriendDecl(const FriendDecl
*D
) {
744 if (auto ND
= D
->getFriendDecl()) {
745 // FIXME: Ignore a class template in a dependent context, these are not
746 // linked properly with their redeclarations, ending up with duplicate
748 // See comment "Friend templates are visible in fairly strange ways." in
749 // SemaTemplate.cpp which precedes code that prevents the friend template
750 // from becoming visible from the enclosing context.
751 if (isa
<ClassTemplateDecl
>(ND
) && D
->getDeclContext()->isDependentContext())
755 if (auto Ty
= D
->getFriendType()) {
756 IndexCtx
.indexTypeSourceInfo(Ty
, cast
<NamedDecl
>(D
->getDeclContext()));
761 bool VisitImportDecl(const ImportDecl
*D
) {
762 return IndexCtx
.importedModule(D
);
765 bool VisitStaticAssertDecl(const StaticAssertDecl
*D
) {
766 IndexCtx
.indexBody(D
->getAssertExpr(),
767 dyn_cast
<NamedDecl
>(D
->getDeclContext()),
768 D
->getLexicalDeclContext());
773 } // anonymous namespace
775 bool IndexingContext::indexDecl(const Decl
*D
) {
776 if (D
->isImplicit() && shouldIgnoreIfImplicit(D
))
779 if (isTemplateImplicitInstantiation(D
) && !shouldIndexImplicitInstantiation())
782 IndexingDeclVisitor
Visitor(*this);
783 bool ShouldContinue
= Visitor
.Visit(D
);
787 if (!Visitor
.Handled
&& isa
<DeclContext
>(D
))
788 return indexDeclContext(cast
<DeclContext
>(D
));
793 bool IndexingContext::indexDeclContext(const DeclContext
*DC
) {
794 for (const auto *I
: DC
->decls())
800 bool IndexingContext::indexTopLevelDecl(const Decl
*D
) {
801 if (!D
|| D
->getLocation().isInvalid())
804 if (isa
<ObjCMethodDecl
>(D
))
805 return true; // Wait for the objc container.
807 if (IndexOpts
.ShouldTraverseDecl
&& !IndexOpts
.ShouldTraverseDecl(D
))
813 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG
) {
814 for (DeclGroupRef::iterator I
= DG
.begin(), E
= DG
.end(); I
!= E
; ++I
)
815 if (!indexTopLevelDecl(*I
))