blob: 98c46621f038d92d6ab8dcb34a63ccc60a846f86 [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.
Douglas Gregorc21c7e92011-01-25 19:13:18 +000080void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
81 SourceLocation Loc) {
John McCall7eb914b2010-05-16 02:09:32 +000082 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); \
Douglas Gregorc21c7e92011-01-25 19:13:18 +000088 TLCasted.initializeLocal(Context, Loc); \
John McCall7eb914b2010-05-16 02:09:32 +000089 TL = TLCasted.getNextTypeLoc(); \
90 if (!TL) return; \
91 continue; \
92 }
93#include "clang/AST/TypeLocNodes.def"
94 }
95 }
Argyrios Kyrtzidisb17166c2009-08-19 01:27:32 +000096}
John McCalled976492009-12-04 22:46:56 +000097
Abramo Bagnarae4aec0e2010-05-21 21:12:12 +000098SourceLocation 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
John McCalled976492009-12-04 22:46:56 +0000134namespace {
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}
John McCallcfb708c2010-01-13 20:03:27 +0000162
163// Reimplemented to account for GNU/C++ extension
164// typeof unary-expression
165// where there are no parentheses.
Abramo Bagnarabd054db2010-05-20 10:00:11 +0000166SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
John McCallcfb708c2010-01-13 20:03:27 +0000167 if (getRParenLoc().isValid())
168 return SourceRange(getTypeofLoc(), getRParenLoc());
169 else
170 return SourceRange(getTypeofLoc(),
171 getUnderlyingExpr()->getSourceRange().getEnd());
172}
Douglas Gregorddf889a2010-01-18 18:04:31 +0000173
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;
Chris Lattner3f59c972010-12-25 23:25:43 +0000191 case BuiltinType::WChar_S:
192 case BuiltinType::WChar_U:
Douglas Gregorddf889a2010-01-18 18:04:31 +0000193 return TST_wchar;
Richard Smith34b41d92011-02-20 03:19:35 +0000194
Douglas Gregorddf889a2010-01-18 18:04:31 +0000195 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:
Douglas Gregord038f362010-01-18 20:37:56 +0000207 case BuiltinType::Float:
208 case BuiltinType::Double:
209 case BuiltinType::LongDouble:
Douglas Gregorddf889a2010-01-18 18:04:31 +0000210 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}
Abramo Bagnara140a2bd2010-12-13 22:27:55 +0000225
Abramo Bagnara723df242010-12-14 22:11:44 +0000226TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
Abramo Bagnara140a2bd2010-12-13 22:27:55 +0000227 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
228 TL = PTL->getInnerLoc();
229 return TL;
230}
Douglas Gregorc21c7e92011-01-25 19:13:18 +0000231
Douglas Gregor239cbb02011-03-01 03:11:17 +0000232void 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
Douglas Gregor2494dd02011-03-01 01:34:45 +0000240void 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
Douglas Gregorc21c7e92011-01-25 19:13:18 +0000249void 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