clang  6.0.0svn
IndexTypeSourceInfo.cpp
Go to the documentation of this file.
1 //===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "IndexingContext.h"
12 
13 using namespace clang;
14 using namespace index;
15 
16 namespace {
17 
18 class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
19  IndexingContext &IndexCtx;
20  const NamedDecl *Parent;
21  const DeclContext *ParentDC;
22  bool IsBase;
24 
26 
27 public:
28  TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
29  const DeclContext *DC, bool isBase, bool isIBType)
30  : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
31  if (IsBase) {
32  assert(Parent);
33  Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
34  }
35  if (isIBType) {
36  assert(Parent);
37  Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
38  }
39  }
40 
41  bool shouldWalkTypesOfTypeLocs() const { return false; }
42 
43 #define TRY_TO(CALL_EXPR) \
44  do { \
45  if (!CALL_EXPR) \
46  return false; \
47  } while (0)
48 
49  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
50  SourceLocation Loc = TL.getNameLoc();
52  if (ND->isTransparentTag()) {
53  TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl();
54  return IndexCtx.handleReference(Underlying, Loc, Parent,
55  ParentDC, SymbolRoleSet(), Relations);
56  }
57  if (IsBase) {
58  TRY_TO(IndexCtx.handleReference(ND, Loc,
59  Parent, ParentDC, SymbolRoleSet()));
60  if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {
61  TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC,
62  (unsigned)SymbolRole::Implicit,
63  Relations));
64  }
65  } else {
66  TRY_TO(IndexCtx.handleReference(ND, Loc,
67  Parent, ParentDC, SymbolRoleSet(),
68  Relations));
69  }
70  return true;
71  }
72 
73  bool traverseParamVarHelper(ParmVarDecl *D) {
74  TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
75  if (D->getTypeSourceInfo())
76  TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
77  return true;
78  }
79 
80  bool TraverseParmVarDecl(ParmVarDecl *D) {
81  // Avoid visiting default arguments from the definition that were already
82  // visited in the declaration.
83  // FIXME: A free function definition can have default arguments.
84  // Avoiding double visitaiton of default arguments should be handled by the
85  // visitor probably with a bit in the AST to indicate if the attached
86  // default argument was 'inherited' or written in source.
87  if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
88  if (FD->isThisDeclarationADefinition()) {
89  return traverseParamVarHelper(D);
90  }
91  }
92 
93  return base::TraverseParmVarDecl(D);
94  }
95 
96  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
97  IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
98  return true;
99  }
100 
101  bool VisitTagTypeLoc(TagTypeLoc TL) {
102  TagDecl *D = TL.getDecl();
103  if (D->getParentFunctionOrMethod())
104  return true;
105 
106  if (TL.isDefinition()) {
107  IndexCtx.indexTagDecl(D);
108  return true;
109  }
110 
111  return IndexCtx.handleReference(D, TL.getNameLoc(),
112  Parent, ParentDC, SymbolRoleSet(),
113  Relations);
114  }
115 
116  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
117  return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
118  Parent, ParentDC, SymbolRoleSet(), Relations);
119  }
120 
121  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
122  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
123  IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
124  Parent, ParentDC, SymbolRoleSet(), Relations);
125  }
126  return true;
127  }
128 
129  template<typename TypeLocType>
130  bool HandleTemplateSpecializationTypeLoc(TypeLocType TL) {
131  if (const auto *T = TL.getTypePtr()) {
132  if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
133  if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
134  IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
135  Parent, ParentDC, SymbolRoleSet(), Relations);
136  } else {
137  if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
138  IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
139  Parent, ParentDC, SymbolRoleSet(), Relations);
140  }
141  }
142  return true;
143  }
144 
145  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
146  return HandleTemplateSpecializationTypeLoc(TL);
147  }
148 
149  bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {
150  return HandleTemplateSpecializationTypeLoc(TL);
151  }
152 
153  bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
154  const DependentNameType *DNT = TL.getTypePtr();
155  const NestedNameSpecifier *NNS = DNT->getQualifier();
156  const Type *T = NNS->getAsType();
157  if (!T)
158  return true;
159  const TemplateSpecializationType *TST =
161  if (!TST)
162  return true;
163  TemplateName TN = TST->getTemplateName();
164  const ClassTemplateDecl *TD =
165  dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
166  if (!TD)
167  return true;
168  CXXRecordDecl *RD = TD->getTemplatedDecl();
169  if (!RD->hasDefinition())
170  return true;
171  RD = RD->getDefinition();
172  DeclarationName Name(DNT->getIdentifier());
173  std::vector<const NamedDecl *> Symbols = RD->lookupDependentName(
174  Name, [](const NamedDecl *ND) { return isa<TypeDecl>(ND); });
175  if (Symbols.size() != 1)
176  return true;
177  return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent,
178  ParentDC, SymbolRoleSet(), Relations);
179  }
180 
181  bool TraverseStmt(Stmt *S) {
182  IndexCtx.indexBody(S, Parent, ParentDC);
183  return true;
184  }
185 };
186 
187 } // anonymous namespace
188 
190  const NamedDecl *Parent,
191  const DeclContext *DC,
192  bool isBase,
193  bool isIBType) {
194  if (!TInfo || TInfo->getTypeLoc().isNull())
195  return;
196 
197  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
198 }
199 
201  const NamedDecl *Parent,
202  const DeclContext *DC,
203  bool isBase,
204  bool isIBType) {
205  if (TL.isNull())
206  return;
207 
208  if (!DC)
209  DC = Parent->getLexicalDeclContext();
210  TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
211 }
212 
214  const NamedDecl *Parent,
215  const DeclContext *DC) {
216  if (!NNS)
217  return;
218 
219  if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
220  indexNestedNameSpecifierLoc(Prefix, Parent, DC);
221 
222  if (!DC)
223  DC = Parent->getLexicalDeclContext();
224  SourceLocation Loc = NNS.getLocalBeginLoc();
225 
226  switch (NNS.getNestedNameSpecifier()->getKind()) {
230  break;
231 
233  handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
234  Loc, Parent, DC, SymbolRoleSet());
235  break;
237  handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
238  Loc, Parent, DC, SymbolRoleSet());
239  break;
240 
243  indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
244  break;
245  }
246 }
247 
249  ArrayRef<SymbolRelation> Relations) {
250  if (!shouldIndex(D))
251  return;
252  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
253  return;
254 
255  if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {
256  if (D->isThisDeclarationADefinition()) {
257  indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
258  if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
259  for (const auto &I : CXXRD->bases()) {
260  indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
261  }
262  }
263  indexDeclContext(D);
264  }
265  }
266 }
ObjCInterfaceDecl * getIFaceDecl() const
Definition: TypeLoc.h:1123
Wrapper for source info for tag types.
Definition: TypeLoc.h:702
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:404
Stmt - This represents one statement.
Definition: Stmt.h:66
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:4851
NestedNameSpecifier * getQualifier() const
Retrieve the qualification on this type.
Definition: Type.h:4870
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:1353
Wrapper for source info for typedefs.
Definition: TypeLoc.h:665
A container of type source information.
Definition: Decl.h:86
const DeclContext * getParentFunctionOrMethod() const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext...
Definition: DeclBase.cpp:243
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:6307
A namespace, stored as a NamespaceDecl*.
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
bool hasDefinition() const
Definition: DeclCXX.h:738
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1514
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:56
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...
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
Definition: Type.h:4565
bool isFunctionLocalSymbol(const Decl *D)
Definition: IndexSymbol.cpp:52
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
SourceLocation getProtocolLoc(unsigned i) const
Definition: TypeLoc.h:1052
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:746
bool isNull() const
Definition: TypeLoc.h:118
Wrapper for source info for ObjC interfaces.
Definition: TypeLoc.h:1118
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC)...
Definition: DeclBase.h:820
SourceLocation getNameLoc() const
Definition: TypeLoc.h:1127
bool isDefinition() const
True if the tag was defined in this type specifier.
Definition: TypeLoc.h:709
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:116
ObjCProtocolDecl * getProtocol(unsigned i) const
Definition: TypeLoc.h:1062
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1590
SourceLocation getNameLoc() const
Definition: TypeLoc.h:2084
bool isTransparentTag() const
Determines if this typedef shares a name and spelling location with its underlying tag type...
Definition: Decl.h:2874
TagDecl * getDecl() const
Definition: TypeLoc.h:706
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
const FunctionProtoType * T
DeclContext * getDeclContext()
Definition: DeclBase.h:425
CXXRecordDecl * getDefinition() const
Definition: DeclCXX.h:731
const IdentifierInfo * getIdentifier() const
Retrieve the type named by the typename specifier as an identifier.
Definition: Type.h:4877
NestedNameSpecifierLoc getPrefix() const
Return the prefix of this nested-name-specifier.
Represents a C++ template name within the type system.
Definition: TemplateName.h:178
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:1594
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)
Encodes a location in the source.
TagDecl - Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:2938
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition: Decl.h:3198
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2796
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:1252
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:399
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:130
QualType getUnderlyingType() const
Definition: Decl.h:2847
DeclarationName - 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:669
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:708
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:239
bool isThisDeclarationADefinition() const
isThisDeclarationADefinition() - Return true if this declaration is a completion definition of the ty...
Definition: Decl.h:3085
Represents a C++ struct/union/class.
Definition: DeclCXX.h:299
unsigned getNumProtocols() const
Definition: TypeLoc.h:1048
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:518
Represents a type template specialization; the template must be a class template, a type alias templa...
Definition: Type.h:4495
bool shouldIndexImplicitTemplateInsts() const
void indexBody(const Stmt *S, const NamedDecl *Parent, const DeclContext *DC=nullptr)
Definition: IndexBody.cpp:445
NamedDecl - This represents a decl with a name.
Definition: Decl.h:245
The global specifier &#39;::&#39;. There is no stored value.