clang  12.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"
11 
12 using namespace clang;
13 using namespace index;
14 
15 namespace {
16 
17 class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
18  IndexingContext &IndexCtx;
19  const NamedDecl *Parent;
20  const DeclContext *ParentDC;
21  bool IsBase;
23 
25 
26 public:
27  TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
28  const DeclContext *DC, bool isBase, bool isIBType)
29  : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
30  if (IsBase) {
31  assert(Parent);
32  Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
33  }
34  if (isIBType) {
35  assert(Parent);
36  Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
37  }
38  }
39 
40  bool shouldWalkTypesOfTypeLocs() const { return false; }
41 
42 #define TRY_TO(CALL_EXPR) \
43  do { \
44  if (!CALL_EXPR) \
45  return false; \
46  } while (0)
47 
48  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) {
49  SourceLocation Loc = TTPL.getNameLoc();
50  TemplateTypeParmDecl *TTPD = TTPL.getDecl();
51  return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC,
52  SymbolRoleSet());
53  }
54 
55  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
56  SourceLocation Loc = TL.getNameLoc();
58  if (ND->isTransparentTag()) {
59  TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl();
60  return IndexCtx.handleReference(Underlying, Loc, Parent,
61  ParentDC, SymbolRoleSet(), Relations);
62  }
63  if (IsBase) {
64  TRY_TO(IndexCtx.handleReference(ND, Loc,
65  Parent, ParentDC, SymbolRoleSet()));
66  if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {
67  TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC,
68  (unsigned)SymbolRole::Implicit,
69  Relations));
70  }
71  } else {
72  TRY_TO(IndexCtx.handleReference(ND, Loc,
73  Parent, ParentDC, SymbolRoleSet(),
74  Relations));
75  }
76  return true;
77  }
78 
79  bool traverseParamVarHelper(ParmVarDecl *D) {
80  TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
81  if (D->getTypeSourceInfo())
82  TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
83  return true;
84  }
85 
86  bool TraverseParmVarDecl(ParmVarDecl *D) {
87  // Avoid visiting default arguments from the definition that were already
88  // visited in the declaration.
89  // FIXME: A free function definition can have default arguments.
90  // Avoiding double visitaiton of default arguments should be handled by the
91  // visitor probably with a bit in the AST to indicate if the attached
92  // default argument was 'inherited' or written in source.
93  if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
94  if (FD->isThisDeclarationADefinition()) {
95  return traverseParamVarHelper(D);
96  }
97  }
98 
99  return base::TraverseParmVarDecl(D);
100  }
101 
102  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
103  IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
104  return true;
105  }
106 
107  bool VisitTagTypeLoc(TagTypeLoc TL) {
108  TagDecl *D = TL.getDecl();
109  if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&
111  return true;
112 
113  if (TL.isDefinition()) {
114  IndexCtx.indexTagDecl(D);
115  return true;
116  }
117 
118  return IndexCtx.handleReference(D, TL.getNameLoc(),
119  Parent, ParentDC, SymbolRoleSet(),
120  Relations);
121  }
122 
123  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
124  return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
125  Parent, ParentDC, SymbolRoleSet(), Relations);
126  }
127 
128  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
129  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
130  IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
131  Parent, ParentDC, SymbolRoleSet(), Relations);
132  }
133  return true;
134  }
135 
136  void HandleTemplateSpecializationTypeLoc(TemplateName TemplName,
137  SourceLocation TemplNameLoc,
138  CXXRecordDecl *ResolvedClass,
139  bool IsTypeAlias) {
140  // In presence of type aliases, the resolved class was never written in
141  // the code so don't report it.
142  if (!IsTypeAlias && ResolvedClass &&
143  (!ResolvedClass->isImplicit() ||
144  IndexCtx.shouldIndexImplicitInstantiation())) {
145  IndexCtx.handleReference(ResolvedClass, TemplNameLoc, Parent, ParentDC,
146  SymbolRoleSet(), Relations);
147  } else if (const TemplateDecl *D = TemplName.getAsTemplateDecl()) {
148  IndexCtx.handleReference(D, TemplNameLoc, Parent, ParentDC,
149  SymbolRoleSet(), Relations);
150  }
151  }
152 
153  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
154  auto *T = TL.getTypePtr();
155  if (!T)
156  return true;
157  HandleTemplateSpecializationTypeLoc(
158  T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(),
159  T->isTypeAlias());
160  return true;
161  }
162 
163  bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {
164  auto *T = TL.getTypePtr();
165  if (!T)
166  return true;
167  HandleTemplateSpecializationTypeLoc(
168  T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(),
169  /*IsTypeAlias=*/false);
170  return true;
171  }
172 
173  bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
174  return IndexCtx.handleReference(TL.getDecl(), TL.getNameLoc(), Parent,
175  ParentDC, SymbolRoleSet(), Relations);
176  }
177 
178  bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
179  const DependentNameType *DNT = TL.getTypePtr();
180  const NestedNameSpecifier *NNS = DNT->getQualifier();
181  const Type *T = NNS->getAsType();
182  if (!T)
183  return true;
184  const TemplateSpecializationType *TST =
186  if (!TST)
187  return true;
188  TemplateName TN = TST->getTemplateName();
189  const ClassTemplateDecl *TD =
190  dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
191  if (!TD)
192  return true;
193  CXXRecordDecl *RD = TD->getTemplatedDecl();
194  if (!RD->hasDefinition())
195  return true;
196  RD = RD->getDefinition();
197  DeclarationName Name(DNT->getIdentifier());
198  std::vector<const NamedDecl *> Symbols = RD->lookupDependentName(
199  Name, [](const NamedDecl *ND) { return isa<TypeDecl>(ND); });
200  if (Symbols.size() != 1)
201  return true;
202  return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent,
203  ParentDC, SymbolRoleSet(), Relations);
204  }
205 
206  bool TraverseStmt(Stmt *S) {
207  IndexCtx.indexBody(S, Parent, ParentDC);
208  return true;
209  }
210 };
211 
212 } // anonymous namespace
213 
215  const NamedDecl *Parent,
216  const DeclContext *DC,
217  bool isBase,
218  bool isIBType) {
219  if (!TInfo || TInfo->getTypeLoc().isNull())
220  return;
221 
222  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
223 }
224 
226  const NamedDecl *Parent,
227  const DeclContext *DC,
228  bool isBase,
229  bool isIBType) {
230  if (TL.isNull())
231  return;
232 
233  if (!DC)
234  DC = Parent->getLexicalDeclContext();
235  TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
236 }
237 
239  const NamedDecl *Parent,
240  const DeclContext *DC) {
241  if (!NNS)
242  return;
243 
244  if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
245  indexNestedNameSpecifierLoc(Prefix, Parent, DC);
246 
247  if (!DC)
248  DC = Parent->getLexicalDeclContext();
249  SourceLocation Loc = NNS.getLocalBeginLoc();
250 
251  switch (NNS.getNestedNameSpecifier()->getKind()) {
255  break;
256 
258  handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
259  Loc, Parent, DC, SymbolRoleSet());
260  break;
262  handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
263  Loc, Parent, DC, SymbolRoleSet());
264  break;
265 
268  indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
269  break;
270  }
271 }
272 
274  ArrayRef<SymbolRelation> Relations) {
275  if (!shouldIndex(D))
276  return;
277  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
278  return;
279 
280  if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {
281  if (D->isThisDeclarationADefinition()) {
282  indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
283  if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
284  for (const auto &I : CXXRD->bases()) {
285  indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
286  }
287  }
288  indexDeclContext(D);
289  }
290  }
291 }
ObjCInterfaceDecl * getIFaceDecl() const
Definition: TypeLoc.h:1045
TemplateTypeParmDecl * getDecl() const
Definition: TypeLoc.h:739
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:502
Wrapper for source info for tag types.
Definition: TypeLoc.h:707
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:409
Stmt - This represents one statement.
Definition: Stmt.h:68
Microsoft&#39;s &#39;__super&#39; specifier, stored as a CXXRecordDecl* of the class it appeared in...
Represents a qualified type name for which the type name is dependent.
Definition: Type.h:5468
NestedNameSpecifier * getQualifier() const
Retrieve the qualification on this type.
Definition: Type.h:5486
void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, const DeclContext *DC=nullptr, bool isBase=false, bool isIBType=false)
The base class of the type hierarchy.
Definition: Type.h:1472
Wrapper for source info for typedefs.
Definition: TypeLoc.h:670
A container of type source information.
Definition: Type.h:6373
const DeclContext * getParentFunctionOrMethod() const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext...
Definition: DeclBase.cpp:286
SourceLocation getLocalBeginLoc() const
Retrieve the location of the beginning of this component of the nested-name-specifier.
An identifier, stored as an IdentifierInfo*.
TRY_TO(TraverseType(T->getPointeeType()))
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:7153
A namespace, stored as a NamespaceDecl*.
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
bool hasDefinition() const
Definition: DeclCXX.h:541
Represents a parameter to a function.
Definition: Decl.h:1595
std::vector< const NamedDecl * > lookupDependentName(const DeclarationName &Name, llvm::function_ref< bool(const NamedDecl *ND)> Filter)
Performs an imprecise lookup of a dependent name in this class.
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:58
A C++ nested-name-specifier augmented with source location information.
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known...
bool isDefinition() const
True if the tag was defined in this type specifier.
Definition: TypeLoc.cpp:298
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
Definition: Type.h:5167
bool isFunctionLocalSymbol(const Decl *D)
Definition: IndexSymbol.cpp:53
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
Wrapper for source info for injected class names of class templates.
Definition: TypeLoc.h:681
SourceLocation getProtocolLoc(unsigned i) const
Definition: TypeLoc.h:974
NamespaceAliasDecl * getAsNamespaceAlias() const
Retrieve the namespace alias stored in this nested name specifier.
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition: Decl.h:737
bool shouldIndexFunctionLocalSymbols() const
bool isNull() const
Definition: TypeLoc.h:120
CXXRecordDecl * getDecl() const
Definition: TypeLoc.h:686
Wrapper for source info for ObjC interfaces.
Definition: TypeLoc.h:1040
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC)...
Definition: DeclBase.h:843
SourceLocation getNameLoc() const
Definition: TypeLoc.h:1049
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
NodeId Parent
Definition: ASTDiff.cpp:192
unsigned SymbolRoleSet
Definition: IndexSymbol.h:130
ObjCProtocolDecl * getProtocol(unsigned i) const
Definition: TypeLoc.h:984
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1758
SourceLocation getNameLoc() const
Definition: TypeLoc.h:2234
bool isTransparentTag() const
Determines if this typedef shares a name and spelling location with its underlying tag type...
Definition: Decl.h:3175
TagDecl * getDecl() const
Definition: TypeLoc.h:711
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
Declaration of a template type parameter.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:563
DeclContext * getDeclContext()
Definition: DeclBase.h:439
CXXRecordDecl * getDefinition() const
Definition: DeclCXX.h:534
const IdentifierInfo * getIdentifier() const
Retrieve the type named by the typename specifier as an identifier.
Definition: Type.h:5493
NestedNameSpecifierLoc getPrefix() const
Return the prefix of this nested-name-specifier.
Represents a C++ template name within the type system.
Definition: TemplateName.h:192
A namespace alias, stored as a NamespaceAliasDecl*.
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:1766
bool handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, SymbolRoleSet Roles=SymbolRoleSet(), ArrayRef< SymbolRelation > Relations=None, const Expr *RefE=nullptr, const Decl *RefD=nullptr)
SourceLocation getTemplateNameLoc() const
Definition: TypeLoc.h:2134
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3239
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
bool shouldIndexImplicitInstantiation() const
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition: Decl.h:3466
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3091
Dataflow Directional Tag Classes.
NestedNameSpecifier * getNestedNameSpecifier() const
Retrieve the nested-name-specifier to which this instance refers.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1303
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:402
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:132
QualType getUnderlyingType() const
Definition: Decl.h:3146
The name of a declaration.
A type that was preceded by the &#39;template&#39; keyword, stored as a Type*.
void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC=nullptr, bool isBase=false, bool isIBType=false)
TypedefNameDecl * getTypedefNameDecl() const
Definition: TypeLoc.h:674
SourceLocation getTemplateNameLoc() const
Definition: TypeLoc.h:1620
void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const NamedDecl *Parent, const DeclContext *DC=nullptr)
void indexTagDecl(const TagDecl *D, ArrayRef< SymbolRelation > Relations=None)
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:700
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:244
bool isThisDeclarationADefinition() const
Return true if this declaration is a completion definition of the type.
Definition: Decl.h:3339
Represents a C++ struct/union/class.
Definition: DeclCXX.h:254
unsigned getNumProtocols() const
Definition: TypeLoc.h:970
Declaration of a class template.
TypeLoc getTypeLoc() const
For a nested-name-specifier that refers to a type, retrieve the type with source-location information...
SourceLocation getNameLoc() const
Definition: TypeLoc.h:523
Represents a type template specialization; the template must be a class template, a type alias templa...
Definition: Type.h:5104
void indexBody(const Stmt *S, const NamedDecl *Parent, const DeclContext *DC=nullptr)
Definition: IndexBody.cpp:471
Wrapper for template type parameters.
Definition: TypeLoc.h:734
This represents a decl that may have a name.
Definition: Decl.h:223
The global specifier &#39;::&#39;. There is no stored value.