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/Attr.h"
11 #include "clang/AST/DeclVisitor.h"
12 #include "clang/Index/IndexDataConsumer.h"
14 using namespace clang;
15 using namespace index;
17 #define TRY_DECL(D,CALL_EXPR) \
19 if (!IndexCtx.shouldIndex(D)) return true; \
24 #define TRY_TO(CALL_EXPR) \
32 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
33 IndexingContext &IndexCtx;
36 explicit IndexingDeclVisitor(IndexingContext &indexCtx)
37 : IndexCtx(indexCtx) { }
41 bool VisitDecl(const Decl *D) {
46 void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
47 const NamedDecl *Parent,
48 const DeclContext *DC) {
49 const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();
50 switch (TALoc.getArgument().getKind()) {
51 case TemplateArgument::Expression:
52 IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
54 case TemplateArgument::Type:
55 IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
57 case TemplateArgument::Template:
58 case TemplateArgument::TemplateExpansion:
59 IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
61 if (const TemplateDecl *TD = TALoc.getArgument()
62 .getAsTemplateOrTemplatePattern()
63 .getAsTemplateDecl()) {
64 if (const NamedDecl *TTD = TD->getTemplatedDecl())
65 IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
73 /// Returns true if the given method has been defined explicitly by the
75 static bool hasUserDefined(const ObjCMethodDecl *D,
76 const ObjCImplDecl *Container) {
77 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
78 D->isInstanceMethod());
79 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition() &&
80 !MD->isSynthesizedAccessorStub();
84 void handleDeclarator(const DeclaratorDecl *D,
85 const NamedDecl *Parent = nullptr,
86 bool isIBType = false) {
87 if (!Parent) Parent = D;
89 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
90 Parent->getLexicalDeclContext(),
91 /*isBase=*/false, isIBType);
92 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
93 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
94 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
95 auto *DC = Parm->getDeclContext();
96 if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
97 if (IndexCtx.shouldIndexParametersInDeclarations() ||
98 FD->isThisDeclarationADefinition())
99 IndexCtx.handleDecl(Parm);
100 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
101 if (MD->isThisDeclarationADefinition())
102 IndexCtx.handleDecl(Parm);
104 IndexCtx.handleDecl(Parm);
106 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
107 if (IndexCtx.shouldIndexParametersInDeclarations() ||
108 FD->isThisDeclarationADefinition()) {
109 for (auto PI : FD->parameters()) {
110 IndexCtx.handleDecl(PI);
115 // Index the default parameter value for function definitions.
116 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
117 if (FD->isThisDeclarationADefinition()) {
118 for (const auto *PV : FD->parameters()) {
119 if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() &&
120 !PV->hasUnparsedDefaultArg())
121 IndexCtx.indexBody(PV->getDefaultArg(), D);
128 bool handleObjCMethod(const ObjCMethodDecl *D,
129 const ObjCPropertyDecl *AssociatedProp = nullptr) {
130 SmallVector<SymbolRelation, 4> Relations;
131 SmallVector<const ObjCMethodDecl*, 4> Overriden;
133 D->getOverriddenMethods(Overriden);
134 for(auto overridden: Overriden) {
135 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
139 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
142 // getLocation() returns beginning token of a method declaration, but for
143 // indexing purposes we want to point to the base name.
144 SourceLocation MethodLoc = D->getSelectorStartLoc();
145 if (MethodLoc.isInvalid())
146 MethodLoc = D->getLocation();
148 SourceLocation AttrLoc;
150 // check for (getter=/setter=)
151 if (AssociatedProp) {
152 bool isGetter = !D->param_size();
154 AssociatedProp->getGetterNameLoc():
155 AssociatedProp->getSetterNameLoc();
158 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
159 if (D->isImplicit()) {
160 if (AttrLoc.isValid()) {
163 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
165 } else if (AttrLoc.isValid()) {
166 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
167 D->getDeclContext(), 0);
170 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
171 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
172 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
173 for (const auto *I : D->parameters()) {
174 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
175 hasIBActionAndFirst = false;
178 if (D->isThisDeclarationADefinition()) {
179 const Stmt *Body = D->getBody();
181 IndexCtx.indexBody(Body, D, D);
187 /// Gather the declarations which the given declaration \D overrides in a
188 /// pseudo-override manner.
190 /// Pseudo-overrides occur when a class template specialization declares
191 /// a declaration that has the same name as a similar declaration in the
192 /// non-specialized template.
194 gatherTemplatePseudoOverrides(const NamedDecl *D,
195 SmallVectorImpl<SymbolRelation> &Relations) {
196 if (!IndexCtx.getLangOpts().CPlusPlus)
199 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
202 llvm::PointerUnion<ClassTemplateDecl *,
203 ClassTemplatePartialSpecializationDecl *>
204 Template = CTSD->getSpecializedTemplateOrPartial();
205 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
206 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
207 bool TypeOverride = isa<TypeDecl>(D);
208 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
209 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
210 ND = CTD->getTemplatedDecl();
211 if (ND->isImplicit())
213 // Types can override other types.
215 if (ND->getKind() != D->getKind())
217 } else if (!isa<TypeDecl>(ND))
219 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
220 const auto *DFD = cast<FunctionDecl>(D);
221 // Function overrides are approximated using the number of parameters.
222 if (FD->getStorageClass() != DFD->getStorageClass() ||
223 FD->getNumParams() != DFD->getNumParams())
226 Relations.emplace_back(
227 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
232 bool VisitFunctionDecl(const FunctionDecl *D) {
233 SymbolRoleSet Roles{};
234 SmallVector<SymbolRelation, 4> Relations;
235 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
236 if (CXXMD->isVirtual())
237 Roles |= (unsigned)SymbolRole::Dynamic;
238 for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
239 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
242 gatherTemplatePseudoOverrides(D, Relations);
243 if (const auto *Base = D->getPrimaryTemplate())
245 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
246 Base->getTemplatedDecl()));
248 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
251 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
252 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
253 Ctor->getParent(), Ctor->getDeclContext(),
254 (unsigned)SymbolRole::NameReference);
256 // Constructor initializers.
257 for (const auto *Init : Ctor->inits()) {
258 if (Init->isWritten()) {
259 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
260 if (const FieldDecl *Member = Init->getAnyMember())
261 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
262 (unsigned)SymbolRole::Write);
263 IndexCtx.indexBody(Init->getInit(), D, D);
266 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
267 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
268 IndexCtx.handleReference(Dtor->getParent(),
269 TypeNameInfo->getTypeLoc().getBeginLoc(),
270 Dtor->getParent(), Dtor->getDeclContext(),
271 (unsigned)SymbolRole::NameReference);
273 } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
274 IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
275 Guide->getLocation(), Guide,
276 Guide->getDeclContext());
278 // Template specialization arguments.
279 if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
280 D->getTemplateSpecializationArgsAsWritten()) {
281 for (const auto &Arg : TemplateArgInfo->arguments())
282 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
285 if (D->isThisDeclarationADefinition()) {
286 const Stmt *Body = D->getBody();
288 IndexCtx.indexBody(Body, D, D);
294 bool VisitVarDecl(const VarDecl *D) {
295 SmallVector<SymbolRelation, 4> Relations;
296 gatherTemplatePseudoOverrides(D, Relations);
297 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
299 IndexCtx.indexBody(D->getInit(), D);
303 bool VisitDecompositionDecl(const DecompositionDecl *D) {
304 for (const auto *Binding : D->bindings())
305 TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
306 return Base::VisitDecompositionDecl(D);
309 bool VisitFieldDecl(const FieldDecl *D) {
310 SmallVector<SymbolRelation, 4> Relations;
311 gatherTemplatePseudoOverrides(D, Relations);
312 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
315 IndexCtx.indexBody(D->getBitWidth(), D);
316 else if (D->hasInClassInitializer())
317 IndexCtx.indexBody(D->getInClassInitializer(), D);
321 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
322 if (D->getSynthesize()) {
323 // handled in VisitObjCPropertyImplDecl
326 TRY_DECL(D, IndexCtx.handleDecl(D));
331 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
332 TRY_DECL(D, IndexCtx.handleDecl(D));
337 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
338 TRY_DECL(D, IndexCtx.handleDecl(D));
339 IndexCtx.indexBody(D->getInitExpr(), D);
343 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
344 if (!D->isTransparentTag()) {
345 SmallVector<SymbolRelation, 4> Relations;
346 gatherTemplatePseudoOverrides(D, Relations);
347 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
348 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
353 bool VisitTagDecl(const TagDecl *D) {
354 // Non-free standing tags are handled in indexTypeSourceInfo.
355 if (D->isFreeStanding()) {
356 if (D->isThisDeclarationADefinition()) {
357 SmallVector<SymbolRelation, 4> Relations;
358 gatherTemplatePseudoOverrides(D, Relations);
359 IndexCtx.indexTagDecl(D, Relations);
361 SmallVector<SymbolRelation, 1> Relations;
362 gatherTemplatePseudoOverrides(D, Relations);
363 return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
364 Relations, D->getLexicalDeclContext());
370 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
371 const ObjCContainerDecl *ContD,
372 SourceLocation SuperLoc) {
373 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
374 for (ObjCInterfaceDecl::protocol_iterator
375 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
376 SourceLocation Loc = *LI;
377 ObjCProtocolDecl *PD = *I;
378 SymbolRoleSet roles{};
380 roles |= (SymbolRoleSet)SymbolRole::Implicit;
381 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
382 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
387 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
388 if (D->isThisDeclarationADefinition()) {
389 TRY_DECL(D, IndexCtx.handleDecl(D));
390 SourceLocation SuperLoc = D->getSuperClassLoc();
391 if (auto *SuperD = D->getSuperClass()) {
392 bool hasSuperTypedef = false;
393 if (auto *TInfo = D->getSuperClassTInfo()) {
394 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
395 if (auto *TD = TT->getDecl()) {
396 hasSuperTypedef = true;
397 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
402 SymbolRoleSet superRoles{};
404 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
405 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
406 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
408 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
410 TRY_TO(IndexCtx.indexDeclContext(D));
412 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
413 D->getDeclContext(), SymbolRoleSet());
418 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
419 if (D->isThisDeclarationADefinition()) {
420 TRY_DECL(D, IndexCtx.handleDecl(D));
421 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
422 /*SuperLoc=*/SourceLocation()));
423 TRY_TO(IndexCtx.indexDeclContext(D));
425 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
426 D->getDeclContext(), SymbolRoleSet());
431 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
432 const ObjCInterfaceDecl *Class = D->getClassInterface();
436 if (Class->isImplicitInterfaceDecl())
437 IndexCtx.handleDecl(Class);
439 TRY_DECL(D, IndexCtx.handleDecl(D));
441 // Visit implicit @synthesize property implementations first as their
442 // location is reported at the name of the @implementation block. This
443 // serves no purpose other than to simplify the FileCheck-based tests.
444 for (const auto *I : D->property_impls()) {
445 if (I->getLocation().isInvalid())
446 IndexCtx.indexDecl(I);
448 for (const auto *I : D->decls()) {
449 if (!isa<ObjCPropertyImplDecl>(I) ||
450 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
451 IndexCtx.indexDecl(I);
457 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
458 if (!IndexCtx.shouldIndex(D))
460 const ObjCInterfaceDecl *C = D->getClassInterface();
463 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
465 (unsigned)SymbolRole::RelationExtendedBy, D
467 SourceLocation CategoryLoc = D->getCategoryNameLoc();
468 if (!CategoryLoc.isValid())
469 CategoryLoc = D->getLocation();
470 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
471 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
472 /*SuperLoc=*/SourceLocation()));
473 TRY_TO(IndexCtx.indexDeclContext(D));
477 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
478 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
481 const ObjCInterfaceDecl *C = D->getClassInterface();
483 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
485 SourceLocation CategoryLoc = D->getCategoryNameLoc();
486 if (!CategoryLoc.isValid())
487 CategoryLoc = D->getLocation();
488 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
489 IndexCtx.indexDeclContext(D);
493 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
494 // Methods associated with a property, even user-declared ones, are
495 // handled when we handle the property.
496 if (D->isPropertyAccessor())
503 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
504 if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
505 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
506 handleObjCMethod(MD, D);
507 if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
508 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
509 handleObjCMethod(MD, D);
510 TRY_DECL(D, IndexCtx.handleDecl(D));
511 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
512 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
513 D->getLexicalDeclContext(), false, true);
514 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
518 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
519 ObjCPropertyDecl *PD = D->getPropertyDecl();
520 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
521 SourceLocation Loc = D->getLocation();
522 SymbolRoleSet Roles = 0;
523 SmallVector<SymbolRelation, 1> Relations;
525 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
526 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
527 if (Loc.isInvalid()) {
528 Loc = Container->getLocation();
529 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
531 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
533 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
536 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
537 SymbolRoleSet AccessorMethodRoles =
538 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
539 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
540 if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
541 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
543 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
544 if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
545 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
547 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
548 if (IvarD->getSynthesize()) {
549 // For synthesized ivars, use the location of its name in the
550 // corresponding @synthesize. If there isn't one, use the containing
551 // @implementation's location, rather than the property's location,
552 // otherwise the header file containing the @interface will have different
553 // indexing contents based on whether the @implementation was present or
554 // not in the translation unit.
555 SymbolRoleSet IvarRoles = 0;
556 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
557 if (D->getLocation().isInvalid()) {
558 IvarLoc = Container->getLocation();
559 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
560 } else if (D->getLocation() == IvarLoc) {
561 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
563 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
565 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
566 D->getDeclContext(), SymbolRoleSet());
572 bool VisitNamespaceDecl(const NamespaceDecl *D) {
573 TRY_DECL(D, IndexCtx.handleDecl(D));
574 IndexCtx.indexDeclContext(D);
578 bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
579 TRY_DECL(D, IndexCtx.handleDecl(D));
580 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
581 IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
582 D->getLexicalDeclContext());
586 bool VisitUsingDecl(const UsingDecl *D) {
587 IndexCtx.handleDecl(D);
589 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
590 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
591 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
592 D->getLexicalDeclContext());
593 for (const auto *I : D->shadows())
594 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
595 D->getLexicalDeclContext(), SymbolRoleSet());
599 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
600 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
601 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
603 // NNS for the local 'using namespace' directives is visited by the body
605 if (!D->getParentFunctionOrMethod())
606 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
607 D->getLexicalDeclContext());
609 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
610 D->getLocation(), Parent,
611 D->getLexicalDeclContext(),
615 bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
616 TRY_DECL(D, IndexCtx.handleDecl(D));
617 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
618 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
619 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
620 D->getLexicalDeclContext());
624 bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
625 TRY_DECL(D, IndexCtx.handleDecl(D));
626 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
627 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
628 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
629 D->getLexicalDeclContext());
633 bool VisitClassTemplateSpecializationDecl(const
634 ClassTemplateSpecializationDecl *D) {
635 // FIXME: Notify subsequent callbacks if info comes from implicit
637 llvm::PointerUnion<ClassTemplateDecl *,
638 ClassTemplatePartialSpecializationDecl *>
639 Template = D->getSpecializedTemplateOrPartial();
640 const Decl *SpecializationOf =
641 Template.is<ClassTemplateDecl *>()
642 ? (Decl *)Template.get<ClassTemplateDecl *>()
643 : Template.get<ClassTemplatePartialSpecializationDecl *>();
644 if (!D->isThisDeclarationADefinition())
645 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
646 IndexCtx.indexTagDecl(
647 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
649 if (TypeSourceInfo *TSI = D->getTypeAsWritten())
650 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
651 D->getLexicalDeclContext());
655 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
656 // We want to index the template parameters only once when indexing the
657 // canonical declaration.
660 if (const auto *FD = dyn_cast<FunctionDecl>(D))
661 return FD->getCanonicalDecl() == FD;
662 else if (const auto *TD = dyn_cast<TagDecl>(D))
663 return TD->getCanonicalDecl() == TD;
664 else if (const auto *VD = dyn_cast<VarDecl>(D))
665 return VD->getCanonicalDecl() == VD;
669 bool VisitTemplateDecl(const TemplateDecl *D) {
671 const NamedDecl *Parent = D->getTemplatedDecl();
675 // Index the default values for the template parameters.
676 if (D->getTemplateParameters() &&
677 shouldIndexTemplateParameterDefaultValue(Parent)) {
678 const TemplateParameterList *Params = D->getTemplateParameters();
679 for (const NamedDecl *TP : *Params) {
680 if (IndexCtx.shouldIndexTemplateParameters())
681 IndexCtx.handleDecl(TP);
682 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
683 if (TTP->hasDefaultArgument())
684 IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
685 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
686 if (NTTP->hasDefaultArgument())
687 IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
688 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
689 if (TTPD->hasDefaultArgument())
690 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
691 TP->getLexicalDeclContext());
696 return Visit(Parent);
699 bool VisitFriendDecl(const FriendDecl *D) {
700 if (auto ND = D->getFriendDecl()) {
701 // FIXME: Ignore a class template in a dependent context, these are not
702 // linked properly with their redeclarations, ending up with duplicate
704 // See comment "Friend templates are visible in fairly strange ways." in
705 // SemaTemplate.cpp which precedes code that prevents the friend template
706 // from becoming visible from the enclosing context.
707 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
711 if (auto Ty = D->getFriendType()) {
712 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
717 bool VisitImportDecl(const ImportDecl *D) {
718 return IndexCtx.importedModule(D);
721 bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
722 IndexCtx.indexBody(D->getAssertExpr(),
723 dyn_cast<NamedDecl>(D->getDeclContext()),
724 D->getLexicalDeclContext());
729 } // anonymous namespace
731 bool IndexingContext::indexDecl(const Decl *D) {
732 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
735 if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
738 IndexingDeclVisitor Visitor(*this);
739 bool ShouldContinue = Visitor.Visit(D);
743 if (!Visitor.Handled && isa<DeclContext>(D))
744 return indexDeclContext(cast<DeclContext>(D));
749 bool IndexingContext::indexDeclContext(const DeclContext *DC) {
750 for (const auto *I : DC->decls())
756 bool IndexingContext::indexTopLevelDecl(const Decl *D) {
757 if (D->getLocation().isInvalid())
760 if (isa<ObjCMethodDecl>(D))
761 return true; // Wait for the objc container.
766 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
767 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
768 if (!indexTopLevelDecl(*I))