clang  5.0.0
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  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
130  if (const TemplateSpecializationType *T = TL.getTypePtr()) {
131  if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
132  if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
133  IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
134  Parent, ParentDC, SymbolRoleSet(), Relations);
135  } else {
136  if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
137  IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
138  Parent, ParentDC, SymbolRoleSet(), Relations);
139  }
140  }
141  return true;
142  }
143 
144  bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
145  const DependentNameType *DNT = TL.getTypePtr();
146  const NestedNameSpecifier *NNS = DNT->getQualifier();
147  const Type *T = NNS->getAsType();
148  if (!T)
149  return true;
150  const TemplateSpecializationType *TST =
152  if (!TST)
153  return true;
154  TemplateName TN = TST->getTemplateName();
155  const ClassTemplateDecl *TD =
156  dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
157  if (!TD)
158  return true;
159  CXXRecordDecl *RD = TD->getTemplatedDecl();
160  if (!RD->hasDefinition())
161  return true;
162  RD = RD->getDefinition();
164  std::vector<const NamedDecl *> Symbols = RD->lookupDependentName(
165  Name, [](const NamedDecl *ND) { return isa<TypeDecl>(ND); });
166  if (Symbols.size() != 1)
167  return true;
168  return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent,
169  ParentDC, SymbolRoleSet(), Relations);
170  }
171 
172  bool TraverseStmt(Stmt *S) {
173  IndexCtx.indexBody(S, Parent, ParentDC);
174  return true;
175  }
176 };
177 
178 } // anonymous namespace
179 
181  const NamedDecl *Parent,
182  const DeclContext *DC,
183  bool isBase,
184  bool isIBType) {
185  if (!TInfo || TInfo->getTypeLoc().isNull())
186  return;
187 
188  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
189 }
190 
192  const NamedDecl *Parent,
193  const DeclContext *DC,
194  bool isBase,
195  bool isIBType) {
196  if (TL.isNull())
197  return;
198 
199  if (!DC)
200  DC = Parent->getLexicalDeclContext();
201  TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
202 }
203 
205  const NamedDecl *Parent,
206  const DeclContext *DC) {
207  if (!NNS)
208  return;
209 
210  if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
211  indexNestedNameSpecifierLoc(Prefix, Parent, DC);
212 
213  if (!DC)
214  DC = Parent->getLexicalDeclContext();
215  SourceLocation Loc = NNS.getLocalBeginLoc();
216 
217  switch (NNS.getNestedNameSpecifier()->getKind()) {
221  break;
222 
225  Loc, Parent, DC, SymbolRoleSet());
226  break;
229  Loc, Parent, DC, SymbolRoleSet());
230  break;
231 
234  indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
235  break;
236  }
237 }
238 
240  ArrayRef<SymbolRelation> Relations) {
241  if (!shouldIndex(D))
242  return;
244  return;
245 
246  if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {
247  if (D->isThisDeclarationADefinition()) {
249  if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
250  for (const auto &I : CXXRD->bases()) {
251  indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
252  }
253  }
254  indexDeclContext(D);
255  }
256  }
257 }
Wrapper for source info for tag types.
Definition: TypeLoc.h:675
SourceLocation getNameLoc() const
Definition: TypeLoc.h:1950
Stmt - This represents one statement.
Definition: Stmt.h:60
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known...
Microsoft's '__super' 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:4642
void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, const DeclContext *DC=nullptr, bool isBase=false, bool isIBType=false)
NestedNameSpecifierLoc getPrefix() const
Return the prefix of this nested-name-specifier.
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
QualType getUnderlyingType() const
Definition: Decl.h:2727
const DeclContext * getParentFunctionOrMethod() const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext...
Definition: DeclBase.cpp:222
bool hasDefinition() const
Definition: DeclCXX.h:702
The base class of the type hierarchy.
Definition: Type.h:1303
Wrapper for source info for typedefs.
Definition: TypeLoc.h:638
A container of type source information.
Definition: Decl.h:62
An identifier, stored as an IdentifierInfo*.
TRY_TO(TraverseType(T->getPointeeType()))
A namespace, stored as a NamespaceDecl*.
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1434
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition: Decl.h:697
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:40
const IdentifierInfo * getIdentifier() const
Retrieve the type named by the typename specifier as an identifier.
Definition: Type.h:4669
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:1552
bool isDefinition() const
True if the tag was defined in this type specifier.
Definition: TypeLoc.h:682
bool isNull() const
Definition: TypeLoc.h:102
A C++ nested-name-specifier augmented with source location information.
bool isFunctionLocalSymbol(const Decl *D)
Definition: IndexSymbol.cpp:52
CXXRecordDecl * getDefinition() const
Definition: DeclCXX.h:695
NestedNameSpecifier * getQualifier() const
Retrieve the qualification on this type.
Definition: Type.h:4662
unsigned getNumProtocols() const
Definition: TypeLoc.h:1013
bool isThisDeclarationADefinition() const
isThisDeclarationADefinition() - Return true if this declaration is a completion definition of the ty...
Definition: Decl.h:2954
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition: Decl.h:3067
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
Definition: Type.h:4382
Wrapper for source info for ObjC interfaces.
Definition: TypeLoc.h:1083
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC)...
Definition: DeclBase.h:796
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
detail::InMemoryDirectory::const_iterator I
TypedefNameDecl * getTypedefNameDecl() const
Definition: TypeLoc.h:642
unsigned SymbolRoleSet
Definition: IndexSymbol.h:113
TypeLoc getTypeLoc() const
For a nested-name-specifier that refers to a type, retrieve the type with source-location information...
TagDecl * getDecl() const
Definition: TypeLoc.h:679
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
bool indexDeclContext(const DeclContext *DC)
Definition: IndexDecl.cpp:722
DeclContext * getDeclContext()
Definition: DeclBase.h:416
Represents a C++ template name within the type system.
Definition: TemplateName.h:176
A namespace alias, stored as a NamespaceAliasDecl*.
bool isTransparentTag() const
Determines if this typedef shares a name and spelling location with its underlying tag type...
Definition: Decl.h:2752
SourceLocation getTemplateNameLoc() const
Definition: TypeLoc.h:1613
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:114
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)
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:661
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:222
Encodes a location in the source.
TagDecl - Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:2816
SourceLocation getLocalBeginLoc() const
Retrieve the location of the beginning of this component of the nested-name-specifier.
SourceLocation getNameLoc() const
Definition: TypeLoc.h:502
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
NamespaceAliasDecl * getAsNamespaceAlias() const
Retrieve the namespace alias stored in this nested name specifier.
SourceLocation getNameLoc() const
Definition: TypeLoc.h:1092
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2682
bool shouldIndex(const Decl *D)
bool handleDecl(const Decl *D, SymbolRoleSet Roles=SymbolRoleSet(), ArrayRef< SymbolRelation > Relations=None)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1215
StringRef Name
Definition: USRFinder.cpp:123
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:378
DeclarationName - The name of a declaration.
ObjCInterfaceDecl * getIFaceDecl() const
Definition: TypeLoc.h:1088
A type that was preceded by the 'template' keyword, stored as a Type*.
void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC=nullptr, bool isBase=false, bool isIBType=false)
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:6042
void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const NamedDecl *Parent, const DeclContext *DC=nullptr)
void indexTagDecl(const TagDecl *D, ArrayRef< SymbolRelation > Relations=None)
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1548
bool shouldIndexFunctionLocalSymbols() const
ObjCProtocolDecl * getProtocol(unsigned i) const
Definition: TypeLoc.h:1026
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:386
SourceLocation getProtocolLoc(unsigned i) const
Definition: TypeLoc.h:1017
Represents a C++ struct/union/class.
Definition: DeclCXX.h:267
NestedNameSpecifier * getNestedNameSpecifier() const
Retrieve the nested-name-specifier to which this instance refers.
Declaration of a class template.
Represents a type template specialization; the template must be a class template, a type alias templa...
Definition: Type.h:4297
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
The global specifier '::'. There is no stored value.