blob: c987b9bb9b1f7ab0f4f0f71781f07f4fde308087 [file] [log] [blame]
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +00001//===--- 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
John McCall34a04472009-10-15 03:50:32 +000014#include "llvm/Support/raw_ostream.h"
Argyrios Kyrtzidis0c411802009-09-29 21:27:32 +000015#include "clang/AST/TypeLocVisitor.h"
John McCallcfb708c2010-01-13 20:03:27 +000016#include "clang/AST/Expr.h"
Douglas Gregorddf889a2010-01-18 18:04:31 +000017#include "llvm/Support/ErrorHandling.h"
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000018using namespace clang;
19
20//===----------------------------------------------------------------------===//
21// TypeLoc Implementation
22//===----------------------------------------------------------------------===//
23
Argyrios Kyrtzidis68006af2009-09-29 19:40:46 +000024namespace {
John McCall51bd8032009-10-18 01:05:36 +000025 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
26 public:
27#define ABSTRACT_TYPELOC(CLASS, PARENT)
John McCall34a04472009-10-15 03:50:32 +000028#define TYPELOC(CLASS, PARENT) \
John McCall51bd8032009-10-18 01:05:36 +000029 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
Abramo Bagnarabd054db2010-05-20 10:00:11 +000030 return TyLoc.getLocalSourceRange(); \
John McCall51bd8032009-10-18 01:05:36 +000031 }
Argyrios Kyrtzidis68006af2009-09-29 19:40:46 +000032#include "clang/AST/TypeLocNodes.def"
John McCall51bd8032009-10-18 01:05:36 +000033 };
Argyrios Kyrtzidis68006af2009-09-29 19:40:46 +000034}
35
Abramo Bagnarabd054db2010-05-20 10:00:11 +000036SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
John McCall51bd8032009-10-18 01:05:36 +000037 if (TL.isNull()) return SourceRange();
38 return TypeLocRanger().Visit(TL);
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000039}
40
41namespace {
John McCall51bd8032009-10-18 01:05:36 +000042 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
43 public:
44#define ABSTRACT_TYPELOC(CLASS, PARENT)
John McCall34a04472009-10-15 03:50:32 +000045#define TYPELOC(CLASS, PARENT) \
John McCall51bd8032009-10-18 01:05:36 +000046 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
47 return TyLoc.getFullDataSize(); \
48 }
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000049#include "clang/AST/TypeLocNodes.def"
John McCall51bd8032009-10-18 01:05:36 +000050 };
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000051}
52
53/// \brief Returns the size of the type source info data block.
John McCall34a04472009-10-15 03:50:32 +000054unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
55 if (Ty.isNull()) return 0;
56 return TypeSizer().Visit(TypeLoc(Ty, 0));
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000057}
58
59namespace {
John McCall51bd8032009-10-18 01:05:36 +000060 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 }
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000067#include "clang/AST/TypeLocNodes.def"
John McCall51bd8032009-10-18 01:05:36 +000068 };
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000069}
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".
John McCall51bd8032009-10-18 01:05:36 +000073TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
74 return NextLoc().Visit(TL);
John McCall4ce74bd2009-10-16 22:31:57 +000075}
76
John McCall51bd8032009-10-18 01:05:36 +000077/// \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.
John McCall4ce74bd2009-10-16 22:31:57 +000080void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) {
John McCall7eb914b2010-05-16 02:09:32 +000081 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 }
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000095}
John McCalled976492009-12-04 22:46:56 +000096
Craig Silverstein45ab4b52010-11-18 08:32:02 +000097/// \brief Initializes a type location by copying all its data from
98/// another type location of the same type.
99void TypeLoc::initializeFullCopyImpl(TypeLoc TL, TypeLoc Other) {
100 assert(TL.getType() == Other.getType() && "Must copy from same type");
101 memcpy(TL.getOpaqueData(), Other.getOpaqueData(), TL.getFullDataSize());
102}
103
Abramo Bagnarae4aec0e2010-05-21 21:12:12 +0000104SourceLocation TypeLoc::getBeginLoc() const {
105 TypeLoc Cur = *this;
106 while (true) {
107 switch (Cur.getTypeLocClass()) {
108 // FIXME: Currently QualifiedTypeLoc does not have a source range
109 // case Qualified:
110 case Elaborated:
111 break;
112 default:
113 TypeLoc Next = Cur.getNextTypeLoc();
114 if (Next.isNull()) break;
115 Cur = Next;
116 continue;
117 }
118 break;
119 }
120 return Cur.getLocalSourceRange().getBegin();
121}
122
123SourceLocation TypeLoc::getEndLoc() const {
124 TypeLoc Cur = *this;
125 while (true) {
126 switch (Cur.getTypeLocClass()) {
127 default:
128 break;
129 case Qualified:
130 case Elaborated:
131 Cur = Cur.getNextTypeLoc();
132 continue;
133 }
134 break;
135 }
136 return Cur.getLocalSourceRange().getEnd();
137}
138
139
John McCalled976492009-12-04 22:46:56 +0000140namespace {
141 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
142 // Overload resolution does the real work for us.
143 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
144 static bool isTypeSpec(TypeLoc _) { return false; }
145
146#define ABSTRACT_TYPELOC(CLASS, PARENT)
147#define TYPELOC(CLASS, PARENT) \
148 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
149 return isTypeSpec(TyLoc); \
150 }
151#include "clang/AST/TypeLocNodes.def"
152 };
153}
154
155
156/// \brief Determines if the given type loc corresponds to a
157/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
158/// the type hierarchy, this is made somewhat complicated.
159///
160/// There are a lot of types that currently use TypeSpecTypeLoc
161/// because it's a convenient base class. Ideally we would not accept
162/// those here, but ideally we would have better implementations for
163/// them.
164bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
165 if (TL->getType().hasLocalQualifiers()) return false;
166 return TSTChecker().Visit(*TL);
167}
John McCallcfb708c2010-01-13 20:03:27 +0000168
169// Reimplemented to account for GNU/C++ extension
170// typeof unary-expression
171// where there are no parentheses.
Abramo Bagnarabd054db2010-05-20 10:00:11 +0000172SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
John McCallcfb708c2010-01-13 20:03:27 +0000173 if (getRParenLoc().isValid())
174 return SourceRange(getTypeofLoc(), getRParenLoc());
175 else
176 return SourceRange(getTypeofLoc(),
177 getUnderlyingExpr()->getSourceRange().getEnd());
178}
Douglas Gregorddf889a2010-01-18 18:04:31 +0000179
180
181TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
182 if (needsExtraLocalData())
183 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
184 else {
185 switch (getTypePtr()->getKind()) {
186 case BuiltinType::Void:
187 return TST_void;
188 case BuiltinType::Bool:
189 return TST_bool;
190 case BuiltinType::Char_U:
191 case BuiltinType::Char_S:
192 return TST_char;
193 case BuiltinType::Char16:
194 return TST_char16;
195 case BuiltinType::Char32:
196 return TST_char32;
197 case BuiltinType::WChar:
198 return TST_wchar;
Douglas Gregorddf889a2010-01-18 18:04:31 +0000199 case BuiltinType::UndeducedAuto:
200 return TST_auto;
201
202 case BuiltinType::UChar:
203 case BuiltinType::UShort:
204 case BuiltinType::UInt:
205 case BuiltinType::ULong:
206 case BuiltinType::ULongLong:
207 case BuiltinType::UInt128:
208 case BuiltinType::SChar:
209 case BuiltinType::Short:
210 case BuiltinType::Int:
211 case BuiltinType::Long:
212 case BuiltinType::LongLong:
213 case BuiltinType::Int128:
Douglas Gregord038f362010-01-18 20:37:56 +0000214 case BuiltinType::Float:
215 case BuiltinType::Double:
216 case BuiltinType::LongDouble:
Douglas Gregorddf889a2010-01-18 18:04:31 +0000217 llvm_unreachable("Builtin type needs extra local data!");
218 // Fall through, if the impossible happens.
219
220 case BuiltinType::NullPtr:
221 case BuiltinType::Overload:
222 case BuiltinType::Dependent:
223 case BuiltinType::ObjCId:
224 case BuiltinType::ObjCClass:
225 case BuiltinType::ObjCSel:
226 return TST_unspecified;
227 }
228 }
229
230 return TST_unspecified;
231}
Abramo Bagnara140a2bd2010-12-13 22:27:55 +0000232
233TypeLoc TypeLoc::IgnoreParens() const {
234 TypeLoc TL = *this;
235 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
236 TL = PTL->getInnerLoc();
237 return TL;
238}
239