TypeLoc.cpp revision ba6f816d633e3b88c38c6896c2d78d19489650f2
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(TypeLoc TL, SourceLocation Loc) {
81  while (true) {
82    switch (TL.getTypeLocClass()) {
83#define ABSTRACT_TYPELOC(CLASS, PARENT)
84#define TYPELOC(CLASS, PARENT)        \
85    case CLASS: {                     \
86      CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
87      TLCasted.initializeLocal(Loc);  \
88      TL = TLCasted.getNextTypeLoc(); \
89      if (!TL) return;                \
90      continue;                       \
91    }
92#include "clang/AST/TypeLocNodes.def"
93    }
94  }
95}
96
97SourceLocation TypeLoc::getBeginLoc() const {
98  TypeLoc Cur = *this;
99  while (true) {
100    switch (Cur.getTypeLocClass()) {
101    // FIXME: Currently QualifiedTypeLoc does not have a source range
102    // case Qualified:
103    case Elaborated:
104      break;
105    default:
106      TypeLoc Next = Cur.getNextTypeLoc();
107      if (Next.isNull()) break;
108      Cur = Next;
109      continue;
110    }
111    break;
112  }
113  return Cur.getLocalSourceRange().getBegin();
114}
115
116SourceLocation TypeLoc::getEndLoc() const {
117  TypeLoc Cur = *this;
118  while (true) {
119    switch (Cur.getTypeLocClass()) {
120    default:
121      break;
122    case Qualified:
123    case Elaborated:
124      Cur = Cur.getNextTypeLoc();
125      continue;
126    }
127    break;
128  }
129  return Cur.getLocalSourceRange().getEnd();
130}
131
132
133namespace {
134  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
135    // Overload resolution does the real work for us.
136    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
137    static bool isTypeSpec(TypeLoc _) { return false; }
138
139#define ABSTRACT_TYPELOC(CLASS, PARENT)
140#define TYPELOC(CLASS, PARENT) \
141    bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
142      return isTypeSpec(TyLoc); \
143    }
144#include "clang/AST/TypeLocNodes.def"
145  };
146}
147
148
149/// \brief Determines if the given type loc corresponds to a
150/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
151/// the type hierarchy, this is made somewhat complicated.
152///
153/// There are a lot of types that currently use TypeSpecTypeLoc
154/// because it's a convenient base class.  Ideally we would not accept
155/// those here, but ideally we would have better implementations for
156/// them.
157bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
158  if (TL->getType().hasLocalQualifiers()) return false;
159  return TSTChecker().Visit(*TL);
160}
161
162// Reimplemented to account for GNU/C++ extension
163//     typeof unary-expression
164// where there are no parentheses.
165SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
166  if (getRParenLoc().isValid())
167    return SourceRange(getTypeofLoc(), getRParenLoc());
168  else
169    return SourceRange(getTypeofLoc(),
170                       getUnderlyingExpr()->getSourceRange().getEnd());
171}
172
173
174TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
175  if (needsExtraLocalData())
176    return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
177  else {
178    switch (getTypePtr()->getKind()) {
179    case BuiltinType::Void:
180      return TST_void;
181    case BuiltinType::Bool:
182      return TST_bool;
183    case BuiltinType::Char_U:
184    case BuiltinType::Char_S:
185      return TST_char;
186    case BuiltinType::Char16:
187      return TST_char16;
188    case BuiltinType::Char32:
189      return TST_char32;
190    case BuiltinType::WChar:
191      return TST_wchar;
192    case BuiltinType::UndeducedAuto:
193      return TST_auto;
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