clang: lib/Index/IndexDecl.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
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> {
38
39public:
41 : IndexCtx(indexCtx) { }
42
43 bool Handled = true;
44
46 Handled = false;
47 return true;
48 }
49
57 break;
60 break;
68 if (const NamedDecl *TTD = TD->getTemplatedDecl())
70 }
71 break;
72 default:
73 break;
74 }
75 }
76
77
78
81 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
82 D->isInstanceMethod());
85 }
86
87
90 bool isIBType = false) {
92
94 Parent->getLexicalDeclContext(),
95 false, isIBType);
97 auto IndexDefaultParmeterArgument = [&](const ParmVarDecl *Parm,
102 };
104 if (const ParmVarDecl *Parm = dyn_cast(D)) {
106 if (auto *FD = dyn_cast(DC)) {
108 FD->isThisDeclarationADefinition())
110 } else if (auto *MD = dyn_cast(DC)) {
111 if (MD->isThisDeclarationADefinition())
113 } else {
115 }
116 } else if (const FunctionDecl *FD = dyn_cast(D)) {
118 FD->isThisDeclarationADefinition()) {
119 for (const auto *PI : FD->parameters()) {
120 IndexDefaultParmeterArgument(PI, D);
122 }
123 }
124 }
125 } else {
126
127 if (const auto *FD = dyn_cast(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())
137 }
138
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
154
158
160
161
162 if (AssociatedProp) {
163 bool isGetter = ->param_size();
164 AttrLoc = isGetter ?
165 AssociatedProp->getGetterNameLoc():
166 AssociatedProp->getSetterNameLoc();
167 }
168
172 MethodLoc = AttrLoc;
173 } else {
175 }
176 } else if (AttrLoc.isValid()) {
179 }
180
183 bool hasIBActionAndFirst = D->hasAttr();
184 for (const auto *I : D->parameters()) {
185 handleDeclarator(I, D, hasIBActionAndFirst);
186 hasIBActionAndFirst = false;
187 }
188
189 if (D->isThisDeclarationADefinition()) {
191 if (Body) {
193 }
194 }
195 return true;
196 }
197
198
199
200
201
202
203
204 void
205 gatherTemplatePseudoOverrides(const NamedDecl *D,
208 return;
209 const auto *CTSD =
211 if (!CTSD)
212 return;
216 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
217 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
218 bool TypeOverride = isa(D);
219 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
220 if (const auto *CTD = dyn_cast(ND))
221 ND = CTD->getTemplatedDecl();
222 if (ND->isImplicit())
223 continue;
224
225 if (!TypeOverride) {
226 if (ND->getKind() != D->getKind())
227 continue;
228 } else if (!isa(ND))
229 continue;
230 if (const auto *FD = dyn_cast(ND)) {
231 const auto *DFD = cast(D);
232
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
246 if (auto *CXXMD = dyn_cast(D)) {
247 if (CXXMD->isVirtual())
248 Roles |= (unsigned)SymbolRole::Dynamic;
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(
257 Base->getTemplatedDecl()));
258
260 handleDeclarator(D);
261
263 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
264 Ctor->getParent(), Ctor->getDeclContext(),
265 (unsigned)SymbolRole::NameReference);
266
267
268 for (const auto *Init : Ctor->inits()) {
269 if (Init->isWritten()) {
273 (unsigned)SymbolRole::Write);
275 }
276 }
277 } else if (const CXXDestructorDecl *Dtor = dyn_cast(D)) {
278 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
280 TypeNameInfo->getTypeLoc().getBeginLoc(),
281 Dtor->getParent(), Dtor->getDeclContext(),
282 (unsigned)SymbolRole::NameReference);
283 }
284 } else if (const auto *Guide = dyn_cast(D)) {
285 IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
286 Guide->getLocation(), Guide,
287 Guide->getDeclContext());
288 }
289
291 D->getTemplateSpecializationArgsAsWritten()) {
292 for (const auto &Arg : TemplateArgInfo->arguments())
294 }
295
296 if (D->isThisDeclarationADefinition()) {
298 if (Body) {
300 }
301 }
302 return true;
303 }
304
305 bool VisitVarDecl(const VarDecl *D) {
307 gatherTemplatePseudoOverrides(D, Relations);
309 handleDeclarator(D);
311 return true;
312 }
313
315 for (const auto *Binding : D->bindings())
317 return Base::VisitDecompositionDecl(D);
318 }
319
320 bool VisitFieldDecl(const FieldDecl *D) {
322 gatherTemplatePseudoOverrides(D, Relations);
324 handleDeclarator(D);
325 if (D->isBitField())
327 else if (D->hasInClassInitializer())
328 IndexCtx.indexBody(D->getInClassInitializer(), D);
329 return true;
330 }
331
333 if (D->getSynthesize()) {
334
335 return true;
336 }
338 handleDeclarator(D);
339 return true;
340 }
341
344 handleDeclarator(D);
345 return true;
346 }
347
351 return true;
352 }
353
355 if (->isTransparentTag()) {
357 gatherTemplatePseudoOverrides(D, Relations);
360 }
361 return true;
362 }
363
364 bool VisitTagDecl(const TagDecl *D) {
365
366 if (D->isFreeStanding()) {
367 if (D->isThisDeclarationADefinition()) {
369 gatherTemplatePseudoOverrides(D, Relations);
371 } else {
373 gatherTemplatePseudoOverrides(D, Relations);
376 }
377 }
378 return true;
379 }
380
381 bool VisitEnumDecl(const EnumDecl *ED) {
382 TRY_TO(VisitTagDecl(ED));
383
384
387 return true;
388 }
389
390 bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
395 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
399 if (Loc == SuperLoc)
402 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
403 }
404 return true;
405 }
406
408 if (D->isThisDeclarationADefinition()) {
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;
419 }
420 }
421 }
423 if (hasSuperTypedef)
424 superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
426 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
427 }
428 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
429 SuperLoc));
431 } else {
434 }
435 return true;
436 }
437
439 if (D->isThisDeclarationADefinition()) {
441 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
444 } else {
447 }
448 return true;
449 }
450
454 return true;
455
456 if (Class->isImplicitInterfaceDecl())
458
460
461
462
463
464 for (const auto *I : D->property_impls()) {
465 if (I->getLocation().isInvalid())
467 }
468 for (const auto *I : D->decls()) {
469 if (!isa(I) ||
470 cast(I)->getLocation().isValid())
472 }
473
474 return true;
475 }
476
479 return true;
481 if ()
482 return true;
485 (unsigned)SymbolRole::RelationExtendedBy, D
486 }));
488 if (!CategoryLoc.isValid())
491 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
494 return true;
495 }
496
499 if (!Cat)
500 return true;
502 if (C)
506 if (!CategoryLoc.isValid())
510 return true;
511 }
512
514
515
516 if (D->isPropertyAccessor())
517 return true;
518
519 handleObjCMethod(D);
520 return true;
521 }
522
526 handleObjCMethod(MD, D);
529 handleObjCMethod(MD, D);
531 if (IBOutletCollectionAttr *attr = D->getAttr())
535 return true;
536 }
537
540 auto *Container = cast(D->getDeclContext());
544
546 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
548 Loc = Container->getLocation();
550 }
552
554 return true;
555
560 if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
561 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
562 }
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
570
571
572
573
574
578 IvarLoc = Container->getLocation();
582 }
584 } else {
585 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
587 }
588 }
589 return true;
590 }
591
595 return true;
596 }
597
601 IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
603 return true;
604 }
605
606 bool VisitUsingDecl(const UsingDecl *D) {
608
613 for (const auto *I : D->shadows()) {
614
615
616
617 if (isa(I->getUnderlyingDecl()))
618 continue;
619
622 }
623 return true;
624 }
625
629
630
631
635
636 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
640 }
641
648 return true;
649 }
650
657 return true;
658 }
659
660 bool VisitClassTemplateSpecializationDecl(const
662
663
666 Template = D->getSpecializedTemplateOrPartial();
667 const Decl *SpecializationOf =
668 isa<ClassTemplateDecl *>(Template)
669 ? (Decl *)cast<ClassTemplateDecl *>(Template)
670 : cast<ClassTemplatePartialSpecializationDecl *>(Template);
671 if (->isThisDeclarationADefinition())
675 SpecializationOf));
676
678 D->getTemplateArgsAsWritten()) {
679 for (const auto &Arg : TemplateArgInfo->arguments())
681 }
682 return true;
683 }
684
685 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
686
687
688 if ()
689 return false;
690 if (const auto *FD = dyn_cast(D))
691 return FD->getCanonicalDecl() == FD;
692 else if (const auto *TD = dyn_cast(D))
693 return TD->getCanonicalDecl() == TD;
694 else if (const auto *VD = dyn_cast(D))
695 return VD->getCanonicalDecl() == VD;
696 return true;
697 }
698
701 for (const NamedDecl *TP : *Params) {
704 if (const auto *TTP = dyn_cast(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(TP)) {
713 if (NTTP->hasDefaultArgument())
714 handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent,
715 TP->getLexicalDeclContext());
716 } else if (const auto *TTPD = dyn_cast(TP)) {
717 if (TTPD->hasDefaultArgument())
718 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
719 TP->getLexicalDeclContext());
720 }
721 }
722 if (auto *R = Params->getRequiresClause())
724 }
725
729 return true;
730
731
732 auto *Params = D->getTemplateParameters();
733 if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) {
734 indexTemplateParameters(Params, Parent);
735 }
736
738 }
739
740 bool VisitConceptDecl(const ConceptDecl *D) {
741 if (auto *Params = D->getTemplateParameters())
742 indexTemplateParameters(Params, D);
743 if (auto *E = D->getConstraintExpr())
746 }
747
748 bool VisitFriendDecl(const FriendDecl *D) {
749 if (auto ND = D->getFriendDecl()) {
750
751
752
753
754
755
757 return true;
758 return Visit(ND);
759 }
760 if (auto Ty = D->getFriendType()) {
762 }
763 return true;
764 }
765
766 bool VisitImportDecl(const ImportDecl *D) {
768 }
769
771 IndexCtx.indexBody(D->getAssertExpr(),
774 return true;
775 }
776};
777
778}
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(D))
794
795 return true;
796}
797
799 for (const auto *I : DC->decls())
801 return false;
802 return true;
803}
804
807 return true;
808
809 if (isa(D))
810 return true;
811
813 return true;
814
816}
817
821 return false;
822 return true;
823}
This file provides AST data structures related to concepts.
Defines the C++ template declaration subclasses.
#define TRY_DECL(D, CALL_EXPR)
#define TRY_TO(CALL_EXPR)
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
Represents a C++ struct/union/class.
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.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
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.
Decl - This represents one declaration (or definition), e.g.
const DeclContext * getParentFunctionOrMethod(bool LexicalParent=false) const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext,...
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
SourceLocation getLocation() const
DeclContext * getDeclContext()
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Represents a ValueDecl that came out of a declarator.
A decomposition declaration.
An instance of this object exists for each enum constant that is defined.
TypeSourceInfo * getIntegerTypeSourceInfo() const
Return the type source info for the underlying integer type, if no type source info exists,...
Represents a member of a struct/union/class.
FriendDecl - Represents the declaration of a friend entity, which can be a function,...
Represents a function declaration or definition.
Describes a module import declaration, which makes the contents of the named module visible in the cu...
An instance of this class represents the declaration of a property member.
This represents a decl that may have a name.
Represents a C++ namespace alias.
Represent a C++ namespace.
ObjCCategoryDecl - Represents a category declaration.
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.
ObjCContainerDecl - Represents a container for method declarations.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
ObjCProtocolList::iterator protocol_iterator
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCMethodDecl - Represents an instance or class method declaration.
bool isSynthesizedAccessorStub() const
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
Represents one property declaration in an Objective-C interface.
ObjCMethodDecl * getGetterMethodDecl() const
ObjCMethodDecl * getSetterMethodDecl() const
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
Represents an Objective-C protocol declaration.
A list of Objective-C protocols, along with the source locations at which they were referenced.
loc_iterator loc_begin() const
Represents a parameter to a function.
bool hasUnparsedDefaultArg() const
Determines whether this parameter has a default argument that has not yet been parsed.
bool hasUninstantiatedDefaultArg() const
bool hasDefaultArg() const
Determines whether this parameter has a default argument, either parsed or not.
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.
Stmt - This represents one statement.
Represents the declaration of a struct/union/class/enum.
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.).
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) 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.
Base class for declarations which introduce a typedef-name.
Represents a dependent using declaration which was marked with typename.
Represents a dependent using declaration which was not marked with typename.
Represents a C++ using-declaration.
Represents C++ using-directive.
Represents a variable declaration or definition.
RetTy VisitDecl(PTR(Decl) D)
bool shouldIndexImplicitInstantiation() const
bool importedModule(const ImportDecl *ImportD)
bool handleDecl(const Decl *D, SymbolRoleSet Roles=SymbolRoleSet(), ArrayRef< SymbolRelation > Relations={})
bool shouldIndex(const Decl *D)
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={})
bool shouldIndexFunctionLocalSymbols() const
void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const NamedDecl *Parent, const DeclContext *DC=nullptr)
bool indexTopLevelDecl(const Decl *D)
bool shouldIndexTemplateParameters() const
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)
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
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 "" in "sort".
Location information for a TemplateArgument.
TypeSourceInfo * getAsTypeSourceInfo() const
std::function< bool(const Decl *)> ShouldTraverseDecl
Represents a relation to another symbol for a symbol occurrence.