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 "llvm/Support/raw_ostream.h"
15 #include "clang/AST/TypeLocVisitor.h"
16 #include "clang/AST/Expr.h"
17 #include "llvm/Support/ErrorHandling.h"
18 using namespace clang;
20 //===----------------------------------------------------------------------===//
21 // TypeLoc Implementation
22 //===----------------------------------------------------------------------===//
25 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
27 #define ABSTRACT_TYPELOC(CLASS, PARENT)
28 #define TYPELOC(CLASS, PARENT) \
29 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
30 return TyLoc.getLocalSourceRange(); \
32 #include "clang/AST/TypeLocNodes.def"
36 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
37 if (TL.isNull()) return SourceRange();
38 return TypeLocRanger().Visit(TL);
42 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
44 #define ABSTRACT_TYPELOC(CLASS, PARENT)
45 #define TYPELOC(CLASS, PARENT) \
46 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
47 return TyLoc.getFullDataSize(); \
49 #include "clang/AST/TypeLocNodes.def"
53 /// \brief Returns the size of the type source info data block.
54 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
55 if (Ty.isNull()) return 0;
56 return TypeSizer().Visit(TypeLoc(Ty, 0));
60 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
62 #define ABSTRACT_TYPELOC(CLASS, PARENT)
63 #define TYPELOC(CLASS, PARENT) \
64 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
65 return TyLoc.getNextTypeLoc(); \
67 #include "clang/AST/TypeLocNodes.def"
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".
73 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
74 return NextLoc().Visit(TL);
77 /// \brief Initializes a type location, and all of its children
78 /// recursively, as if the entire tree had been written in the
80 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
83 switch (TL.getTypeLocClass()) {
84 #define ABSTRACT_TYPELOC(CLASS, PARENT)
85 #define TYPELOC(CLASS, PARENT) \
87 CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
88 TLCasted.initializeLocal(Context, Loc); \
89 TL = TLCasted.getNextTypeLoc(); \
93 #include "clang/AST/TypeLocNodes.def"
98 SourceLocation TypeLoc::getBeginLoc() const {
101 switch (Cur.getTypeLocClass()) {
102 // FIXME: Currently QualifiedTypeLoc does not have a source range
107 TypeLoc Next = Cur.getNextTypeLoc();
108 if (Next.isNull()) break;
114 return Cur.getLocalSourceRange().getBegin();
117 SourceLocation TypeLoc::getEndLoc() const {
120 switch (Cur.getTypeLocClass()) {
125 Cur = Cur.getNextTypeLoc();
130 return Cur.getLocalSourceRange().getEnd();
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; }
140 #define ABSTRACT_TYPELOC(CLASS, PARENT)
141 #define TYPELOC(CLASS, PARENT) \
142 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
143 return isTypeSpec(TyLoc); \
145 #include "clang/AST/TypeLocNodes.def"
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.
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
158 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
159 if (TL->getType().hasLocalQualifiers()) return false;
160 return TSTChecker().Visit(*TL);
163 // Reimplemented to account for GNU/C++ extension
164 // typeof unary-expression
165 // where there are no parentheses.
166 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
167 if (getRParenLoc().isValid())
168 return SourceRange(getTypeofLoc(), getRParenLoc());
170 return SourceRange(getTypeofLoc(),
171 getUnderlyingExpr()->getSourceRange().getEnd());
175 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
176 if (needsExtraLocalData())
177 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
179 switch (getTypePtr()->getKind()) {
180 case BuiltinType::Void:
182 case BuiltinType::Bool:
184 case BuiltinType::Char_U:
185 case BuiltinType::Char_S:
187 case BuiltinType::Char16:
189 case BuiltinType::Char32:
191 case BuiltinType::WChar_S:
192 case BuiltinType::WChar_U:
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.
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;
223 return TST_unspecified;
226 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
227 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
228 TL = PTL->getInnerLoc();
232 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
233 SourceLocation Loc) {
235 NestedNameSpecifierLocBuilder Builder;
236 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
237 setQualifierLoc(Builder.getWithLocInContext(Context));
241 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
243 const TemplateArgument *Args,
244 TemplateArgumentLocInfo *ArgInfos,
245 SourceLocation Loc) {
246 for (unsigned i = 0, e = NumArgs; i != e; ++i) {
247 switch (Args[i].getKind()) {
248 case TemplateArgument::Null:
249 case TemplateArgument::Declaration:
250 case TemplateArgument::Integral:
251 case TemplateArgument::Pack:
252 case TemplateArgument::Expression:
253 // FIXME: Can we do better for declarations and integral values?
254 ArgInfos[i] = TemplateArgumentLocInfo();
257 case TemplateArgument::Type:
258 ArgInfos[i] = TemplateArgumentLocInfo(
259 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
263 case TemplateArgument::Template:
264 ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc,
268 case TemplateArgument::TemplateExpansion:
269 ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc);