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);
78 struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> {
80 TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {}
82 #define ABSTRACT_TYPELOC(CLASS, PARENT)
83 #define TYPELOC(CLASS, PARENT) \
84 void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
85 TyLoc.initializeLocal(Loc); \
87 #include "clang/AST/TypeLocNodes.def"
91 /// \brief Initializes a type location, and all of its children
92 /// recursively, as if the entire tree had been written in the
94 void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) {
96 switch (TL.getTypeLocClass()) {
97 #define ABSTRACT_TYPELOC(CLASS, PARENT)
98 #define TYPELOC(CLASS, PARENT) \
100 CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
101 TLCasted.initializeLocal(Loc); \
102 TL = TLCasted.getNextTypeLoc(); \
106 #include "clang/AST/TypeLocNodes.def"
111 SourceLocation TypeLoc::getBeginLoc() const {
114 switch (Cur.getTypeLocClass()) {
115 // FIXME: Currently QualifiedTypeLoc does not have a source range
120 TypeLoc Next = Cur.getNextTypeLoc();
121 if (Next.isNull()) break;
127 return Cur.getLocalSourceRange().getBegin();
130 SourceLocation TypeLoc::getEndLoc() const {
133 switch (Cur.getTypeLocClass()) {
138 Cur = Cur.getNextTypeLoc();
143 return Cur.getLocalSourceRange().getEnd();
148 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
149 // Overload resolution does the real work for us.
150 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
151 static bool isTypeSpec(TypeLoc _) { return false; }
153 #define ABSTRACT_TYPELOC(CLASS, PARENT)
154 #define TYPELOC(CLASS, PARENT) \
155 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
156 return isTypeSpec(TyLoc); \
158 #include "clang/AST/TypeLocNodes.def"
163 /// \brief Determines if the given type loc corresponds to a
164 /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
165 /// the type hierarchy, this is made somewhat complicated.
167 /// There are a lot of types that currently use TypeSpecTypeLoc
168 /// because it's a convenient base class. Ideally we would not accept
169 /// those here, but ideally we would have better implementations for
171 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
172 if (TL->getType().hasLocalQualifiers()) return false;
173 return TSTChecker().Visit(*TL);
176 // Reimplemented to account for GNU/C++ extension
177 // typeof unary-expression
178 // where there are no parentheses.
179 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
180 if (getRParenLoc().isValid())
181 return SourceRange(getTypeofLoc(), getRParenLoc());
183 return SourceRange(getTypeofLoc(),
184 getUnderlyingExpr()->getSourceRange().getEnd());
188 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
189 if (needsExtraLocalData())
190 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
192 switch (getTypePtr()->getKind()) {
193 case BuiltinType::Void:
195 case BuiltinType::Bool:
197 case BuiltinType::Char_U:
198 case BuiltinType::Char_S:
200 case BuiltinType::Char16:
202 case BuiltinType::Char32:
204 case BuiltinType::WChar:
206 case BuiltinType::UndeducedAuto:
209 case BuiltinType::UChar:
210 case BuiltinType::UShort:
211 case BuiltinType::UInt:
212 case BuiltinType::ULong:
213 case BuiltinType::ULongLong:
214 case BuiltinType::UInt128:
215 case BuiltinType::SChar:
216 case BuiltinType::Short:
217 case BuiltinType::Int:
218 case BuiltinType::Long:
219 case BuiltinType::LongLong:
220 case BuiltinType::Int128:
221 case BuiltinType::Float:
222 case BuiltinType::Double:
223 case BuiltinType::LongDouble:
224 llvm_unreachable("Builtin type needs extra local data!");
225 // Fall through, if the impossible happens.
227 case BuiltinType::NullPtr:
228 case BuiltinType::Overload:
229 case BuiltinType::Dependent:
230 case BuiltinType::ObjCId:
231 case BuiltinType::ObjCClass:
232 case BuiltinType::ObjCSel:
233 return TST_unspecified;
237 return TST_unspecified;