clang  19.0.0git
IndexTypeSourceInfo.cpp
Go to the documentation of this file.
1 //===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
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"
10 #include "clang/AST/ASTConcept.h"
13 #include "clang/AST/TypeLoc.h"
14 #include "llvm/ADT/ScopeExit.h"
15 
16 using namespace clang;
17 using namespace index;
18 
19 namespace {
20 
21 class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
22  IndexingContext &IndexCtx;
23  const NamedDecl *Parent;
24  const DeclContext *ParentDC;
25  bool IsBase;
27 
29 
30 public:
31  TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
32  const DeclContext *DC, bool isBase, bool isIBType)
33  : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
34  if (IsBase) {
35  assert(Parent);
36  Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
37  }
38  if (isIBType) {
39  assert(Parent);
40  Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
41  }
42  }
43 
44  bool shouldWalkTypesOfTypeLocs() const { return false; }
45 
46 #define TRY_TO(CALL_EXPR) \
47  do { \
48  if (!CALL_EXPR) \
49  return false; \
50  } while (0)
51 
52  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) {
53  SourceLocation Loc = TTPL.getNameLoc();
54  TemplateTypeParmDecl *TTPD = TTPL.getDecl();
55  return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC,
56  SymbolRoleSet());
57  }
58 
59  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
62  if (ND->isTransparentTag()) {
63  TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl();
64  return IndexCtx.handleReference(Underlying, Loc, Parent,
65  ParentDC, SymbolRoleSet(), Relations);
66  }
67  if (IsBase) {
68  TRY_TO(IndexCtx.handleReference(ND, Loc,
69  Parent, ParentDC, SymbolRoleSet()));
70  if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {
71  TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC,
72  (unsigned)SymbolRole::Implicit,
73  Relations));
74  }
75  } else {
76  TRY_TO(IndexCtx.handleReference(ND, Loc,
77  Parent, ParentDC, SymbolRoleSet(),
78  Relations));
79  }
80  return true;
81  }
82 
83  bool VisitAutoTypeLoc(AutoTypeLoc TL) {
84  if (auto *C = TL.getNamedConcept())
85  return IndexCtx.handleReference(C, TL.getConceptNameLoc(), Parent,
86  ParentDC);
87  return true;
88  }
89 
90  bool traverseParamVarHelper(ParmVarDecl *D) {
91  TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
92  if (D->getTypeSourceInfo())
93  TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
94  return true;
95  }
96 
97  bool TraverseParmVarDecl(ParmVarDecl *D) {
98  // Avoid visiting default arguments from the definition that were already
99  // visited in the declaration.
100  // FIXME: A free function definition can have default arguments.
101  // Avoiding double visitaiton of default arguments should be handled by the
102  // visitor probably with a bit in the AST to indicate if the attached
103  // default argument was 'inherited' or written in source.
104  if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
105  if (FD->isThisDeclarationADefinition()) {
106  return traverseParamVarHelper(D);
107  }
108  }
109 
110  return base::TraverseParmVarDecl(D);
111  }
112 
113  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
114  IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
115  return true;
116  }
117 
118  bool VisitTagTypeLoc(TagTypeLoc TL) {
119  TagDecl *D = TL.getDecl();
120  if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&
122  return true;
123 
124  if (TL.isDefinition()) {
125  IndexCtx.indexTagDecl(D);
126  return true;
127  }
128 
129  return IndexCtx.handleReference(D, TL.getNameLoc(),
130  Parent, ParentDC, SymbolRoleSet(),
131  Relations);
132  }
133 
134  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
135  return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
136  Parent, ParentDC, SymbolRoleSet(), Relations);
137  }
138 
139  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
140  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
141  IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
142  Parent, ParentDC, SymbolRoleSet(), Relations);
143  }
144  return true;
145  }
146 
147  void HandleTemplateSpecializationTypeLoc(TemplateName TemplName,
148  SourceLocation TemplNameLoc,
149  CXXRecordDecl *ResolvedClass,
150  bool IsTypeAlias) {
151  // In presence of type aliases, the resolved class was never written in
152  // the code so don't report it.
153  if (!IsTypeAlias && ResolvedClass &&
154  (!ResolvedClass->isImplicit() ||
155  IndexCtx.shouldIndexImplicitInstantiation())) {
156  IndexCtx.handleReference(ResolvedClass, TemplNameLoc, Parent, ParentDC,
157  SymbolRoleSet(), Relations);
158  } else if (const TemplateDecl *D = TemplName.getAsTemplateDecl()) {
159  IndexCtx.handleReference(D, TemplNameLoc, Parent, ParentDC,
160  SymbolRoleSet(), Relations);
161  }
162  }
163 
164  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
165  auto *T = TL.getTypePtr();
166  if (!T)
167  return true;
168  HandleTemplateSpecializationTypeLoc(
169  T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(),
170  T->isTypeAlias());
171  return true;
172  }
173 
174  bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
175  if (!WalkUpFromTemplateSpecializationTypeLoc(TL))
176  return false;
177  if (!TraverseTemplateName(TL.getTypePtr()->getTemplateName()))
178  return false;
179 
180  // The relations we have to `Parent` do not apply to our template arguments,
181  // so clear them while visiting the args.
182  SmallVector<SymbolRelation, 3> SavedRelations = Relations;
183  Relations.clear();
184  auto ResetSavedRelations =
185  llvm::make_scope_exit([&] { this->Relations = SavedRelations; });
186  for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
187  if (!TraverseTemplateArgumentLoc(TL.getArgLoc(I)))
188  return false;
189  }
190 
191  return true;
192  }
193 
194  bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {
195  auto *T = TL.getTypePtr();
196  if (!T)
197  return true;
198  HandleTemplateSpecializationTypeLoc(
199  T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(),
200  /*IsTypeAlias=*/false);
201  return true;
202  }
203 
204  bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
205  return IndexCtx.handleReference(TL.getDecl(), TL.getNameLoc(), Parent,
206  ParentDC, SymbolRoleSet(), Relations);
207  }
208 
209  bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
210  const DependentNameType *DNT = TL.getTypePtr();
211  const NestedNameSpecifier *NNS = DNT->getQualifier();
212  const Type *T = NNS->getAsType();
213  if (!T)
214  return true;
215  const TemplateSpecializationType *TST =
217  if (!TST)
218  return true;
219  TemplateName TN = TST->getTemplateName();
220  const ClassTemplateDecl *TD =
221  dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
222  if (!TD)
223  return true;
224  CXXRecordDecl *RD = TD->getTemplatedDecl();
225  if (!RD->hasDefinition())
226  return true;
227  RD = RD->getDefinition();
228  DeclarationName Name(DNT->getIdentifier());
229  std::vector<const NamedDecl *> Symbols = RD->lookupDependentName(
230  Name, [](const NamedDecl *ND) { return isa<TypeDecl>(ND); });
231  if (Symbols.size() != 1)
232  return true;
233  return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent,
234  ParentDC, SymbolRoleSet(), Relations);
235  }
236 
237  bool TraverseStmt(Stmt *S) {
238  IndexCtx.indexBody(S, Parent, ParentDC);
239  return true;
240  }
241 };
242 
243 } // anonymous namespace
244 
246  const NamedDecl *Parent,
247  const DeclContext *DC,
248  bool isBase,
249  bool isIBType) {
250  if (!TInfo || TInfo->getTypeLoc().isNull())
251  return;
252 
253  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
254 }
255 
257  const NamedDecl *Parent,
258  const DeclContext *DC,
259  bool isBase,
260  bool isIBType) {
261  if (TL.isNull())
262  return;
263 
264  if (!DC)
265  DC = Parent->getLexicalDeclContext();
266  TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
267 }
268 
270  const NamedDecl *Parent,
271  const DeclContext *DC) {
272  if (!NNS)
273  return;
274 
275  if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
276  indexNestedNameSpecifierLoc(Prefix, Parent, DC);
277 
278  if (!DC)
279  DC = Parent->getLexicalDeclContext();
281 
282  switch (NNS.getNestedNameSpecifier()->getKind()) {
286  break;
287 
290  Loc, Parent, DC, SymbolRoleSet());
291  break;
294  Loc, Parent, DC, SymbolRoleSet());
295  break;
296 
299  indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
300  break;
301  }
302 }
303 
305  ArrayRef<SymbolRelation> Relations) {
306  if (!shouldIndex(D))
307  return;
309  return;
310 
311  if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {
312  if (D->isThisDeclarationADefinition()) {
314  if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
315  for (const auto &I : CXXRD->bases()) {
316  indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
317  }
318  }
319  indexDeclContext(D);
320  }
321  }
322 }
This file provides AST data structures related to concepts.
NodeId Parent
Definition: ASTDiff.cpp:191
SourceLocation Loc
Definition: SemaObjC.cpp:755
Defines the clang::TypeLoc interface and its subclasses.
ConceptDecl * getNamedConcept() const
Definition: TypeLoc.h:2231
SourceLocation getConceptNameLoc() const
Definition: TypeLoc.h:2219
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool hasDefinition() const
Definition: DeclCXX.h:571
std::vector< const NamedDecl * > lookupDependentName(DeclarationName Name, llvm::function_ref< bool(const NamedDecl *ND)> Filter)
Performs an imprecise lookup of a dependent name in this class.
CXXRecordDecl * getDefinition() const
Definition: DeclCXX.h:564
Declaration of a class template.
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:421
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
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:295
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:599
DeclContext * getDeclContext()
Definition: DeclBase.h:454
The name of a declaration.
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:800
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition: Decl.h:837
SourceLocation getTemplateNameLoc() const
Definition: TypeLoc.h:2298
SourceLocation getNameLoc() const
Definition: TypeLoc.h:2419
Represents a qualified type name for which the type name is dependent.
Definition: Type.h:6464
const IdentifierInfo * getIdentifier() const
Retrieve the type named by the typename specifier as an identifier.
Definition: Type.h:6489
NestedNameSpecifier * getQualifier() const
Retrieve the qualification on this type.
Definition: Type.h:6482
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:514
Wrapper for source info for injected class names of class templates.
Definition: TypeLoc.h:705
CXXRecordDecl * getDecl() const
Definition: TypeLoc.h:707
This represents a decl that may have a name.
Definition: Decl.h:249
A C++ nested-name-specifier augmented with source location information.
TypeLoc getTypeLoc() const
For a nested-name-specifier that refers to a type, retrieve the type with source-location information...
NestedNameSpecifierLoc getPrefix() const
Return the prefix of this nested-name-specifier.
NestedNameSpecifier * getNestedNameSpecifier() const
Retrieve the nested-name-specifier to which this instance refers.
SourceLocation getLocalBeginLoc() const
Retrieve the location of the beginning of this component of the nested-name-specifier.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
NamespaceAliasDecl * getAsNamespaceAlias() const
Retrieve the namespace alias stored in this nested name specifier.
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
@ NamespaceAlias
A namespace alias, stored as a NamespaceAliasDecl*.
@ TypeSpec
A type, stored as a Type*.
@ TypeSpecWithTemplate
A type that was preceded by the 'template' keyword, stored as a Type*.
@ Super
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Identifier
An identifier, stored as an IdentifierInfo*.
@ Global
The global specifier '::'. There is no stored value.
@ Namespace
A namespace, stored as a NamespaceDecl*.
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
Wrapper for source info for ObjC interfaces.
Definition: TypeLoc.h:1091
SourceLocation getNameLoc() const
Definition: TypeLoc.h:1097
ObjCInterfaceDecl * getIFaceDecl() const
Definition: TypeLoc.h:1093
unsigned getNumProtocols() const
Definition: TypeLoc.h:1018
SourceLocation getProtocolLoc(unsigned i) const
Definition: TypeLoc.h:1022
ObjCProtocolDecl * getProtocol(unsigned i) const
Definition: TypeLoc.h:1032
Represents a parameter to a function.
Definition: Decl.h:1762
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Encodes a location in the source.
Stmt - This represents one statement.
Definition: Stmt.h:84
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3587
bool isThisDeclarationADefinition() const
Return true if this declaration is a completion definition of the type.
Definition: Decl.h:3685
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition: Decl.h:3832
Wrapper for source info for tag types.
Definition: TypeLoc.h:730
TagDecl * getDecl() const
Definition: TypeLoc.h:732
bool isDefinition() const
True if the tag was defined in this type specifier.
Definition: TypeLoc.cpp:314
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:394
Represents a C++ template name within the type system.
Definition: TemplateName.h:202
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known.
TemplateArgumentLoc getArgLoc(unsigned i) const
Definition: TypeLoc.h:1695
SourceLocation getTemplateNameLoc() const
Definition: TypeLoc.h:1700
Represents a type template specialization; the template must be a class template, a type alias templa...
Definition: Type.h:6101
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
Definition: Type.h:6167
Declaration of a template type parameter.
Wrapper for template type parameters.
Definition: TypeLoc.h:758
TemplateTypeParmDecl * getDecl() const
Definition: TypeLoc.h:760
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:133
bool isNull() const
Definition: TypeLoc.h:121
A container of type source information.
Definition: Type.h:7342
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
SourceLocation getNameLoc() const
Definition: TypeLoc.h:535
The base class of the type hierarchy.
Definition: Type.h:1813
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1881
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8160
TagDecl * getAsTagDecl() const
Retrieves the TagDecl that this type refers to, either because the type is a TagType or because it is...
Definition: Type.cpp:1889
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3435
QualType getUnderlyingType() const
Definition: Decl.h:3490
bool isTransparentTag() const
Determines if this typedef shares a name and spelling location with its underlying tag type,...
Definition: Decl.h:3519
Wrapper for source info for typedefs.
Definition: TypeLoc.h:693
TypedefNameDecl * getTypedefNameDecl() const
Definition: TypeLoc.h:695
bool shouldIndexImplicitInstantiation() const
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)
void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, const DeclContext *DC=nullptr, bool isBase=false, bool isIBType=false)
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
void indexTagDecl(const TagDecl *D, ArrayRef< SymbolRelation > Relations=std::nullopt)
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)
bool isFunctionLocalSymbol(const Decl *D)
Definition: IndexSymbol.cpp:53
unsigned SymbolRoleSet
Definition: IndexSymbol.h:133
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
TRY_TO(TraverseType(T->getPointeeType()))