]> granicus.if.org Git - clang/blob - lib/AST/TypeLoc.cpp
Improved TypeLoc::getSourceRange().
[clang] / lib / AST / TypeLoc.cpp
1 //===--- 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 "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;
19
20 //===----------------------------------------------------------------------===//
21 // TypeLoc Implementation
22 //===----------------------------------------------------------------------===//
23
24 namespace {
25   class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
26   public:
27 #define ABSTRACT_TYPELOC(CLASS, PARENT)
28 #define TYPELOC(CLASS, PARENT) \
29     SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
30       return TyLoc.getLocalSourceRange(); \
31     }
32 #include "clang/AST/TypeLocNodes.def"
33   };
34 }
35
36 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
37   if (TL.isNull()) return SourceRange();
38   return TypeLocRanger().Visit(TL);
39 }
40
41 namespace {
42   class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
43   public:
44 #define ABSTRACT_TYPELOC(CLASS, PARENT)
45 #define TYPELOC(CLASS, PARENT) \
46     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
47       return TyLoc.getFullDataSize(); \
48     }
49 #include "clang/AST/TypeLocNodes.def"
50   };
51 }
52
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));
57 }
58
59 namespace {
60   class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
61   public:
62 #define ABSTRACT_TYPELOC(CLASS, PARENT)
63 #define TYPELOC(CLASS, PARENT) \
64     TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
65       return TyLoc.getNextTypeLoc(); \
66     }
67 #include "clang/AST/TypeLocNodes.def"
68   };
69 }
70
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);
75 }
76
77 namespace {
78   struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> {
79     SourceLocation Loc;
80     TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {}
81   
82 #define ABSTRACT_TYPELOC(CLASS, PARENT)
83 #define TYPELOC(CLASS, PARENT) \
84     void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
85       TyLoc.initializeLocal(Loc); \
86     }
87 #include "clang/AST/TypeLocNodes.def"
88   };
89 }
90
91 /// \brief Initializes a type location, and all of its children
92 /// recursively, as if the entire tree had been written in the
93 /// given location.
94 void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) {
95   while (true) {
96     switch (TL.getTypeLocClass()) {
97 #define ABSTRACT_TYPELOC(CLASS, PARENT)
98 #define TYPELOC(CLASS, PARENT)        \
99     case CLASS: {                     \
100       CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
101       TLCasted.initializeLocal(Loc);  \
102       TL = TLCasted.getNextTypeLoc(); \
103       if (!TL) return;                \
104       continue;                       \
105     }
106 #include "clang/AST/TypeLocNodes.def"
107     }
108   }
109 }
110
111 SourceLocation TypeLoc::getBeginLoc() const {
112   TypeLoc Cur = *this;
113   while (true) {
114     switch (Cur.getTypeLocClass()) {
115     // FIXME: Currently QualifiedTypeLoc does not have a source range
116     // case Qualified:
117     case Elaborated:
118       break;
119     default:
120       TypeLoc Next = Cur.getNextTypeLoc();
121       if (Next.isNull()) break;
122       Cur = Next;
123       continue;
124     }
125     break;
126   }
127   return Cur.getLocalSourceRange().getBegin();
128 }
129
130 SourceLocation TypeLoc::getEndLoc() const {
131   TypeLoc Cur = *this;
132   while (true) {
133     switch (Cur.getTypeLocClass()) {
134     default:
135       break;
136     case Qualified:
137     case Elaborated:
138       Cur = Cur.getNextTypeLoc();
139       continue;
140     }
141     break;
142   }
143   return Cur.getLocalSourceRange().getEnd();
144 }
145
146
147 namespace {
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; }
152
153 #define ABSTRACT_TYPELOC(CLASS, PARENT)
154 #define TYPELOC(CLASS, PARENT) \
155     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
156       return isTypeSpec(TyLoc); \
157     }
158 #include "clang/AST/TypeLocNodes.def"
159   };
160 }
161
162
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.
166 ///
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
170 /// them.
171 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
172   if (TL->getType().hasLocalQualifiers()) return false;
173   return TSTChecker().Visit(*TL);
174 }
175
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());
182   else
183     return SourceRange(getTypeofLoc(),
184                        getUnderlyingExpr()->getSourceRange().getEnd());
185 }
186
187
188 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
189   if (needsExtraLocalData())
190     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
191   else {
192     switch (getTypePtr()->getKind()) {
193     case BuiltinType::Void:
194       return TST_void;
195     case BuiltinType::Bool:
196       return TST_bool;
197     case BuiltinType::Char_U:
198     case BuiltinType::Char_S:
199       return TST_char;
200     case BuiltinType::Char16:
201       return TST_char16;        
202     case BuiltinType::Char32:
203       return TST_char32;
204     case BuiltinType::WChar:
205       return TST_wchar;
206     case BuiltinType::UndeducedAuto:
207       return TST_auto;
208         
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.
226         
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;
234     }
235   }
236   
237   return TST_unspecified;
238 }