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/Index/IndexDataConsumer.h"
11 #include "clang/AST/DeclVisitor.h"
13 using namespace clang;
14 using namespace index;
16 #define TRY_DECL(D,CALL_EXPR) \
18 if (!IndexCtx.shouldIndex(D)) return true; \
23 #define TRY_TO(CALL_EXPR) \
31 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
32 IndexingContext &IndexCtx;
35 explicit IndexingDeclVisitor(IndexingContext &indexCtx)
36 : IndexCtx(indexCtx) { }
40 bool VisitDecl(const Decl *D) {
45 /// Returns true if the given method has been defined explicitly by the
47 static bool hasUserDefined(const ObjCMethodDecl *D,
48 const ObjCImplDecl *Container) {
49 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
50 D->isInstanceMethod());
51 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
54 void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
55 const NamedDecl *Parent,
56 const DeclContext *DC) {
57 const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();
58 switch (TALoc.getArgument().getKind()) {
59 case TemplateArgument::Expression:
60 IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
62 case TemplateArgument::Type:
63 IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
65 case TemplateArgument::Template:
66 case TemplateArgument::TemplateExpansion:
67 IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
69 if (const TemplateDecl *TD = TALoc.getArgument()
70 .getAsTemplateOrTemplatePattern()
71 .getAsTemplateDecl()) {
72 if (const NamedDecl *TTD = TD->getTemplatedDecl())
73 IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
81 void handleDeclarator(const DeclaratorDecl *D,
82 const NamedDecl *Parent = nullptr,
83 bool isIBType = false) {
84 if (!Parent) Parent = D;
86 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
87 Parent->getLexicalDeclContext(),
88 /*isBase=*/false, isIBType);
89 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
90 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
91 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
92 auto *DC = Parm->getDeclContext();
93 if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
94 if (IndexCtx.shouldIndexParametersInDeclarations() ||
95 FD->isThisDeclarationADefinition())
96 IndexCtx.handleDecl(Parm);
97 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
98 if (MD->isThisDeclarationADefinition())
99 IndexCtx.handleDecl(Parm);
101 IndexCtx.handleDecl(Parm);
103 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
104 if (IndexCtx.shouldIndexParametersInDeclarations() ||
105 FD->isThisDeclarationADefinition()) {
106 for (auto PI : FD->parameters()) {
107 IndexCtx.handleDecl(PI);
112 // Index the default parameter value for function definitions.
113 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
114 if (FD->isThisDeclarationADefinition()) {
115 for (const auto *PV : FD->parameters()) {
116 if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() &&
117 !PV->hasUnparsedDefaultArg())
118 IndexCtx.indexBody(PV->getDefaultArg(), D);
125 bool handleObjCMethod(const ObjCMethodDecl *D,
126 const ObjCPropertyDecl *AssociatedProp = nullptr) {
127 SmallVector<SymbolRelation, 4> Relations;
128 SmallVector<const ObjCMethodDecl*, 4> Overriden;
130 D->getOverriddenMethods(Overriden);
131 for(auto overridden: Overriden) {
132 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
136 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
139 // getLocation() returns beginning token of a method declaration, but for
140 // indexing purposes we want to point to the base name.
141 SourceLocation MethodLoc = D->getSelectorStartLoc();
142 if (MethodLoc.isInvalid())
143 MethodLoc = D->getLocation();
145 SourceLocation AttrLoc;
147 // check for (getter=/setter=)
148 if (AssociatedProp) {
149 bool isGetter = !D->param_size();
151 AssociatedProp->getGetterNameLoc():
152 AssociatedProp->getSetterNameLoc();
155 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
156 if (D->isImplicit()) {
157 if (AttrLoc.isValid()) {
160 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
162 } else if (AttrLoc.isValid()) {
163 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
164 D->getDeclContext(), 0);
167 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
168 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
169 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
170 for (const auto *I : D->parameters()) {
171 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
172 hasIBActionAndFirst = false;
175 if (D->isThisDeclarationADefinition()) {
176 const Stmt *Body = D->getBody();
178 IndexCtx.indexBody(Body, D, D);
184 /// Gather the declarations which the given declaration \D overrides in a
185 /// pseudo-override manner.
187 /// Pseudo-overrides occur when a class template specialization declares
188 /// a declaration that has the same name as a similar declaration in the
189 /// non-specialized template.
191 gatherTemplatePseudoOverrides(const NamedDecl *D,
192 SmallVectorImpl<SymbolRelation> &Relations) {
193 if (!IndexCtx.getLangOpts().CPlusPlus)
196 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
199 llvm::PointerUnion<ClassTemplateDecl *,
200 ClassTemplatePartialSpecializationDecl *>
201 Template = CTSD->getSpecializedTemplateOrPartial();
202 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
203 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
204 bool TypeOverride = isa<TypeDecl>(D);
205 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
206 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
207 ND = CTD->getTemplatedDecl();
208 if (ND->isImplicit())
210 // Types can override other types.
212 if (ND->getKind() != D->getKind())
214 } else if (!isa<TypeDecl>(ND))
216 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
217 const auto *DFD = cast<FunctionDecl>(D);
218 // Function overrides are approximated using the number of parameters.
219 if (FD->getStorageClass() != DFD->getStorageClass() ||
220 FD->getNumParams() != DFD->getNumParams())
223 Relations.emplace_back(
224 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
229 bool VisitFunctionDecl(const FunctionDecl *D) {
230 SymbolRoleSet Roles{};
231 SmallVector<SymbolRelation, 4> Relations;
232 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
233 if (CXXMD->isVirtual())
234 Roles |= (unsigned)SymbolRole::Dynamic;
235 for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
236 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
239 gatherTemplatePseudoOverrides(D, Relations);
240 if (const auto *Base = D->getPrimaryTemplate())
242 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
243 Base->getTemplatedDecl()));
245 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
248 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
249 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
250 Ctor->getParent(), Ctor->getDeclContext(),
251 (unsigned)SymbolRole::NameReference);
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);
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 (unsigned)SymbolRole::NameReference);
270 } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
271 IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
272 Guide->getLocation(), Guide,
273 Guide->getDeclContext());
275 // Template specialization arguments.
276 if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
277 D->getTemplateSpecializationArgsAsWritten()) {
278 for (const auto &Arg : TemplateArgInfo->arguments())
279 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
282 if (D->isThisDeclarationADefinition()) {
283 const Stmt *Body = D->getBody();
285 IndexCtx.indexBody(Body, D, D);
291 bool VisitVarDecl(const VarDecl *D) {
292 SmallVector<SymbolRelation, 4> Relations;
293 gatherTemplatePseudoOverrides(D, Relations);
294 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
296 IndexCtx.indexBody(D->getInit(), D);
300 bool VisitDecompositionDecl(const DecompositionDecl *D) {
301 for (const auto *Binding : D->bindings())
302 TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
303 return Base::VisitDecompositionDecl(D);
306 bool VisitFieldDecl(const FieldDecl *D) {
307 SmallVector<SymbolRelation, 4> Relations;
308 gatherTemplatePseudoOverrides(D, Relations);
309 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
312 IndexCtx.indexBody(D->getBitWidth(), D);
313 else if (D->hasInClassInitializer())
314 IndexCtx.indexBody(D->getInClassInitializer(), D);
318 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
319 if (D->getSynthesize()) {
320 // handled in VisitObjCPropertyImplDecl
323 TRY_DECL(D, IndexCtx.handleDecl(D));
328 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
329 TRY_DECL(D, IndexCtx.handleDecl(D));
334 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
335 TRY_DECL(D, IndexCtx.handleDecl(D));
336 IndexCtx.indexBody(D->getInitExpr(), D);
340 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
341 if (!D->isTransparentTag()) {
342 SmallVector<SymbolRelation, 4> Relations;
343 gatherTemplatePseudoOverrides(D, Relations);
344 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
345 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
350 bool VisitTagDecl(const TagDecl *D) {
351 // Non-free standing tags are handled in indexTypeSourceInfo.
352 if (D->isFreeStanding()) {
353 if (D->isThisDeclarationADefinition()) {
354 SmallVector<SymbolRelation, 4> Relations;
355 gatherTemplatePseudoOverrides(D, Relations);
356 IndexCtx.indexTagDecl(D, Relations);
358 SmallVector<SymbolRelation, 1> Relations;
359 gatherTemplatePseudoOverrides(D, Relations);
360 return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
361 Relations, D->getLexicalDeclContext());
367 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
368 const ObjCContainerDecl *ContD,
369 SourceLocation SuperLoc) {
370 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
371 for (ObjCInterfaceDecl::protocol_iterator
372 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
373 SourceLocation Loc = *LI;
374 ObjCProtocolDecl *PD = *I;
375 SymbolRoleSet roles{};
377 roles |= (SymbolRoleSet)SymbolRole::Implicit;
378 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
379 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
384 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
385 if (D->isThisDeclarationADefinition()) {
386 TRY_DECL(D, IndexCtx.handleDecl(D));
387 SourceLocation SuperLoc = D->getSuperClassLoc();
388 if (auto *SuperD = D->getSuperClass()) {
389 bool hasSuperTypedef = false;
390 if (auto *TInfo = D->getSuperClassTInfo()) {
391 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
392 if (auto *TD = TT->getDecl()) {
393 hasSuperTypedef = true;
394 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
399 SymbolRoleSet superRoles{};
401 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
402 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
403 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
405 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
407 TRY_TO(IndexCtx.indexDeclContext(D));
409 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
410 D->getDeclContext(), SymbolRoleSet());
415 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
416 if (D->isThisDeclarationADefinition()) {
417 TRY_DECL(D, IndexCtx.handleDecl(D));
418 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
419 /*SuperLoc=*/SourceLocation()));
420 TRY_TO(IndexCtx.indexDeclContext(D));
422 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
423 D->getDeclContext(), SymbolRoleSet());
428 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
429 const ObjCInterfaceDecl *Class = D->getClassInterface();
433 if (Class->isImplicitInterfaceDecl())
434 IndexCtx.handleDecl(Class);
436 TRY_DECL(D, IndexCtx.handleDecl(D));
438 // Visit implicit @synthesize property implementations first as their
439 // location is reported at the name of the @implementation block. This
440 // serves no purpose other than to simplify the FileCheck-based tests.
441 for (const auto *I : D->property_impls()) {
442 if (I->getLocation().isInvalid())
443 IndexCtx.indexDecl(I);
445 for (const auto *I : D->decls()) {
446 if (!isa<ObjCPropertyImplDecl>(I) ||
447 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
448 IndexCtx.indexDecl(I);
454 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
455 if (!IndexCtx.shouldIndex(D))
457 const ObjCInterfaceDecl *C = D->getClassInterface();
460 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
462 (unsigned)SymbolRole::RelationExtendedBy, D
464 SourceLocation CategoryLoc = D->getCategoryNameLoc();
465 if (!CategoryLoc.isValid())
466 CategoryLoc = D->getLocation();
467 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
468 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
469 /*SuperLoc=*/SourceLocation()));
470 TRY_TO(IndexCtx.indexDeclContext(D));
474 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
475 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
478 const ObjCInterfaceDecl *C = D->getClassInterface();
480 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
482 SourceLocation CategoryLoc = D->getCategoryNameLoc();
483 if (!CategoryLoc.isValid())
484 CategoryLoc = D->getLocation();
485 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
486 IndexCtx.indexDeclContext(D);
490 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
491 // Methods associated with a property, even user-declared ones, are
492 // handled when we handle the property.
493 if (D->isPropertyAccessor())
500 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
501 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
502 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
503 handleObjCMethod(MD, D);
504 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
505 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
506 handleObjCMethod(MD, D);
507 TRY_DECL(D, IndexCtx.handleDecl(D));
508 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
509 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
510 D->getLexicalDeclContext(), false, true);
511 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
515 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
516 ObjCPropertyDecl *PD = D->getPropertyDecl();
517 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
518 SourceLocation Loc = D->getLocation();
519 SymbolRoleSet Roles = 0;
520 SmallVector<SymbolRelation, 1> Relations;
522 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
523 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
524 if (Loc.isInvalid()) {
525 Loc = Container->getLocation();
526 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
528 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
530 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
533 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
534 SymbolRoleSet AccessorMethodRoles =
535 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
536 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
537 if (MD->isPropertyAccessor() &&
538 !hasUserDefined(MD, Container))
539 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
541 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
542 if (MD->isPropertyAccessor() &&
543 !hasUserDefined(MD, Container))
544 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
546 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
547 if (IvarD->getSynthesize()) {
548 // For synthesized ivars, use the location of its name in the
549 // corresponding @synthesize. If there isn't one, use the containing
550 // @implementation's location, rather than the property's location,
551 // otherwise the header file containing the @interface will have different
552 // indexing contents based on whether the @implementation was present or
553 // not in the translation unit.
554 SymbolRoleSet IvarRoles = 0;
555 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
556 if (D->getLocation().isInvalid()) {
557 IvarLoc = Container->getLocation();
558 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
559 } else if (D->getLocation() == IvarLoc) {
560 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
562 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
564 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
565 D->getDeclContext(), SymbolRoleSet());
571 bool VisitNamespaceDecl(const NamespaceDecl *D) {
572 TRY_DECL(D, IndexCtx.handleDecl(D));
573 IndexCtx.indexDeclContext(D);
577 bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
578 TRY_DECL(D, IndexCtx.handleDecl(D));
579 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
580 IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
581 D->getLexicalDeclContext());
585 bool VisitUsingDecl(const UsingDecl *D) {
586 IndexCtx.handleDecl(D);
588 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
589 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
590 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
591 D->getLexicalDeclContext());
592 for (const auto *I : D->shadows())
593 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
594 D->getLexicalDeclContext(), SymbolRoleSet());
598 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
599 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
600 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
602 // NNS for the local 'using namespace' directives is visited by the body
604 if (!D->getParentFunctionOrMethod())
605 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
606 D->getLexicalDeclContext());
608 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
609 D->getLocation(), Parent,
610 D->getLexicalDeclContext(),
614 bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
615 TRY_DECL(D, IndexCtx.handleDecl(D));
616 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
617 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
618 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
619 D->getLexicalDeclContext());
623 bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
624 TRY_DECL(D, IndexCtx.handleDecl(D));
625 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
626 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
627 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
628 D->getLexicalDeclContext());
632 bool VisitClassTemplateSpecializationDecl(const
633 ClassTemplateSpecializationDecl *D) {
634 // FIXME: Notify subsequent callbacks if info comes from implicit
636 llvm::PointerUnion<ClassTemplateDecl *,
637 ClassTemplatePartialSpecializationDecl *>
638 Template = D->getSpecializedTemplateOrPartial();
639 const Decl *SpecializationOf =
640 Template.is<ClassTemplateDecl *>()
641 ? (Decl *)Template.get<ClassTemplateDecl *>()
642 : Template.get<ClassTemplatePartialSpecializationDecl *>();
643 if (!D->isThisDeclarationADefinition())
644 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
645 IndexCtx.indexTagDecl(
646 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
648 if (TypeSourceInfo *TSI = D->getTypeAsWritten())
649 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
650 D->getLexicalDeclContext());
654 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
655 // We want to index the template parameters only once when indexing the
656 // canonical declaration.
659 if (const auto *FD = dyn_cast<FunctionDecl>(D))
660 return FD->getCanonicalDecl() == FD;
661 else if (const auto *TD = dyn_cast<TagDecl>(D))
662 return TD->getCanonicalDecl() == TD;
663 else if (const auto *VD = dyn_cast<VarDecl>(D))
664 return VD->getCanonicalDecl() == VD;
668 bool VisitTemplateDecl(const TemplateDecl *D) {
670 const NamedDecl *Parent = D->getTemplatedDecl();
674 // Index the default values for the template parameters.
675 if (D->getTemplateParameters() &&
676 shouldIndexTemplateParameterDefaultValue(Parent)) {
677 const TemplateParameterList *Params = D->getTemplateParameters();
678 for (const NamedDecl *TP : *Params) {
679 if (IndexCtx.shouldIndexTemplateParameters())
680 IndexCtx.handleDecl(TP);
681 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
682 if (TTP->hasDefaultArgument())
683 IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
684 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
685 if (NTTP->hasDefaultArgument())
686 IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
687 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
688 if (TTPD->hasDefaultArgument())
689 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
690 TP->getLexicalDeclContext());
695 return Visit(Parent);
698 bool VisitFriendDecl(const FriendDecl *D) {
699 if (auto ND = D->getFriendDecl()) {
700 // FIXME: Ignore a class template in a dependent context, these are not
701 // linked properly with their redeclarations, ending up with duplicate
703 // See comment "Friend templates are visible in fairly strange ways." in
704 // SemaTemplate.cpp which precedes code that prevents the friend template
705 // from becoming visible from the enclosing context.
706 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
710 if (auto Ty = D->getFriendType()) {
711 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
716 bool VisitImportDecl(const ImportDecl *D) {
717 return IndexCtx.importedModule(D);
720 bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
721 IndexCtx.indexBody(D->getAssertExpr(),
722 dyn_cast<NamedDecl>(D->getDeclContext()),
723 D->getLexicalDeclContext());
728 } // anonymous namespace
730 bool IndexingContext::indexDecl(const Decl *D) {
731 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
734 if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
737 IndexingDeclVisitor Visitor(*this);
738 bool ShouldContinue = Visitor.Visit(D);
742 if (!Visitor.Handled && isa<DeclContext>(D))
743 return indexDeclContext(cast<DeclContext>(D));
748 bool IndexingContext::indexDeclContext(const DeclContext *DC) {
749 for (const auto *I : DC->decls())
755 bool IndexingContext::indexTopLevelDecl(const Decl *D) {
756 if (D->getLocation().isInvalid())
759 if (isa<ObjCMethodDecl>(D))
760 return true; // Wait for the objc container.
765 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
766 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
767 if (!indexTopLevelDecl(*I))