clang  3.7.0
TypeLoc.cpp
Go to the documentation of this file.
1 //===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
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 // This file defines the TypeLoc subclasses implementations.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/TypeLoc.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Expr.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
20 using namespace clang;
21 
22 static const unsigned TypeLocMaxDataAlign = llvm::alignOf<void *>();
23 
24 //===----------------------------------------------------------------------===//
25 // TypeLoc Implementation
26 //===----------------------------------------------------------------------===//
27 
28 namespace {
29  class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
30  public:
31 #define ABSTRACT_TYPELOC(CLASS, PARENT)
32 #define TYPELOC(CLASS, PARENT) \
33  SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
34  return TyLoc.getLocalSourceRange(); \
35  }
36 #include "clang/AST/TypeLocNodes.def"
37  };
38 }
39 
40 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
41  if (TL.isNull()) return SourceRange();
42  return TypeLocRanger().Visit(TL);
43 }
44 
45 namespace {
46  class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
47  public:
48 #define ABSTRACT_TYPELOC(CLASS, PARENT)
49 #define TYPELOC(CLASS, PARENT) \
50  unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
51  return TyLoc.getLocalDataAlignment(); \
52  }
53 #include "clang/AST/TypeLocNodes.def"
54  };
55 }
56 
57 /// \brief Returns the alignment of the type source info data block.
59  if (Ty.isNull()) return 1;
60  return TypeAligner().Visit(TypeLoc(Ty, nullptr));
61 }
62 
63 namespace {
64  class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
65  public:
66 #define ABSTRACT_TYPELOC(CLASS, PARENT)
67 #define TYPELOC(CLASS, PARENT) \
68  unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
69  return TyLoc.getLocalDataSize(); \
70  }
71 #include "clang/AST/TypeLocNodes.def"
72  };
73 }
74 
75 /// \brief Returns the size of the type source info data block.
77  unsigned Total = 0;
78  TypeLoc TyLoc(Ty, nullptr);
79  unsigned MaxAlign = 1;
80  while (!TyLoc.isNull()) {
81  unsigned Align = getLocalAlignmentForType(TyLoc.getType());
82  MaxAlign = std::max(Align, MaxAlign);
83  Total = llvm::RoundUpToAlignment(Total, Align);
84  Total += TypeSizer().Visit(TyLoc);
85  TyLoc = TyLoc.getNextTypeLoc();
86  }
87  Total = llvm::RoundUpToAlignment(Total, MaxAlign);
88  return Total;
89 }
90 
91 namespace {
92  class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
93  public:
94 #define ABSTRACT_TYPELOC(CLASS, PARENT)
95 #define TYPELOC(CLASS, PARENT) \
96  TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
97  return TyLoc.getNextTypeLoc(); \
98  }
99 #include "clang/AST/TypeLocNodes.def"
100  };
101 }
102 
103 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
104 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
105 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
106  return NextLoc().Visit(TL);
107 }
108 
109 /// \brief Initializes a type location, and all of its children
110 /// recursively, as if the entire tree had been written in the
111 /// given location.
112 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
113  SourceLocation Loc) {
114  while (true) {
115  switch (TL.getTypeLocClass()) {
116 #define ABSTRACT_TYPELOC(CLASS, PARENT)
117 #define TYPELOC(CLASS, PARENT) \
118  case CLASS: { \
119  CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
120  TLCasted.initializeLocal(Context, Loc); \
121  TL = TLCasted.getNextTypeLoc(); \
122  if (!TL) return; \
123  continue; \
124  }
125 #include "clang/AST/TypeLocNodes.def"
126  }
127  }
128 }
129 
130 namespace {
131  class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
132  TypeLoc Source;
133  public:
134  TypeLocCopier(TypeLoc source) : Source(source) { }
135 
136 #define ABSTRACT_TYPELOC(CLASS, PARENT)
137 #define TYPELOC(CLASS, PARENT) \
138  void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \
139  dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \
140  }
141 #include "clang/AST/TypeLocNodes.def"
142  };
143 }
144 
145 
146 void TypeLoc::copy(TypeLoc other) {
147  assert(getFullDataSize() == other.getFullDataSize());
148 
149  // If both data pointers are aligned to the maximum alignment, we
150  // can memcpy because getFullDataSize() accurately reflects the
151  // layout of the data.
152  if (reinterpret_cast<uintptr_t>(Data)
153  == llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(Data),
155  reinterpret_cast<uintptr_t>(other.Data)
156  == llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(other.Data),
158  memcpy(Data, other.Data, getFullDataSize());
159  return;
160  }
161 
162  // Copy each of the pieces.
163  TypeLoc TL(getType(), Data);
164  do {
165  TypeLocCopier(other).Visit(TL);
166  other = other.getNextTypeLoc();
167  } while ((TL = TL.getNextTypeLoc()));
168 }
169 
171  TypeLoc Cur = *this;
172  TypeLoc LeftMost = Cur;
173  while (true) {
174  switch (Cur.getTypeLocClass()) {
175  case Elaborated:
176  LeftMost = Cur;
177  break;
178  case FunctionProto:
180  ->hasTrailingReturn()) {
181  LeftMost = Cur;
182  break;
183  }
184  /* Fall through */
185  case FunctionNoProto:
186  case ConstantArray:
187  case DependentSizedArray:
188  case IncompleteArray:
189  case VariableArray:
190  // FIXME: Currently QualifiedTypeLoc does not have a source range
191  case Qualified:
192  Cur = Cur.getNextTypeLoc();
193  continue;
194  default:
195  if (!Cur.getLocalSourceRange().getBegin().isInvalid())
196  LeftMost = Cur;
197  Cur = Cur.getNextTypeLoc();
198  if (Cur.isNull())
199  break;
200  continue;
201  } // switch
202  break;
203  } // while
204  return LeftMost.getLocalSourceRange().getBegin();
205 }
206 
208  TypeLoc Cur = *this;
209  TypeLoc Last;
210  while (true) {
211  switch (Cur.getTypeLocClass()) {
212  default:
213  if (!Last)
214  Last = Cur;
215  return Last.getLocalSourceRange().getEnd();
216  case Paren:
217  case ConstantArray:
218  case DependentSizedArray:
219  case IncompleteArray:
220  case VariableArray:
221  case FunctionNoProto:
222  Last = Cur;
223  break;
224  case FunctionProto:
226  Last = TypeLoc();
227  else
228  Last = Cur;
229  break;
230  case Pointer:
231  case BlockPointer:
232  case MemberPointer:
233  case LValueReference:
234  case RValueReference:
235  case PackExpansion:
236  if (!Last)
237  Last = Cur;
238  break;
239  case Qualified:
240  case Elaborated:
241  break;
242  }
243  Cur = Cur.getNextTypeLoc();
244  }
245 }
246 
247 
248 namespace {
249  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
250  // Overload resolution does the real work for us.
251  static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
252  static bool isTypeSpec(TypeLoc _) { return false; }
253 
254 #define ABSTRACT_TYPELOC(CLASS, PARENT)
255 #define TYPELOC(CLASS, PARENT) \
256  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
257  return isTypeSpec(TyLoc); \
258  }
259 #include "clang/AST/TypeLocNodes.def"
260  };
261 }
262 
263 
264 /// \brief Determines if the given type loc corresponds to a
265 /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
266 /// the type hierarchy, this is made somewhat complicated.
267 ///
268 /// There are a lot of types that currently use TypeSpecTypeLoc
269 /// because it's a convenient base class. Ideally we would not accept
270 /// those here, but ideally we would have better implementations for
271 /// them.
272 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
273  if (TL.getType().hasLocalQualifiers()) return false;
274  return TSTChecker().Visit(TL);
275 }
276 
277 // Reimplemented to account for GNU/C++ extension
278 // typeof unary-expression
279 // where there are no parentheses.
281  if (getRParenLoc().isValid())
283  else
284  return SourceRange(getTypeofLoc(),
285  getUnderlyingExpr()->getSourceRange().getEnd());
286 }
287 
288 
290  if (needsExtraLocalData())
291  return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
292  switch (getTypePtr()->getKind()) {
293  case BuiltinType::Void:
294  return TST_void;
295  case BuiltinType::Bool:
296  return TST_bool;
297  case BuiltinType::Char_U:
298  case BuiltinType::Char_S:
299  return TST_char;
300  case BuiltinType::Char16:
301  return TST_char16;
302  case BuiltinType::Char32:
303  return TST_char32;
304  case BuiltinType::WChar_S:
305  case BuiltinType::WChar_U:
306  return TST_wchar;
307  case BuiltinType::UChar:
308  case BuiltinType::UShort:
309  case BuiltinType::UInt:
310  case BuiltinType::ULong:
311  case BuiltinType::ULongLong:
312  case BuiltinType::UInt128:
313  case BuiltinType::SChar:
314  case BuiltinType::Short:
315  case BuiltinType::Int:
316  case BuiltinType::Long:
317  case BuiltinType::LongLong:
318  case BuiltinType::Int128:
319  case BuiltinType::Half:
320  case BuiltinType::Float:
321  case BuiltinType::Double:
322  case BuiltinType::LongDouble:
323  llvm_unreachable("Builtin type needs extra local data!");
324  // Fall through, if the impossible happens.
325 
326  case BuiltinType::NullPtr:
327  case BuiltinType::Overload:
328  case BuiltinType::Dependent:
329  case BuiltinType::BoundMember:
330  case BuiltinType::UnknownAny:
331  case BuiltinType::ARCUnbridgedCast:
332  case BuiltinType::PseudoObject:
333  case BuiltinType::ObjCId:
334  case BuiltinType::ObjCClass:
335  case BuiltinType::ObjCSel:
336  case BuiltinType::OCLImage1d:
337  case BuiltinType::OCLImage1dArray:
338  case BuiltinType::OCLImage1dBuffer:
339  case BuiltinType::OCLImage2d:
340  case BuiltinType::OCLImage2dArray:
341  case BuiltinType::OCLImage3d:
342  case BuiltinType::OCLSampler:
343  case BuiltinType::OCLEvent:
344  case BuiltinType::BuiltinFn:
345  return TST_unspecified;
346  }
347 
348  llvm_unreachable("Invalid BuiltinType Kind!");
349 }
350 
351 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
352  while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
353  TL = PTL.getInnerLoc();
354  return TL;
355 }
356 
358  if (auto attributedLoc = getAs<AttributedTypeLoc>()) {
359  if (attributedLoc.getAttrKind() == AttributedType::attr_nullable ||
360  attributedLoc.getAttrKind() == AttributedType::attr_nonnull ||
361  attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified)
362  return attributedLoc.getAttrNameLoc();
363  }
364 
365  return SourceLocation();
366 }
367 
369  SourceLocation Loc) {
373  for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
374  setTypeArgTInfo(i,
375  Context.getTrivialTypeSourceInfo(
376  getTypePtr()->getTypeArgsAsWritten()[i], Loc));
377  }
380  for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
381  setProtocolLoc(i, Loc);
382 }
383 
385  SourceLocation Loc) {
387  ::initializeLocal(Context, Loc);
389  getUnderlyingType(), Loc);
390 }
391 
393  SourceLocation Loc) {
396  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
397  setQualifierLoc(Builder.getWithLocInContext(Context));
398 }
399 
401  SourceLocation Loc) {
404  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
405  setQualifierLoc(Builder.getWithLocInContext(Context));
406  setNameLoc(Loc);
407 }
408 
409 void
411  SourceLocation Loc) {
413  if (getTypePtr()->getQualifier()) {
415  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
416  setQualifierLoc(Builder.getWithLocInContext(Context));
417  } else {
419  }
421  setTemplateNameLoc(Loc);
422  setLAngleLoc(Loc);
423  setRAngleLoc(Loc);
425  getTypePtr()->getArgs(),
426  getArgInfos(), Loc);
427 }
428 
430  unsigned NumArgs,
431  const TemplateArgument *Args,
432  TemplateArgumentLocInfo *ArgInfos,
433  SourceLocation Loc) {
434  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
435  switch (Args[i].getKind()) {
437  llvm_unreachable("Impossible TemplateArgument");
438 
442  ArgInfos[i] = TemplateArgumentLocInfo();
443  break;
444 
446  ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
447  break;
448 
450  ArgInfos[i] = TemplateArgumentLocInfo(
451  Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
452  Loc));
453  break;
454 
458  TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
460  Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
461  else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
462  Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
463 
464  ArgInfos[i] = TemplateArgumentLocInfo(
465  Builder.getWithLocInContext(Context), Loc,
467  : Loc);
468  break;
469  }
470 
472  ArgInfos[i] = TemplateArgumentLocInfo();
473  break;
474  }
475  }
476 }
Kind getKind() const
Definition: Type.h:2006
Defines the clang::ASTContext interface.
SourceLocation getEnd() const
T getAs() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
Definition: TypeLoc.h:64
static unsigned getFullDataSizeForType(QualType Ty)
Returns the size of type source info data block for the given type.
Definition: TypeLoc.cpp:76
void initializeLocal(ASTContext &Context, SourceLocation Loc)
Definition: TypeLoc.h:1608
void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R)
Make a new nested-name-specifier from incomplete source-location information.
SourceLocation findNullabilityLoc() const
Definition: TypeLoc.cpp:357
RetTy Visit(TypeLoc TyLoc)
WrittenBuiltinSpecs & getWrittenBuiltinSpecs()
Definition: TypeLoc.h:523
void setTemplateKeywordLoc(SourceLocation Loc)
Definition: TypeLoc.h:1862
Expr * getUnderlyingExpr() const
Definition: TypeLoc.h:1619
void initializeLocal(ASTContext &Context, SourceLocation Loc)
Definition: TypeLoc.cpp:410
Represents an empty template argument, e.g., one that has not been deduced.
Definition: TemplateBase.h:45
TypeSpecifierType
Specifies the kind of type.
Definition: Specifiers.h:39
void * Data
Definition: TypeLoc.h:45
void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc)
Definition: TypeLoc.h:1727
A reasonable base class for TypeLocs that correspond to types that are written as a type-specifier...
Definition: TypeLoc.h:477
void setTypeArgTInfo(unsigned i, TypeSourceInfo *TInfo)
Definition: TypeLoc.h:879
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:40
bool isNull() const
Definition: TypeLoc.h:95
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:89
A C++ nested-name-specifier augmented with source location information.
Represents a dependent template name that cannot be resolved prior to template instantiation.
Definition: TemplateName.h:440
void setElaboratedKeywordLoc(SourceLocation Loc)
Definition: TypeLoc.h:1776
SourceRange getLocalSourceRange() const
Get the local source range.
Definition: TypeLoc.h:134
unsigned getNumProtocols() const
Definition: TypeLoc.h:898
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:170
void setRAngleLoc(SourceLocation Loc)
Definition: TypeLoc.h:1883
void initializeLocal(ASTContext &Context, SourceLocation Loc)
Definition: TypeLoc.cpp:392
bool needsExtraLocalData() const
Definition: TypeLoc.h:530
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context...
void setProtocolLoc(unsigned i, SourceLocation Loc)
Definition: TypeLoc.h:906
bool isInvalid() const
T castAs() const
Convert to the specified TypeLoc type, asserting that this TypeLoc is of the desired type...
Definition: TypeLoc.h:53
Class that aids in the construction of nested-name-specifiers along with source-location information ...
DependentTemplateName * getAsDependentTemplateName() const
Retrieve the underlying dependent template name structure, if any.
Definition: TemplateName.h:284
TypeLoc getNextTypeLoc() const
Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the TypeLoc is a PointerLoc and next Typ...
Definition: TypeLoc.h:145
ASTContext * Context
bool hasLocalQualifiers() const
Determine whether this particular QualType instance has any qualifiers, without looking through any t...
Definition: Type.h:670
void setTemplateNameLoc(SourceLocation Loc)
Definition: TypeLoc.h:1869
void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc)
Definition: TypeLoc.h:1843
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:218
Represents a C++ template name within the type system.
Definition: TemplateName.h:175
Defines the clang::TypeLoc interface and its subclasses.
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:107
bool hasTrailingReturn() const
Definition: Type.h:3238
TemplateName getAsTemplateOrTemplatePattern() const
Retrieve the template argument as a template name; if the argument is a pack expansion, return the pattern as a template name.
Definition: TemplateBase.h:271
void setHasBaseTypeAsWritten(bool HasBaseType)
Definition: TypeLoc.h:925
void initializeLocal(ASTContext &Context, SourceLocation Loc)
Definition: TypeLoc.cpp:384
void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc)
Definition: TypeLoc.h:1785
TypeSourceInfo * UnderlyingTInfo
Definition: TypeLoc.h:1568
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:465
void initializeLocal(ASTContext &Context, SourceLocation Loc)
Definition: TypeLoc.cpp:400
SourceLocation getEndLoc() const
Get the end source location.
Definition: TypeLoc.cpp:207
void setLAngleLoc(SourceLocation Loc)
Definition: TypeLoc.h:1876
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
void initializeLocal(ASTContext &Context, SourceLocation Loc)
Definition: TypeLoc.cpp:368
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location, which defaults to the empty location.
void setProtocolRAngleLoc(SourceLocation Loc)
Definition: TypeLoc.h:894
unsigned getNumTypeArgs() const
Definition: TypeLoc.h:870
static const unsigned TypeLocMaxDataAlign
Definition: TypeLoc.cpp:22
void setElaboratedKeywordLoc(SourceLocation Loc)
Definition: TypeLoc.h:1831
TypeLocClass getTypeLocClass() const
Definition: TypeLoc.h:90
TypeSpecifierType getWrittenTypeSpec() const
Definition: TypeLoc.cpp:289
SourceLocation getBegin() const
QualifiedTemplateName * getAsQualifiedTemplateName() const
Retrieve the underlying qualified template name structure, if any.
Definition: TemplateName.h:278
void setTypeArgsLAngleLoc(SourceLocation Loc)
Definition: TypeLoc.h:859
Represents a template argument.
Definition: TemplateBase.h:39
QualType getAsType() const
Retrieve the type for a type template argument.
Definition: TemplateBase.h:240
Represents a template name that was expressed as a qualified name.
Definition: TemplateName.h:383
QualType getUnderlyingType() const
Definition: TypeLoc.h:1631
void setNameLoc(SourceLocation Loc)
Definition: TypeLoc.h:1795
SourceRange getSourceRange() const LLVM_READONLY
Get the full source range.
Definition: TypeLoc.h:127
static void initializeArgLocs(ASTContext &Context, unsigned NumArgs, const TemplateArgument *Args, TemplateArgumentLocInfo *ArgInfos, SourceLocation Loc)
Definition: TypeLoc.cpp:429
void setTypeArgsRAngleLoc(SourceLocation Loc)
Definition: TypeLoc.h:866
The template argument is a type.
Definition: TemplateBase.h:47
unsigned getFullDataSize() const
Returns the size of the type source info data block.
Definition: TypeLoc.h:139
BoundNodesTreeBuilder *const Builder
static unsigned getLocalAlignmentForType(QualType Ty)
Returns the alignment of type source info data block for the given type.
Definition: TypeLoc.cpp:58
Location information for a TemplateArgument.
Definition: TemplateBase.h:364
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:739
void copy(TypeLoc other)
Copies the other type loc into this one.
Definition: TypeLoc.cpp:146
void setProtocolLAngleLoc(SourceLocation Loc)
Definition: TypeLoc.h:887
SourceRange getLocalSourceRange() const
Definition: TypeLoc.cpp:280
A trivial tuple used to represent a source range.
bool isNull() const
isNull - Return true if this QualType doesn't point to a type yet.
Definition: Type.h:633
void setElaboratedKeywordLoc(SourceLocation Loc)
Definition: TypeLoc.h:1718