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
106 case DependentTemplateSpecialization:
109 TypeLoc Next = Cur.getNextTypeLoc();
110 if (Next.isNull()) break;
116 return Cur.getLocalSourceRange().getBegin();
119 SourceLocation TypeLoc::getEndLoc() const {
123 switch (Cur.getTypeLocClass()) {
127 return Last.getLocalSourceRange().getEnd();
130 case DependentSizedArray:
131 case IncompleteArray:
134 case FunctionNoProto:
140 case LValueReference:
141 case RValueReference:
150 Cur = Cur.getNextTypeLoc();
156 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
157 // Overload resolution does the real work for us.
158 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
159 static bool isTypeSpec(TypeLoc _) { return false; }
161 #define ABSTRACT_TYPELOC(CLASS, PARENT)
162 #define TYPELOC(CLASS, PARENT) \
163 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
164 return isTypeSpec(TyLoc); \
166 #include "clang/AST/TypeLocNodes.def"
171 /// \brief Determines if the given type loc corresponds to a
172 /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
173 /// the type hierarchy, this is made somewhat complicated.
175 /// There are a lot of types that currently use TypeSpecTypeLoc
176 /// because it's a convenient base class. Ideally we would not accept
177 /// those here, but ideally we would have better implementations for
179 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
180 if (TL->getType().hasLocalQualifiers()) return false;
181 return TSTChecker().Visit(*TL);
184 // Reimplemented to account for GNU/C++ extension
185 // typeof unary-expression
186 // where there are no parentheses.
187 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
188 if (getRParenLoc().isValid())
189 return SourceRange(getTypeofLoc(), getRParenLoc());
191 return SourceRange(getTypeofLoc(),
192 getUnderlyingExpr()->getSourceRange().getEnd());
196 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
197 if (needsExtraLocalData())
198 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
200 switch (getTypePtr()->getKind()) {
201 case BuiltinType::Void:
203 case BuiltinType::Bool:
205 case BuiltinType::Char_U:
206 case BuiltinType::Char_S:
208 case BuiltinType::Char16:
210 case BuiltinType::Char32:
212 case BuiltinType::WChar_S:
213 case BuiltinType::WChar_U:
216 case BuiltinType::UChar:
217 case BuiltinType::UShort:
218 case BuiltinType::UInt:
219 case BuiltinType::ULong:
220 case BuiltinType::ULongLong:
221 case BuiltinType::UInt128:
222 case BuiltinType::SChar:
223 case BuiltinType::Short:
224 case BuiltinType::Int:
225 case BuiltinType::Long:
226 case BuiltinType::LongLong:
227 case BuiltinType::Int128:
228 case BuiltinType::Float:
229 case BuiltinType::Double:
230 case BuiltinType::LongDouble:
231 llvm_unreachable("Builtin type needs extra local data!");
232 // Fall through, if the impossible happens.
234 case BuiltinType::NullPtr:
235 case BuiltinType::Overload:
236 case BuiltinType::Dependent:
237 case BuiltinType::BoundMember:
238 case BuiltinType::UnknownAny:
239 case BuiltinType::ObjCId:
240 case BuiltinType::ObjCClass:
241 case BuiltinType::ObjCSel:
242 return TST_unspecified;
246 return TST_unspecified;
249 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
250 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
251 TL = PTL->getInnerLoc();
255 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
256 SourceLocation Loc) {
258 NestedNameSpecifierLocBuilder Builder;
259 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
260 setQualifierLoc(Builder.getWithLocInContext(Context));
263 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
264 SourceLocation Loc) {
266 NestedNameSpecifierLocBuilder Builder;
267 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
268 setQualifierLoc(Builder.getWithLocInContext(Context));
273 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
274 SourceLocation Loc) {
276 if (getTypePtr()->getQualifier()) {
277 NestedNameSpecifierLocBuilder Builder;
278 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
279 setQualifierLoc(Builder.getWithLocInContext(Context));
281 setQualifierLoc(NestedNameSpecifierLoc());
287 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
288 getTypePtr()->getArgs(),
292 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
294 const TemplateArgument *Args,
295 TemplateArgumentLocInfo *ArgInfos,
296 SourceLocation Loc) {
297 for (unsigned i = 0, e = NumArgs; i != e; ++i) {
298 switch (Args[i].getKind()) {
299 case TemplateArgument::Null:
300 case TemplateArgument::Declaration:
301 case TemplateArgument::Integral:
302 case TemplateArgument::Pack:
303 case TemplateArgument::Expression:
304 // FIXME: Can we do better for declarations and integral values?
305 ArgInfos[i] = TemplateArgumentLocInfo();
308 case TemplateArgument::Type:
309 ArgInfos[i] = TemplateArgumentLocInfo(
310 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
314 case TemplateArgument::Template:
315 case TemplateArgument::TemplateExpansion: {
316 NestedNameSpecifierLocBuilder Builder;
317 TemplateName Template = Args[i].getAsTemplate();
318 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
319 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
320 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
321 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
323 ArgInfos[i] = TemplateArgumentLocInfo(
324 Builder.getWithLocInContext(Context),
326 Args[i].getKind() == TemplateArgument::Template