TypeLoc.cpp revision 239cbb023c8da689e7722f7146914eed9755e368
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 "llvm/Support/raw_ostream.h"
15#include "clang/AST/TypeLocVisitor.h"
16#include "clang/AST/Expr.h"
17#include "llvm/Support/ErrorHandling.h"
18using namespace clang;
19
20//===----------------------------------------------------------------------===//
21// TypeLoc Implementation
22//===----------------------------------------------------------------------===//
23
24namespace {
25  class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
26  public:
27#define ABSTRACT_TYPELOC(CLASS, PARENT)
28#define TYPELOC(CLASS, PARENT) \
29    SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
30      return TyLoc.getLocalSourceRange(); \
31    }
32#include "clang/AST/TypeLocNodes.def"
33  };
34}
35
36SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
37  if (TL.isNull()) return SourceRange();
38  return TypeLocRanger().Visit(TL);
39}
40
41namespace {
42  class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
43  public:
44#define ABSTRACT_TYPELOC(CLASS, PARENT)
45#define TYPELOC(CLASS, PARENT) \
46    unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
47      return TyLoc.getFullDataSize(); \
48    }
49#include "clang/AST/TypeLocNodes.def"
50  };
51}
52
53/// \brief Returns the size of the type source info data block.
54unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
55  if (Ty.isNull()) return 0;
56  return TypeSizer().Visit(TypeLoc(Ty, 0));
57}
58
59namespace {
60  class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
61  public:
62#define ABSTRACT_TYPELOC(CLASS, PARENT)
63#define TYPELOC(CLASS, PARENT) \
64    TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
65      return TyLoc.getNextTypeLoc(); \
66    }
67#include "clang/AST/TypeLocNodes.def"
68  };
69}
70
71/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
72/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
73TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
74  return NextLoc().Visit(TL);
75}
76
77/// \brief Initializes a type location, and all of its children
78/// recursively, as if the entire tree had been written in the
79/// given location.
80void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
81                             SourceLocation Loc) {
82  while (true) {
83    switch (TL.getTypeLocClass()) {
84#define ABSTRACT_TYPELOC(CLASS, PARENT)
85#define TYPELOC(CLASS, PARENT)        \
86    case CLASS: {                     \
87      CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
88      TLCasted.initializeLocal(Context, Loc);  \
89      TL = TLCasted.getNextTypeLoc(); \
90      if (!TL) return;                \
91      continue;                       \
92    }
93#include "clang/AST/TypeLocNodes.def"
94    }
95  }
96}
97
98SourceLocation TypeLoc::getBeginLoc() const {
99  TypeLoc Cur = *this;
100  while (true) {
101    switch (Cur.getTypeLocClass()) {
102    // FIXME: Currently QualifiedTypeLoc does not have a source range
103    // case Qualified:
104    case Elaborated:
105      break;
106    default:
107      TypeLoc Next = Cur.getNextTypeLoc();
108      if (Next.isNull()) break;
109      Cur = Next;
110      continue;
111    }
112    break;
113  }
114  return Cur.getLocalSourceRange().getBegin();
115}
116
117SourceLocation TypeLoc::getEndLoc() const {
118  TypeLoc Cur = *this;
119  while (true) {
120    switch (Cur.getTypeLocClass()) {
121    default:
122      break;
123    case Qualified:
124    case Elaborated:
125      Cur = Cur.getNextTypeLoc();
126      continue;
127    }
128    break;
129  }
130  return Cur.getLocalSourceRange().getEnd();
131}
132
133
134namespace {
135  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
136    // Overload resolution does the real work for us.
137    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
138    static bool isTypeSpec(TypeLoc _) { return false; }
139
140#define ABSTRACT_TYPELOC(CLASS, PARENT)
141#define TYPELOC(CLASS, PARENT) \
142    bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
143      return isTypeSpec(TyLoc); \
144    }
145#include "clang/AST/TypeLocNodes.def"
146  };
147}
148
149
150/// \brief Determines if the given type loc corresponds to a
151/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
152/// the type hierarchy, this is made somewhat complicated.
153///
154/// There are a lot of types that currently use TypeSpecTypeLoc
155/// because it's a convenient base class.  Ideally we would not accept
156/// those here, but ideally we would have better implementations for
157/// them.
158bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
159  if (TL->getType().hasLocalQualifiers()) return false;
160  return TSTChecker().Visit(*TL);
161}
162
163// Reimplemented to account for GNU/C++ extension
164//     typeof unary-expression
165// where there are no parentheses.
166SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
167  if (getRParenLoc().isValid())
168    return SourceRange(getTypeofLoc(), getRParenLoc());
169  else
170    return SourceRange(getTypeofLoc(),
171                       getUnderlyingExpr()->getSourceRange().getEnd());
172}
173
174
175TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
176  if (needsExtraLocalData())
177    return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
178  else {
179    switch (getTypePtr()->getKind()) {
180    case BuiltinType::Void:
181      return TST_void;
182    case BuiltinType::Bool:
183      return TST_bool;
184    case BuiltinType::Char_U:
185    case BuiltinType::Char_S:
186      return TST_char;
187    case BuiltinType::Char16:
188      return TST_char16;
189    case BuiltinType::Char32:
190      return TST_char32;
191    case BuiltinType::WChar_S:
192    case BuiltinType::WChar_U:
193      return TST_wchar;
194
195    case BuiltinType::UChar:
196    case BuiltinType::UShort:
197    case BuiltinType::UInt:
198    case BuiltinType::ULong:
199    case BuiltinType::ULongLong:
200    case BuiltinType::UInt128:
201    case BuiltinType::SChar:
202    case BuiltinType::Short:
203    case BuiltinType::Int:
204    case BuiltinType::Long:
205    case BuiltinType::LongLong:
206    case BuiltinType::Int128:
207    case BuiltinType::Float:
208    case BuiltinType::Double:
209    case BuiltinType::LongDouble:
210      llvm_unreachable("Builtin type needs extra local data!");
211      // Fall through, if the impossible happens.
212
213    case BuiltinType::NullPtr:
214    case BuiltinType::Overload:
215    case BuiltinType::Dependent:
216    case BuiltinType::ObjCId:
217    case BuiltinType::ObjCClass:
218    case BuiltinType::ObjCSel:
219      return TST_unspecified;
220    }
221  }
222
223  return TST_unspecified;
224}
225
226TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
227  while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
228    TL = PTL->getInnerLoc();
229  return TL;
230}
231
232void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
233                                        SourceLocation Loc) {
234  setKeywordLoc(Loc);
235  NestedNameSpecifierLocBuilder Builder;
236  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
237  setQualifierLoc(Builder.getWithLocInContext(Context));
238}
239
240void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
241                                           SourceLocation Loc) {
242  setKeywordLoc(Loc);
243  NestedNameSpecifierLocBuilder Builder;
244  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
245  setQualifierLoc(Builder.getWithLocInContext(Context));
246  setNameLoc(Loc);
247}
248
249void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
250                                                      unsigned NumArgs,
251                                                  const TemplateArgument *Args,
252                                              TemplateArgumentLocInfo *ArgInfos,
253                                                      SourceLocation Loc) {
254  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
255    switch (Args[i].getKind()) {
256    case TemplateArgument::Null:
257    case TemplateArgument::Declaration:
258    case TemplateArgument::Integral:
259    case TemplateArgument::Pack:
260    case TemplateArgument::Expression:
261      // FIXME: Can we do better for declarations and integral values?
262      ArgInfos[i] = TemplateArgumentLocInfo();
263      break;
264
265    case TemplateArgument::Type:
266      ArgInfos[i] = TemplateArgumentLocInfo(
267                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
268                                                           Loc));
269      break;
270
271    case TemplateArgument::Template:
272      ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc,
273                                            SourceLocation());
274      break;
275
276    case TemplateArgument::TemplateExpansion:
277      ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc);
278      break;
279    }
280  }
281}
282
283