blob: 03d40309f53a692a34ed682ba3e4fefe5afc6f92 [file] [log] [blame]
Guy Benyei7f92f2d2012-12-18 14:30:41 +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
14#include "clang/AST/TypeLoc.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Expr.h"
17#include "clang/AST/TypeLocVisitor.h"
18#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Support/raw_ostream.h"
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// TypeLoc Implementation
24//===----------------------------------------------------------------------===//
25
26namespace {
27 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
28 public:
29#define ABSTRACT_TYPELOC(CLASS, PARENT)
30#define TYPELOC(CLASS, PARENT) \
31 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
32 return TyLoc.getLocalSourceRange(); \
33 }
34#include "clang/AST/TypeLocNodes.def"
35 };
36}
37
38SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
39 if (TL.isNull()) return SourceRange();
40 return TypeLocRanger().Visit(TL);
41}
42
43namespace {
44 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
45 public:
46#define ABSTRACT_TYPELOC(CLASS, PARENT)
47#define TYPELOC(CLASS, PARENT) \
48 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
Manuel Klimek20387ef2013-06-07 11:27:53 +000049 return TyLoc.getFullDataSize(); \
Guy Benyei7f92f2d2012-12-18 14:30:41 +000050 }
51#include "clang/AST/TypeLocNodes.def"
52 };
53}
54
55/// \brief Returns the size of the type source info data block.
56unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
Manuel Klimek20387ef2013-06-07 11:27:53 +000057 if (Ty.isNull()) return 0;
58 return TypeSizer().Visit(TypeLoc(Ty, 0));
Guy Benyei7f92f2d2012-12-18 14:30:41 +000059}
60
61namespace {
62 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
63 public:
64#define ABSTRACT_TYPELOC(CLASS, PARENT)
65#define TYPELOC(CLASS, PARENT) \
66 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
67 return TyLoc.getNextTypeLoc(); \
68 }
69#include "clang/AST/TypeLocNodes.def"
70 };
71}
72
73/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
74/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
75TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
76 return NextLoc().Visit(TL);
77}
78
79/// \brief Initializes a type location, and all of its children
80/// recursively, as if the entire tree had been written in the
81/// given location.
82void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
83 SourceLocation Loc) {
84 while (true) {
85 switch (TL.getTypeLocClass()) {
86#define ABSTRACT_TYPELOC(CLASS, PARENT)
87#define TYPELOC(CLASS, PARENT) \
88 case CLASS: { \
David Blaikie39e6ab42013-02-18 22:06:02 +000089 CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
Guy Benyei7f92f2d2012-12-18 14:30:41 +000090 TLCasted.initializeLocal(Context, Loc); \
91 TL = TLCasted.getNextTypeLoc(); \
92 if (!TL) return; \
93 continue; \
94 }
95#include "clang/AST/TypeLocNodes.def"
96 }
97 }
98}
99
100SourceLocation TypeLoc::getBeginLoc() const {
101 TypeLoc Cur = *this;
102 TypeLoc LeftMost = Cur;
103 while (true) {
104 switch (Cur.getTypeLocClass()) {
105 case Elaborated:
106 LeftMost = Cur;
107 break;
108 case FunctionProto:
David Blaikie39e6ab42013-02-18 22:06:02 +0000109 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
110 ->hasTrailingReturn()) {
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000111 LeftMost = Cur;
112 break;
113 }
114 /* Fall through */
115 case FunctionNoProto:
116 case ConstantArray:
117 case DependentSizedArray:
118 case IncompleteArray:
119 case VariableArray:
120 // FIXME: Currently QualifiedTypeLoc does not have a source range
121 case Qualified:
122 Cur = Cur.getNextTypeLoc();
123 continue;
124 default:
125 if (!Cur.getLocalSourceRange().getBegin().isInvalid())
126 LeftMost = Cur;
127 Cur = Cur.getNextTypeLoc();
128 if (Cur.isNull())
129 break;
130 continue;
131 } // switch
132 break;
133 } // while
134 return LeftMost.getLocalSourceRange().getBegin();
135}
136
137SourceLocation TypeLoc::getEndLoc() const {
138 TypeLoc Cur = *this;
139 TypeLoc Last;
140 while (true) {
141 switch (Cur.getTypeLocClass()) {
142 default:
143 if (!Last)
144 Last = Cur;
145 return Last.getLocalSourceRange().getEnd();
146 case Paren:
147 case ConstantArray:
148 case DependentSizedArray:
149 case IncompleteArray:
150 case VariableArray:
151 case FunctionNoProto:
152 Last = Cur;
153 break;
154 case FunctionProto:
David Blaikie39e6ab42013-02-18 22:06:02 +0000155 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000156 Last = TypeLoc();
157 else
158 Last = Cur;
159 break;
160 case Pointer:
161 case BlockPointer:
162 case MemberPointer:
163 case LValueReference:
164 case RValueReference:
165 case PackExpansion:
166 if (!Last)
167 Last = Cur;
168 break;
169 case Qualified:
170 case Elaborated:
171 break;
172 }
173 Cur = Cur.getNextTypeLoc();
174 }
175}
176
177
178namespace {
179 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
180 // Overload resolution does the real work for us.
181 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
182 static bool isTypeSpec(TypeLoc _) { return false; }
183
184#define ABSTRACT_TYPELOC(CLASS, PARENT)
185#define TYPELOC(CLASS, PARENT) \
186 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
187 return isTypeSpec(TyLoc); \
188 }
189#include "clang/AST/TypeLocNodes.def"
190 };
191}
192
193
194/// \brief Determines if the given type loc corresponds to a
195/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
196/// the type hierarchy, this is made somewhat complicated.
197///
198/// There are a lot of types that currently use TypeSpecTypeLoc
199/// because it's a convenient base class. Ideally we would not accept
200/// those here, but ideally we would have better implementations for
201/// them.
David Blaikie65124fe2013-02-21 01:47:08 +0000202bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
203 if (TL.getType().hasLocalQualifiers()) return false;
204 return TSTChecker().Visit(TL);
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000205}
206
207// Reimplemented to account for GNU/C++ extension
208// typeof unary-expression
209// where there are no parentheses.
210SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
211 if (getRParenLoc().isValid())
212 return SourceRange(getTypeofLoc(), getRParenLoc());
213 else
214 return SourceRange(getTypeofLoc(),
215 getUnderlyingExpr()->getSourceRange().getEnd());
216}
217
218
219TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
220 if (needsExtraLocalData())
221 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
222 switch (getTypePtr()->getKind()) {
223 case BuiltinType::Void:
224 return TST_void;
225 case BuiltinType::Bool:
226 return TST_bool;
227 case BuiltinType::Char_U:
228 case BuiltinType::Char_S:
229 return TST_char;
230 case BuiltinType::Char16:
231 return TST_char16;
232 case BuiltinType::Char32:
233 return TST_char32;
234 case BuiltinType::WChar_S:
235 case BuiltinType::WChar_U:
236 return TST_wchar;
237 case BuiltinType::UChar:
238 case BuiltinType::UShort:
239 case BuiltinType::UInt:
240 case BuiltinType::ULong:
241 case BuiltinType::ULongLong:
242 case BuiltinType::UInt128:
243 case BuiltinType::SChar:
244 case BuiltinType::Short:
245 case BuiltinType::Int:
246 case BuiltinType::Long:
247 case BuiltinType::LongLong:
248 case BuiltinType::Int128:
249 case BuiltinType::Half:
250 case BuiltinType::Float:
251 case BuiltinType::Double:
252 case BuiltinType::LongDouble:
253 llvm_unreachable("Builtin type needs extra local data!");
254 // Fall through, if the impossible happens.
255
256 case BuiltinType::NullPtr:
257 case BuiltinType::Overload:
258 case BuiltinType::Dependent:
259 case BuiltinType::BoundMember:
260 case BuiltinType::UnknownAny:
261 case BuiltinType::ARCUnbridgedCast:
262 case BuiltinType::PseudoObject:
263 case BuiltinType::ObjCId:
264 case BuiltinType::ObjCClass:
265 case BuiltinType::ObjCSel:
Guy Benyeib13621d2012-12-18 14:38:23 +0000266 case BuiltinType::OCLImage1d:
267 case BuiltinType::OCLImage1dArray:
268 case BuiltinType::OCLImage1dBuffer:
269 case BuiltinType::OCLImage2d:
270 case BuiltinType::OCLImage2dArray:
271 case BuiltinType::OCLImage3d:
Guy Benyei21f18c42013-02-07 10:55:47 +0000272 case BuiltinType::OCLSampler:
Guy Benyeie6b9d802013-01-20 12:31:11 +0000273 case BuiltinType::OCLEvent:
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000274 case BuiltinType::BuiltinFn:
275 return TST_unspecified;
276 }
277
278 llvm_unreachable("Invalid BuiltinType Kind!");
279}
280
281TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
David Blaikie39e6ab42013-02-18 22:06:02 +0000282 while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
283 TL = PTL.getInnerLoc();
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000284 return TL;
285}
286
287void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
288 SourceLocation Loc) {
289 setElaboratedKeywordLoc(Loc);
290 NestedNameSpecifierLocBuilder Builder;
291 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
292 setQualifierLoc(Builder.getWithLocInContext(Context));
293}
294
295void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
296 SourceLocation Loc) {
297 setElaboratedKeywordLoc(Loc);
298 NestedNameSpecifierLocBuilder Builder;
299 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
300 setQualifierLoc(Builder.getWithLocInContext(Context));
301 setNameLoc(Loc);
302}
303
304void
305DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
306 SourceLocation Loc) {
307 setElaboratedKeywordLoc(Loc);
308 if (getTypePtr()->getQualifier()) {
309 NestedNameSpecifierLocBuilder Builder;
310 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
311 setQualifierLoc(Builder.getWithLocInContext(Context));
312 } else {
313 setQualifierLoc(NestedNameSpecifierLoc());
314 }
315 setTemplateKeywordLoc(Loc);
316 setTemplateNameLoc(Loc);
317 setLAngleLoc(Loc);
318 setRAngleLoc(Loc);
319 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
320 getTypePtr()->getArgs(),
321 getArgInfos(), Loc);
322}
323
324void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
325 unsigned NumArgs,
326 const TemplateArgument *Args,
327 TemplateArgumentLocInfo *ArgInfos,
328 SourceLocation Loc) {
329 for (unsigned i = 0, e = NumArgs; i != e; ++i) {
330 switch (Args[i].getKind()) {
331 case TemplateArgument::Null:
332 case TemplateArgument::Declaration:
333 case TemplateArgument::Integral:
334 case TemplateArgument::NullPtr:
335 llvm_unreachable("Impossible TemplateArgument");
336
337 case TemplateArgument::Expression:
338 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
339 break;
340
341 case TemplateArgument::Type:
342 ArgInfos[i] = TemplateArgumentLocInfo(
343 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
344 Loc));
345 break;
346
347 case TemplateArgument::Template:
348 case TemplateArgument::TemplateExpansion: {
349 NestedNameSpecifierLocBuilder Builder;
350 TemplateName Template = Args[i].getAsTemplate();
351 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
352 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
353 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
354 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
355
356 ArgInfos[i] = TemplateArgumentLocInfo(
357 Builder.getWithLocInContext(Context),
358 Loc,
359 Args[i].getKind() == TemplateArgument::Template
360 ? SourceLocation()
361 : Loc);
362 break;
363 }
364
365 case TemplateArgument::Pack:
366 ArgInfos[i] = TemplateArgumentLocInfo();
367 break;
368 }
369 }
370}