1 //===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the TypeLoc subclasses implementations.
12 //===----------------------------------------------------------------------===//
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"
20 using namespace clang;
22 //===----------------------------------------------------------------------===//
23 // TypeLoc Implementation
24 //===----------------------------------------------------------------------===//
27 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
29 #define ABSTRACT_TYPELOC(CLASS, PARENT)
30 #define TYPELOC(CLASS, PARENT) \
31 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
32 return TyLoc.getLocalSourceRange(); \
34 #include "clang/AST/TypeLocNodes.def"
38 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
39 if (TL.isNull()) return SourceRange();
40 return TypeLocRanger().Visit(TL);
44 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
46 #define ABSTRACT_TYPELOC(CLASS, PARENT)
47 #define TYPELOC(CLASS, PARENT) \
48 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
49 return TyLoc.getFullDataSize(); \
51 #include "clang/AST/TypeLocNodes.def"
55 /// \brief Returns the size of the type source info data block.
56 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
57 if (Ty.isNull()) return 0;
58 return TypeSizer().Visit(TypeLoc(Ty, 0));
62 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
64 #define ABSTRACT_TYPELOC(CLASS, PARENT)
65 #define TYPELOC(CLASS, PARENT) \
66 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
67 return TyLoc.getNextTypeLoc(); \
69 #include "clang/AST/TypeLocNodes.def"
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".
75 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
76 return NextLoc().Visit(TL);
79 /// \brief Initializes a type location, and all of its children
80 /// recursively, as if the entire tree had been written in the
82 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
85 switch (TL.getTypeLocClass()) {
86 #define ABSTRACT_TYPELOC(CLASS, PARENT)
87 #define TYPELOC(CLASS, PARENT) \
89 CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
90 TLCasted.initializeLocal(Context, Loc); \
91 TL = TLCasted.getNextTypeLoc(); \
95 #include "clang/AST/TypeLocNodes.def"
100 SourceLocation TypeLoc::getBeginLoc() const {
102 TypeLoc LeftMost = Cur;
104 switch (Cur.getTypeLocClass()) {
109 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
110 ->hasTrailingReturn()) {
115 case FunctionNoProto:
117 case DependentSizedArray:
118 case IncompleteArray:
120 // FIXME: Currently QualifiedTypeLoc does not have a source range
122 Cur = Cur.getNextTypeLoc();
125 if (!Cur.getLocalSourceRange().getBegin().isInvalid())
127 Cur = Cur.getNextTypeLoc();
134 return LeftMost.getLocalSourceRange().getBegin();
137 SourceLocation TypeLoc::getEndLoc() const {
141 switch (Cur.getTypeLocClass()) {
145 return Last.getLocalSourceRange().getEnd();
148 case DependentSizedArray:
149 case IncompleteArray:
151 case FunctionNoProto:
155 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
163 case LValueReference:
164 case RValueReference:
173 Cur = Cur.getNextTypeLoc();
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; }
184 #define ABSTRACT_TYPELOC(CLASS, PARENT)
185 #define TYPELOC(CLASS, PARENT) \
186 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
187 return isTypeSpec(TyLoc); \
189 #include "clang/AST/TypeLocNodes.def"
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.
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
202 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
203 if (TL.getType().hasLocalQualifiers()) return false;
204 return TSTChecker().Visit(TL);
207 // Reimplemented to account for GNU/C++ extension
208 // typeof unary-expression
209 // where there are no parentheses.
210 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
211 if (getRParenLoc().isValid())
212 return SourceRange(getTypeofLoc(), getRParenLoc());
214 return SourceRange(getTypeofLoc(),
215 getUnderlyingExpr()->getSourceRange().getEnd());
219 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
220 if (needsExtraLocalData())
221 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
222 switch (getTypePtr()->getKind()) {
223 case BuiltinType::Void:
225 case BuiltinType::Bool:
227 case BuiltinType::Char_U:
228 case BuiltinType::Char_S:
230 case BuiltinType::Char16:
232 case BuiltinType::Char32:
234 case BuiltinType::WChar_S:
235 case BuiltinType::WChar_U:
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.
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:
266 case BuiltinType::OCLImage1d:
267 case BuiltinType::OCLImage1dArray:
268 case BuiltinType::OCLImage1dBuffer:
269 case BuiltinType::OCLImage2d:
270 case BuiltinType::OCLImage2dArray:
271 case BuiltinType::OCLImage3d:
272 case BuiltinType::OCLSampler:
273 case BuiltinType::OCLEvent:
274 case BuiltinType::BuiltinFn:
275 return TST_unspecified;
278 llvm_unreachable("Invalid BuiltinType Kind!");
281 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
282 while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
283 TL = PTL.getInnerLoc();
287 void 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));
295 void 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));
305 DependentTemplateSpecializationTypeLoc::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));
313 setQualifierLoc(NestedNameSpecifierLoc());
315 setTemplateKeywordLoc(Loc);
316 setTemplateNameLoc(Loc);
319 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
320 getTypePtr()->getArgs(),
324 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
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");
337 case TemplateArgument::Expression:
338 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
341 case TemplateArgument::Type:
342 ArgInfos[i] = TemplateArgumentLocInfo(
343 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
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);
356 ArgInfos[i] = TemplateArgumentLocInfo(
357 Builder.getWithLocInContext(Context),
359 Args[i].getKind() == TemplateArgument::Template
365 case TemplateArgument::Pack:
366 ArgInfos[i] = TemplateArgumentLocInfo();