clang 24.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 (const AssociatedConstraint &C = D->getTrailingRequiresClause())
136 IndexCtx.indexBody(C.ConstraintExpr, 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 =
292 for (const auto &Arg : TemplateArgInfo->arguments())
293 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
294 }
295
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()) {
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) {
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) {
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()) {
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;
481 if (!C)
482 return true;
483 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
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;
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) {
540 auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
541 SourceLocation Loc = D->getLocation();
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
554 return true;
555
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;
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));
603 return true;
604 }
605
606 bool VisitUsingDecl(const UsingDecl *D) {
607 IndexCtx.handleDecl(D);
608
609 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
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) {
627 const DeclContext *DC = D->getDeclContext()->getRedeclContext();
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
637 D->getLocation(), Parent,
639 SymbolRoleSet());
640 }
641
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,
648 return true;
649 }
650
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,
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 *,
667 const Decl *SpecializationOf =
673 IndexCtx.indexTagDecl(
674 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
675 SpecializationOf));
676 // Template specialization arguments.
677 if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
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,
708 if (auto *C = TTP->getTypeConstraint())
709 IndexCtx.handleReference(C->getNamedConcept().getAsTemplateDecl(),
710 C->getConceptNameLoc(), Parent,
711 TTP->getLexicalDeclContext());
712 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
713 IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent);
714 if (NTTP->hasDefaultArgument())
715 handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent,
717 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
718 if (TTPD->hasDefaultArgument())
719 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
721 }
722 }
723 if (auto *R = Params->getRequiresClause())
724 IndexCtx.indexBody(R, Parent);
725 }
726
727 bool VisitTemplateDecl(const TemplateDecl *D) {
728 const NamedDecl *Parent = D->getTemplatedDecl();
729 if (!Parent)
730 return true;
731
732 // Index the default values for the template parameters.
733 auto *Params = D->getTemplateParameters();
734 if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) {
735 indexTemplateParameters(Params, Parent);
736 }
737
738 return Visit(Parent);
739 }
740
741 bool VisitConceptDecl(const ConceptDecl *D) {
742 if (auto *Params = D->getTemplateParameters())
743 indexTemplateParameters(Params, D);
744 if (auto *E = D->getConstraintExpr())
745 IndexCtx.indexBody(E, D);
746 return IndexCtx.handleDecl(D);
747 }
748
749 bool VisitFriendDecl(const FriendDecl *D) {
750 if (auto ND = D->getFriendDecl()) {
751 // FIXME: Ignore a class template in a dependent context, these are not
752 // linked properly with their redeclarations, ending up with duplicate
753 // USRs.
754 // See comment "Friend templates are visible in fairly strange ways." in
755 // SemaTemplate.cpp which precedes code that prevents the friend template
756 // from becoming visible from the enclosing context.
758 return true;
759 return Visit(ND);
760 }
761 if (auto Ty = D->getFriendType()) {
763 }
764 return true;
765 }
766
767 bool VisitFriendTemplateDecl(const FriendTemplateDecl *D) {
768 const NamedDecl *ND = cast<NamedDecl>(D->getDeclContext());
769 if (!D->getFriendType() && D->getFriendTemplateName().isNull())
770 ND = D->getFriendDecl();
772 indexTemplateParameters(TPL, ND);
773 return VisitFriendDecl(D);
774 }
775
776 bool VisitImportDecl(const ImportDecl *D) {
777 return IndexCtx.importedModule(D);
778 }
779
780 bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
781 IndexCtx.indexBody(D->getAssertExpr(),
782 dyn_cast<NamedDecl>(D->getDeclContext()),
784 return true;
785 }
786};
787
788} // anonymous namespace
789
791 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
792 return true;
793
795 return true;
796
797 IndexingDeclVisitor Visitor(*this);
798 bool ShouldContinue = Visitor.Visit(D);
799 if (!ShouldContinue)
800 return false;
801
802 if (!Visitor.Handled && isa<DeclContext>(D))
804
805 return true;
806}
807
809 for (const auto *I : DC->decls())
810 if (!indexDecl(I))
811 return false;
812 return true;
813}
814
816 if (!D || D->getLocation().isInvalid())
817 return true;
818
819 if (isa<ObjCMethodDecl>(D))
820 return true; // Wait for the objc container.
821
822 if (IndexOpts.ShouldTraverseDecl && !IndexOpts.ShouldTraverseDecl(D))
823 return true; // skip
824
825 return indexDecl(D);
826}
827
829 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
830 if (!indexTopLevelDecl(*I))
831 return false;
832 return true;
833}
This file provides AST data structures related to concepts.
Defines the C++ template declaration subclasses.
#define TRY_TO(CALL_EXPR)
Definition IndexDecl.cpp:28
#define TRY_DECL(D, CALL_EXPR)
Definition IndexDecl.cpp:21
shadow_range shadows() const
Definition DeclCXX.h:3591
Represents a C++ constructor within a class.
Definition DeclCXX.h:2641
Represents a C++ destructor within a class.
Definition DeclCXX.h:2906
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2149
overridden_method_range overridden_methods() const
Definition DeclCXX.cpp:2828
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...
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Retrieve the template argument list as written in the sources, if any.
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.
Expr * getConstraintExpr() const
A simple visitor class that helps create declaration visitors.
Definition DeclVisitor.h:75
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2403
iterator begin()
Definition DeclGroup.h:95
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:344
T * getAttr() const
Definition DeclBase.h:581
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:601
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:1104
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:935
bool hasAttr() const
Definition DeclBase.h:585
Kind getKind() const
Definition DeclBase.h:450
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:781
A decomposition declaration.
Definition DeclCXX.h:4278
ArrayRef< BindingDecl * > bindings() const
Definition DeclCXX.h:4318
An instance of this object exists for each enum constant that is defined.
Definition Decl.h:3558
const Expr * getInitExpr() const
Definition Decl.h:3576
Represents an enum.
Definition Decl.h:4146
TypeSourceInfo * getIntegerTypeSourceInfo() const
Return the type source info for the underlying integer type, if no type source info exists,...
Definition Decl.h:4335
Represents a member of a struct/union/class.
Definition Decl.h:3295
Expr * getInClassInitializer() const
Get the C++11 default member initializer for this member, or null if one has not been set.
Definition Decl.cpp:4789
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3398
bool hasInClassInitializer() const
Determine whether this member has a C++11 default member initializer.
Definition Decl.h:3475
Expr * getBitWidth() const
Returns the expression that represents the bit width, if this field is a bit field.
Definition Decl.h:3411
FriendDecl - Represents the declaration of a friend entity, which can be a function,...
Definition DeclFriend.h:46
virtual NamedDecl * getFriendDecl() const
If this friend declaration doesn't name a type, return the inner declaration.
Definition DeclFriend.h:102
TypeSourceInfo * getFriendType() const
If this friend declaration names an (untemplated but possibly dependent) type, return the type; other...
Definition DeclFriend.h:96
Declaration of a friend template.
NamedDecl * getFriendDecl() const override
If this friend declaration doesn't name a type, return the inner declaration.
TemplateName getFriendTemplateName() const
ArrayRef< TemplateParameterList * > getTemplateParameterLists() const
Represents a function declaration or definition.
Definition Decl.h:2059
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3268
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition Decl.h:2428
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition Decl.cpp:4354
const ASTTemplateArgumentListInfo * getTemplateSpecializationArgsAsWritten() const
Retrieve the template argument list as written in the sources, if any.
Definition Decl.cpp:4380
Describes a module import declaration, which makes the contents of the named module visible in the cu...
Definition Decl.h:5188
An instance of this class represents the declaration of a property member.
Definition DeclCXX.h:4378
This represents a decl that may have a name.
Definition Decl.h:275
Represents a C++ namespace alias.
Definition DeclCXX.h:3230
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier that qualifies the name of the namespace, with source-location inf...
Definition DeclCXX.h:3291
NamespaceBaseDecl * getAliasedNamespace() const
Retrieve the namespace that this alias refers to, which may either be a NamespaceDecl or a NamespaceA...
Definition DeclCXX.h:3323
SourceLocation getTargetNameLoc() const
Returns the location of the identifier in the named namespace.
Definition DeclCXX.h:3319
Represent a C++ namespace.
Definition Decl.h:593
ObjCCategoryDecl - Represents a category declaration.
Definition DeclObjC.h:2335
ObjCInterfaceDecl * getClassInterface()
Definition DeclObjC.h:2378
const ObjCProtocolList & getReferencedProtocols() const
Definition DeclObjC.h:2402
SourceLocation getCategoryNameLoc() const
Definition DeclObjC.h:2466
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.
Definition DeclObjC.h:2551
SourceLocation getCategoryNameLoc() const
Definition DeclObjC.h:2578
ObjCCategoryDecl * getCategoryDecl() const
ObjCContainerDecl - Represents a container for method declarations.
Definition DeclObjC.h:954
ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const
Definition DeclObjC.cpp:90
propimpl_range property_impls() const
Definition DeclObjC.h:2519
const ObjCInterfaceDecl * getClassInterface() const
Definition DeclObjC.h:2492
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Definition DeclObjC.h:2603
Represents an ObjC class declaration.
Definition DeclObjC.h:1160
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
Definition DeclObjC.cpp:369
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
Definition DeclObjC.h:1529
const ObjCProtocolList & getReferencedProtocols() const
Definition DeclObjC.h:1339
ObjCProtocolList::iterator protocol_iterator
Definition DeclObjC.h:1362
ObjCProtocolList::loc_iterator protocol_loc_iterator
Definition DeclObjC.h:1391
ObjCInterfaceDecl * getSuperClass() const
Definition DeclObjC.cpp:349
TypeSourceInfo * getSuperClassTInfo() const
Definition DeclObjC.h:1579
ObjCIvarDecl - Represents an ObjC instance variable.
Definition DeclObjC.h:1958
bool getSynthesize() const
Definition DeclObjC.h:2013
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 isPropertyAccessor() const
Definition DeclObjC.h:439
bool isSynthesizedAccessorStub() const
Definition DeclObjC.h:447
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
Definition DeclObjC.h:537
Represents one property declaration in an Objective-C interface.
Definition DeclObjC.h:734
ObjCMethodDecl * getGetterMethodDecl() const
Definition DeclObjC.h:907
ObjCMethodDecl * getSetterMethodDecl() const
Definition DeclObjC.h:910
TypeSourceInfo * getTypeSourceInfo() const
Definition DeclObjC.h:808
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
Definition DeclObjC.h:2811
ObjCIvarDecl * getPropertyIvarDecl() const
Definition DeclObjC.h:2885
SourceLocation getPropertyIvarDeclLoc() const
Definition DeclObjC.h:2888
Kind getPropertyImplementation() const
Definition DeclObjC.h:2881
ObjCPropertyDecl * getPropertyDecl() const
Definition DeclObjC.h:2876
Represents an Objective-C protocol declaration.
Definition DeclObjC.h:2090
bool isThisDeclarationADefinition() const
Determine whether this particular declaration is also the definition.
Definition DeclObjC.h:2267
const ObjCProtocolList & getReferencedProtocols() const
Definition DeclObjC.h:2159
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:1820
bool hasUnparsedDefaultArg() const
Determines whether this parameter has a default argument that has not yet been parsed.
Definition Decl.h:1949
bool hasUninstantiatedDefaultArg() const
Definition Decl.h:1953
Expr * getDefaultArg()
Definition Decl.cpp:2998
bool hasDefaultArg() const
Determines whether this parameter has a default argument, either parsed or not.
Definition Decl.cpp:3046
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:4165
Stmt - This represents one statement.
Definition Stmt.h:85
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3852
bool isThisDeclarationADefinition() const
Return true if this declaration is a completion definition of the type.
Definition Decl.h:3948
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition Decl.h:4106
bool isFreeStanding() const
True if this tag is free standing, e.g. "struct foo;".
Definition Decl.h:3988
Location wrapper for a TemplateArgument.
TemplateArgumentLocInfo getLocInfo() const
const TemplateArgument & getArgument() const
SourceLocation getTemplateNameLoc() const
NestedNameSpecifierLoc getTemplateQualifierLoc() const
@ Template
The template argument is a template name that was provided for a template template parameter.
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
@ Type
The template argument is a type.
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
ArgKind getKind() const
Return the kind of stored template argument.
TemplateName getAsTemplateOrTemplatePattern() const
Retrieve the template argument as a template name; if the argument is a pack expansion,...
The base class of all kinds of template declarations (e.g., class, function, etc.).
NamedDecl * getTemplatedDecl() const
Get the underlying, templated declaration.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
bool isNull() const
Determine whether this template name is NULL.
Stores a list of template parameters for a TemplateDecl and its derived classes.
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3697
TypeSourceInfo * getTypeSourceInfo() const
Definition Decl.h:3747
bool isTransparentTag() const
Determines if this typedef shares a name and spelling location with its underlying tag type,...
Definition Decl.h:3780
Represents a dependent using declaration which was marked with typename.
Definition DeclCXX.h:4066
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier that qualifies the name, with source-location information.
Definition DeclCXX.h:4100
Represents a dependent using declaration which was not marked with typename.
Definition DeclCXX.h:3969
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier that qualifies the name, with source-location information.
Definition DeclCXX.h:4010
Represents a C++ using-declaration.
Definition DeclCXX.h:3620
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier that qualifies the name, with source-location information.
Definition DeclCXX.h:3654
Represents C++ using-directive.
Definition DeclCXX.h:3125
NamedDecl * getNominatedNamespaceAsWritten()
Definition DeclCXX.h:3178
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier that qualifies the name of the namespace, with source-location inf...
Definition DeclCXX.h:3170
Represents a variable declaration or definition.
Definition Decl.h:933
const Expr * getInit() const
Definition Decl.h:1392
bool importedModule(const ImportDecl *ImportD)
bool handleDecl(const Decl *D, SymbolRoleSet Roles=SymbolRoleSet(), ArrayRef< SymbolRelation > Relations={})
bool indexDeclContext(const DeclContext *DC)
bool handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, SymbolRoleSet Roles=SymbolRoleSet(), ArrayRef< SymbolRelation > Relations={}, const Expr *RefE=nullptr)
void indexTagDecl(const TagDecl *D, ArrayRef< SymbolRelation > Relations={})
void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const NamedDecl *Parent, const DeclContext *DC=nullptr)
bool indexTopLevelDecl(const Decl *D)
void indexBody(const Stmt *S, const NamedDecl *Parent, const DeclContext *DC=nullptr)
bool shouldIndexParametersInDeclarations() const
bool indexDeclGroupRef(DeclGroupRef DG)
static bool isTemplateImplicitInstantiation(const Decl *D)
const LangOptions & getLangOpts() const
bool indexDecl(const Decl *D)
void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC=nullptr, bool isBase=false, bool isIBType=false)
unsigned SymbolRoleSet
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Template
We are parsing a template declaration.
Definition Parser.h:81
U cast(CodeGen::Address addr)
Definition Address.h:327
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Location information for a TemplateArgument.
TypeSourceInfo * getAsTypeSourceInfo() const
Represents a relation to another symbol for a symbol occurrence.