clang 20.0.0git
IndexDecl.cpp
Go to the documentation of this file.
1//===- IndexDecl.cpp - Indexing declarations ------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "IndexingContext.h"
11#include "clang/AST/Attr.h"
12#include "clang/AST/Decl.h"
17
18using namespace clang;
19using namespace index;
20
21#define TRY_DECL(D,CALL_EXPR) \
22 do { \
23 if (!IndexCtx.shouldIndex(D)) return true; \
24 if (!CALL_EXPR) \
25 return false; \
26 } while (0)
27
28#define TRY_TO(CALL_EXPR) \
29 do { \
30 if (!CALL_EXPR) \
31 return false; \
32 } while (0)
33
34namespace {
35
36class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
37 IndexingContext &IndexCtx;
38
39public:
40 explicit IndexingDeclVisitor(IndexingContext &indexCtx)
41 : IndexCtx(indexCtx) { }
42
43 bool Handled = true;
44
45 bool VisitDecl(const Decl *D) {
46 Handled = false;
47 return true;
48 }
49
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()) {
56 IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
57 break;
59 IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
60 break;
64 Parent, DC);
65 if (const TemplateDecl *TD = TALoc.getArgument()
68 if (const NamedDecl *TTD = TD->getTemplatedDecl())
69 IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
70 }
71 break;
72 default:
73 break;
74 }
75 }
76
77 /// Returns true if the given method has been defined explicitly by the
78 /// user.
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() &&
85 }
86
87
88 void handleDeclarator(const DeclaratorDecl *D,
89 const NamedDecl *Parent = nullptr,
90 bool isIBType = false) {
91 if (!Parent) Parent = D;
92
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);
102 };
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)) {
108 FD->isThisDeclarationADefinition())
109 IndexCtx.handleDecl(Parm);
110 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
111 if (MD->isThisDeclarationADefinition())
112 IndexCtx.handleDecl(Parm);
113 } else {
114 IndexCtx.handleDecl(Parm);
115 }
116 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
118 FD->isThisDeclarationADefinition()) {
119 for (const auto *PI : FD->parameters()) {
120 IndexDefaultParmeterArgument(PI, D);
121 IndexCtx.handleDecl(PI);
122 }
123 }
124 }
125 } else {
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);
131 }
132 }
133 }
134 }
135 if (auto *C = D->getTrailingRequiresClause())
136 IndexCtx.indexBody(C, Parent);
137 }
138
139 bool handleObjCMethod(const ObjCMethodDecl *D,
140 const ObjCPropertyDecl *AssociatedProp = nullptr) {
143
144 D->getOverriddenMethods(Overriden);
145 for(auto overridden: Overriden) {
146 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
147 overridden);
148 }
149 if (AssociatedProp)
150 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
151 AssociatedProp);
152
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();
158
159 SourceLocation AttrLoc;
160
161 // check for (getter=/setter=)
162 if (AssociatedProp) {
163 bool isGetter = !D->param_size();
164 AttrLoc = isGetter ?
165 AssociatedProp->getGetterNameLoc():
166 AssociatedProp->getSetterNameLoc();
167 }
168
169 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
170 if (D->isImplicit()) {
171 if (AttrLoc.isValid()) {
172 MethodLoc = AttrLoc;
173 } else {
174 Roles |= (SymbolRoleSet)SymbolRole::Implicit;
175 }
176 } else if (AttrLoc.isValid()) {
177 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
178 D->getDeclContext(), 0);
179 }
180
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;
187 }
188
189 if (D->isThisDeclarationADefinition()) {
190 const Stmt *Body = D->getBody();
191 if (Body) {
192 IndexCtx.indexBody(Body, D, D);
193 }
194 }
195 return true;
196 }
197
198 /// Gather the declarations which the given declaration \D overrides in a
199 /// pseudo-override manner.
200 ///
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.
204 void
205 gatherTemplatePseudoOverrides(const NamedDecl *D,
207 if (!IndexCtx.getLangOpts().CPlusPlus)
208 return;
209 const auto *CTSD =
210 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
211 if (!CTSD)
212 return;
213 llvm::PointerUnion<ClassTemplateDecl *,
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())
223 continue;
224 // Types can override other types.
225 if (!TypeOverride) {
226 if (ND->getKind() != D->getKind())
227 continue;
228 } else if (!isa<TypeDecl>(ND))
229 continue;
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())
235 continue;
236 }
237 Relations.emplace_back(
238 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
239 }
240 }
241 }
242
243 bool VisitFunctionDecl(const FunctionDecl *D) {
244 SymbolRoleSet Roles{};
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);
251 }
252 }
253 gatherTemplatePseudoOverrides(D, Relations);
254 if (const auto *Base = D->getPrimaryTemplate())
255 Relations.push_back(
256 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
257 Base->getTemplatedDecl()));
258
259 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
260 handleDeclarator(D);
261
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);
266
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);
275 }
276 }
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);
283 }
284 } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
285 IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
286 Guide->getLocation(), Guide,
287 Guide->getDeclContext());
288 }
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());
294 }
295
296 if (D->isThisDeclarationADefinition()) {
297 const Stmt *Body = D->getBody();
298 if (Body) {
299 IndexCtx.indexBody(Body, D, D);
300 }
301 }
302 return true;
303 }
304
305 bool VisitVarDecl(const VarDecl *D) {
307 gatherTemplatePseudoOverrides(D, Relations);
308 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
309 handleDeclarator(D);
310 IndexCtx.indexBody(D->getInit(), D);
311 return true;
312 }
313
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);
318 }
319
320 bool VisitFieldDecl(const FieldDecl *D) {
322 gatherTemplatePseudoOverrides(D, Relations);
323 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
324 handleDeclarator(D);
325 if (D->isBitField())
326 IndexCtx.indexBody(D->getBitWidth(), D);
327 else if (D->hasInClassInitializer())
328 IndexCtx.indexBody(D->getInClassInitializer(), D);
329 return true;
330 }
331
332 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
333 if (D->getSynthesize()) {
334 // handled in VisitObjCPropertyImplDecl
335 return true;
336 }
337 TRY_DECL(D, IndexCtx.handleDecl(D));
338 handleDeclarator(D);
339 return true;
340 }
341
342 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
343 TRY_DECL(D, IndexCtx.handleDecl(D));
344 handleDeclarator(D);
345 return true;
346 }
347
348 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
349 TRY_DECL(D, IndexCtx.handleDecl(D));
350 IndexCtx.indexBody(D->getInitExpr(), D);
351 return true;
352 }
353
354 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
355 if (!D->isTransparentTag()) {
357 gatherTemplatePseudoOverrides(D, Relations);
358 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
359 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
360 }
361 return true;
362 }
363
364 bool VisitTagDecl(const TagDecl *D) {
365 // Non-free standing tags are handled in indexTypeSourceInfo.
366 if (D->isFreeStanding()) {
367 if (D->isThisDeclarationADefinition()) {
369 gatherTemplatePseudoOverrides(D, Relations);
370 IndexCtx.indexTagDecl(D, Relations);
371 } else {
373 gatherTemplatePseudoOverrides(D, Relations);
374 return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
375 Relations, D->getLexicalDeclContext());
376 }
377 }
378 return true;
379 }
380
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);
387 return true;
388 }
389
390 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
391 const ObjCContainerDecl *ContD,
392 SourceLocation SuperLoc) {
395 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
396 SourceLocation Loc = *LI;
397 ObjCProtocolDecl *PD = *I;
398 SymbolRoleSet roles{};
399 if (Loc == SuperLoc)
400 roles |= (SymbolRoleSet)SymbolRole::Implicit;
401 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
402 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
403 }
404 return true;
405 }
406
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,
418 SymbolRoleSet()));
419 }
420 }
421 }
422 SymbolRoleSet superRoles{};
423 if (hasSuperTypedef)
424 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
425 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
426 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
427 }
428 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
429 SuperLoc));
430 TRY_TO(IndexCtx.indexDeclContext(D));
431 } else {
432 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
434 }
435 return true;
436 }
437
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));
444 } else {
445 return IndexCtx.handleReference(D, D->getLocation(), nullptr,
447 }
448 return true;
449 }
450
451 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
452 const ObjCInterfaceDecl *Class = D->getClassInterface();
453 if (!Class)
454 return true;
455
456 if (Class->isImplicitInterfaceDecl())
457 IndexCtx.handleDecl(Class);
458
459 TRY_DECL(D, IndexCtx.handleDecl(D));
460
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);
467 }
468 for (const auto *I : D->decls()) {
469 if (!isa<ObjCPropertyImplDecl>(I) ||
470 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
471 IndexCtx.indexDecl(I);
472 }
473
474 return true;
475 }
476
477 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
478 if (!IndexCtx.shouldIndex(D))
479 return true;
480 const ObjCInterfaceDecl *C = D->getClassInterface();
481 if (!C)
482 return true;
485 (unsigned)SymbolRole::RelationExtendedBy, D
486 }));
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));
494 return true;
495 }
496
497 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
498 const ObjCCategoryDecl *Cat = D->getCategoryDecl();
499 if (!Cat)
500 return true;
501 const ObjCInterfaceDecl *C = D->getClassInterface();
502 if (C)
503 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
504 SymbolRoleSet()));
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);
510 return true;
511 }
512
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())
517 return true;
518
519 handleObjCMethod(D);
520 return true;
521 }
522
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);
535 return true;
536 }
537
538 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
539 ObjCPropertyDecl *PD = D->getPropertyDecl();
540 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
542 SymbolRoleSet Roles = 0;
544
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;
550 }
551 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
552
553 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
554 return true;
555
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);
562 }
563 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
564 if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
565 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
566 }
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;
582 }
583 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
584 } else {
585 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
587 }
588 }
589 return true;
590 }
591
592 bool VisitNamespaceDecl(const NamespaceDecl *D) {
593 TRY_DECL(D, IndexCtx.handleDecl(D));
594 IndexCtx.indexDeclContext(D);
595 return true;
596 }
597
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,
603 return true;
604 }
605
606 bool VisitUsingDecl(const UsingDecl *D) {
607 IndexCtx.handleDecl(D);
608
610 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
611 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
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()))
618 continue;
619
620 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
622 }
623 return true;
624 }
625
626 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
628 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
629
630 // NNS for the local 'using namespace' directives is visited by the body
631 // visitor.
633 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
635
636 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
637 D->getLocation(), Parent,
639 SymbolRoleSet());
640 }
641
642 bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
643 TRY_DECL(D, IndexCtx.handleDecl(D));
645 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
646 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
648 return true;
649 }
650
651 bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
652 TRY_DECL(D, IndexCtx.handleDecl(D));
654 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
655 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
657 return true;
658 }
659
660 bool VisitClassTemplateSpecializationDecl(const
662 // FIXME: Notify subsequent callbacks if info comes from implicit
663 // instantiation.
664 llvm::PointerUnion<ClassTemplateDecl *,
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),
675 SpecializationOf));
676 // Template specialization arguments.
677 if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
678 D->getTemplateArgsAsWritten()) {
679 for (const auto &Arg : TemplateArgInfo->arguments())
680 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
681 }
682 return true;
683 }
684
685 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
686 // We want to index the template parameters only once when indexing the
687 // canonical declaration.
688 if (!D)
689 return false;
690 if (const auto *FD = dyn_cast<FunctionDecl>(D))
691 return FD->getCanonicalDecl() == FD;
692 else if (const auto *TD = dyn_cast<TagDecl>(D))
693 return TD->getCanonicalDecl() == TD;
694 else if (const auto *VD = dyn_cast<VarDecl>(D))
695 return VD->getCanonicalDecl() == VD;
696 return true;
697 }
698
699 void indexTemplateParameters(TemplateParameterList *Params,
700 const NamedDecl *Parent) {
701 for (const NamedDecl *TP : *Params) {
702 if (IndexCtx.shouldIndexTemplateParameters())
703 IndexCtx.handleDecl(TP);
704 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
705 if (TTP->hasDefaultArgument())
706 handleTemplateArgumentLoc(TTP->getDefaultArgument(), Parent,
707 TP->getLexicalDeclContext());
708 if (auto *C = TTP->getTypeConstraint())
709 IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
710 Parent, TTP->getLexicalDeclContext());
711 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
712 IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent);
713 if (NTTP->hasDefaultArgument())
714 handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent,
715 TP->getLexicalDeclContext());
716 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
717 if (TTPD->hasDefaultArgument())
718 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
719 TP->getLexicalDeclContext());
720 }
721 }
722 if (auto *R = Params->getRequiresClause())
723 IndexCtx.indexBody(R, Parent);
724 }
725
726 bool VisitTemplateDecl(const TemplateDecl *D) {
727 const NamedDecl *Parent = D->getTemplatedDecl();
728 if (!Parent)
729 return true;
730
731 // Index the default values for the template parameters.
732 auto *Params = D->getTemplateParameters();
733 if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) {
734 indexTemplateParameters(Params, Parent);
735 }
736
737 return Visit(Parent);
738 }
739
740 bool VisitConceptDecl(const ConceptDecl *D) {
741 if (auto *Params = D->getTemplateParameters())
742 indexTemplateParameters(Params, D);
743 if (auto *E = D->getConstraintExpr())
744 IndexCtx.indexBody(E, D);
745 return IndexCtx.handleDecl(D);
746 }
747
748 bool VisitFriendDecl(const FriendDecl *D) {
749 if (auto ND = D->getFriendDecl()) {
750 // FIXME: Ignore a class template in a dependent context, these are not
751 // linked properly with their redeclarations, ending up with duplicate
752 // USRs.
753 // See comment "Friend templates are visible in fairly strange ways." in
754 // SemaTemplate.cpp which precedes code that prevents the friend template
755 // from becoming visible from the enclosing context.
756 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
757 return true;
758 return Visit(ND);
759 }
760 if (auto Ty = D->getFriendType()) {
761 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
762 }
763 return true;
764 }
765
766 bool VisitImportDecl(const ImportDecl *D) {
767 return IndexCtx.importedModule(D);
768 }
769
770 bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
771 IndexCtx.indexBody(D->getAssertExpr(),
772 dyn_cast<NamedDecl>(D->getDeclContext()),
774 return true;
775 }
776};
777
778} // anonymous namespace
779
781 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
782 return true;
783
785 return true;
786
787 IndexingDeclVisitor Visitor(*this);
788 bool ShouldContinue = Visitor.Visit(D);
789 if (!ShouldContinue)
790 return false;
791
792 if (!Visitor.Handled && isa<DeclContext>(D))
793 return indexDeclContext(cast<DeclContext>(D));
794
795 return true;
796}
797
799 for (const auto *I : DC->decls())
800 if (!indexDecl(I))
801 return false;
802 return true;
803}
804
806 if (!D || D->getLocation().isInvalid())
807 return true;
808
809 if (isa<ObjCMethodDecl>(D))
810 return true; // Wait for the objc container.
811
812 if (IndexOpts.ShouldTraverseDecl && !IndexOpts.ShouldTraverseDecl(D))
813 return true; // skip
814
815 return indexDecl(D);
816}
817
819 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
820 if (!indexTopLevelDecl(*I))
821 return false;
822 return true;
823}
This file provides AST data structures related to concepts.
NodeId Parent
Definition: ASTDiff.cpp:191
const Decl * D
Expr * E
Defines the C++ template declaration subclasses.
#define TRY_DECL(D, CALL_EXPR)
Definition: IndexDecl.cpp:21
#define TRY_TO(CALL_EXPR)
SourceLocation Loc
Definition: SemaObjC.cpp:759
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2539
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2803
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2064
overridden_method_range overridden_methods() const
Definition: DeclCXX.cpp:2572
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
Declaration of a class template.
Represents a class template specialization, which refers to a class template with a given set of temp...
llvm::PointerUnion< ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl * > getSpecializedTemplateOrPartial() const
Retrieve the class template or class template partial specialization which was specialized by this.
Declaration of a C++20 concept.
A simple visitor class that helps create declaration visitors.
Definition: DeclVisitor.h:74
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1333
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Definition: DeclBase.cpp:1852
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
Definition: DeclBase.cpp:1988
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2350
iterator begin()
Definition: DeclGroup.h:99
iterator end()
Definition: DeclGroup.h:105
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
const DeclContext * getParentFunctionOrMethod(bool LexicalParent=false) const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext,...
Definition: DeclBase.cpp:317
T * getAttr() const
Definition: DeclBase.h:580
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:600
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:1077
SourceLocation getLocation() const
Definition: DeclBase.h:446
DeclContext * getDeclContext()
Definition: DeclBase.h:455
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition: DeclBase.h:908
bool hasAttr() const
Definition: DeclBase.h:584
Kind getKind() const
Definition: DeclBase.h:449
Represents a ValueDecl that came out of a declarator.
Definition: Decl.h:731
A decomposition declaration.
Definition: DeclCXX.h:4170
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:3274
Represents an enum.
Definition: Decl.h:3844
TypeSourceInfo * getIntegerTypeSourceInfo() const
Return the type source info for the underlying integer type, if no type source info exists,...
Definition: Decl.h:4020
Represents a member of a struct/union/class.
Definition: Decl.h:3030
FriendDecl - Represents the declaration of a friend entity, which can be a function,...
Definition: DeclFriend.h:54
Represents a function declaration or definition.
Definition: Decl.h:1932
Describes a module import declaration, which makes the contents of the named module visible in the cu...
Definition: Decl.h:4783
An instance of this class represents the declaration of a property member.
Definition: DeclCXX.h:4239
This represents a decl that may have a name.
Definition: Decl.h:249
Represents a C++ namespace alias.
Definition: DeclCXX.h:3124
Represent a C++ namespace.
Definition: Decl.h:547
ObjCCategoryDecl - Represents a category declaration.
Definition: DeclObjC.h:2328
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.
Definition: DeclObjC.h:2544
ObjCContainerDecl - Represents a container for method declarations.
Definition: DeclObjC.h:947
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Definition: DeclObjC.h:2596
Represents an ObjC class declaration.
Definition: DeclObjC.h:1153
ObjCProtocolList::iterator protocol_iterator
Definition: DeclObjC.h:1355
ObjCIvarDecl - Represents an ObjC instance variable.
Definition: DeclObjC.h:1951
iterator end() const
Definition: DeclObjC.h:91
iterator begin() const
Definition: DeclObjC.h:90
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:140
bool isSynthesizedAccessorStub() const
Definition: DeclObjC.h:444
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
Definition: DeclObjC.h:534
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:730
ObjCMethodDecl * getGetterMethodDecl() const
Definition: DeclObjC.h:900
ObjCMethodDecl * getSetterMethodDecl() const
Definition: DeclObjC.h:903
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
Definition: DeclObjC.h:2804
Represents an Objective-C protocol declaration.
Definition: DeclObjC.h:2083
A list of Objective-C protocols, along with the source locations at which they were referenced.
Definition: DeclObjC.h:101
loc_iterator loc_begin() const
Definition: DeclObjC.h:111
Represents a parameter to a function.
Definition: Decl.h:1722
bool hasUnparsedDefaultArg() const
Determines whether this parameter has a default argument that has not yet been parsed.
Definition: Decl.h:1851
bool hasUninstantiatedDefaultArg() const
Definition: Decl.h:1855
Expr * getDefaultArg()
Definition: Decl.cpp:2956
bool hasDefaultArg() const
Determines whether this parameter has a default argument, either parsed or not.
Definition: Decl.cpp:3004
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Represents a C++11 static_assert declaration.
Definition: DeclCXX.h:4062
Stmt - This represents one statement.
Definition: Stmt.h:84
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3561
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:524
TemplateArgumentLocInfo getLocInfo() const
Definition: TemplateBase.h:576
const TemplateArgument & getArgument() const
Definition: TemplateBase.h:574
SourceLocation getTemplateNameLoc() const
Definition: TemplateBase.h:616
NestedNameSpecifierLoc getTemplateQualifierLoc() const
Definition: TemplateBase.h:609
@ Template
The template argument is a template name that was provided for a template template parameter.
Definition: TemplateBase.h:93
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
Definition: TemplateBase.h:97
@ Type
The template argument is a type.
Definition: TemplateBase.h:70
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
Definition: TemplateBase.h:103
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:295
TemplateName getAsTemplateOrTemplatePattern() const
Retrieve the template argument as a template name; if the argument is a pack expansion,...
Definition: TemplateBase.h:350
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:394
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known.
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:73
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3409
Represents a dependent using declaration which was marked with typename.
Definition: DeclCXX.h:3963
Represents a dependent using declaration which was not marked with typename.
Definition: DeclCXX.h:3866
Represents a C++ using-declaration.
Definition: DeclCXX.h:3516
Represents C++ using-directive.
Definition: DeclCXX.h:3019
Represents a variable declaration or definition.
Definition: Decl.h:879
RetTy Visit(PTR(Decl) D)
Definition: DeclVisitor.h:37
RetTy VisitDecl(PTR(Decl) D)
Definition: DeclVisitor.h:53
bool shouldIndexImplicitInstantiation() const
bool importedModule(const ImportDecl *ImportD)
bool shouldIndex(const Decl *D)
bool indexDeclContext(const DeclContext *DC)
Definition: IndexDecl.cpp:798
bool shouldIndexFunctionLocalSymbols() const
void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const NamedDecl *Parent, const DeclContext *DC=nullptr)
bool indexTopLevelDecl(const Decl *D)
Definition: IndexDecl.cpp:805
bool handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, SymbolRoleSet Roles=SymbolRoleSet(), ArrayRef< SymbolRelation > Relations=std::nullopt, const Expr *RefE=nullptr)
void indexBody(const Stmt *S, const NamedDecl *Parent, const DeclContext *DC=nullptr)
Definition: IndexBody.cpp:512
bool shouldIndexParametersInDeclarations() const
bool indexDeclGroupRef(DeclGroupRef DG)
Definition: IndexDecl.cpp:818
static bool isTemplateImplicitInstantiation(const Decl *D)
void indexTagDecl(const TagDecl *D, ArrayRef< SymbolRelation > Relations=std::nullopt)
const LangOptions & getLangOpts() const
bool indexDecl(const Decl *D)
Definition: IndexDecl.cpp:780
void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC=nullptr, bool isBase=false, bool isIBType=false)
bool handleDecl(const Decl *D, SymbolRoleSet Roles=SymbolRoleSet(), ArrayRef< SymbolRelation > Relations=std::nullopt)
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
unsigned SymbolRoleSet
Definition: IndexSymbol.h:133
The JSON file list parser is used to communicate input to InstallAPI.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Definition: TemplateBase.h:676
Location information for a TemplateArgument.
Definition: TemplateBase.h:472
TypeSourceInfo * getAsTypeSourceInfo() const
Definition: TemplateBase.h:501
std::function< bool(const Decl *)> ShouldTraverseDecl
Represents a relation to another symbol for a symbol occurrence.
Definition: IndexSymbol.h:136