]> granicus.if.org Git - clang/blob - lib/AST/TypeLoc.cpp
Reinstate the introduction of source-location information for
[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 /// \brief Initializes a type location, and all of its children
78 /// recursively, as if the entire tree had been written in the
79 /// given location.
80 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 
81                              SourceLocation Loc) {
82   while (true) {
83     switch (TL.getTypeLocClass()) {
84 #define ABSTRACT_TYPELOC(CLASS, PARENT)
85 #define TYPELOC(CLASS, PARENT)        \
86     case CLASS: {                     \
87       CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
88       TLCasted.initializeLocal(Context, Loc);  \
89       TL = TLCasted.getNextTypeLoc(); \
90       if (!TL) return;                \
91       continue;                       \
92     }
93 #include "clang/AST/TypeLocNodes.def"
94     }
95   }
96 }
97
98 SourceLocation TypeLoc::getBeginLoc() const {
99   TypeLoc Cur = *this;
100   while (true) {
101     switch (Cur.getTypeLocClass()) {
102     // FIXME: Currently QualifiedTypeLoc does not have a source range
103     // case Qualified:
104     case Elaborated:
105       break;
106     default:
107       TypeLoc Next = Cur.getNextTypeLoc();
108       if (Next.isNull()) break;
109       Cur = Next;
110       continue;
111     }
112     break;
113   }
114   return Cur.getLocalSourceRange().getBegin();
115 }
116
117 SourceLocation TypeLoc::getEndLoc() const {
118   TypeLoc Cur = *this;
119   while (true) {
120     switch (Cur.getTypeLocClass()) {
121     default:
122       break;
123     case Qualified:
124     case Elaborated:
125       Cur = Cur.getNextTypeLoc();
126       continue;
127     }
128     break;
129   }
130   return Cur.getLocalSourceRange().getEnd();
131 }
132
133
134 namespace {
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; }
139
140 #define ABSTRACT_TYPELOC(CLASS, PARENT)
141 #define TYPELOC(CLASS, PARENT) \
142     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
143       return isTypeSpec(TyLoc); \
144     }
145 #include "clang/AST/TypeLocNodes.def"
146   };
147 }
148
149
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.
153 ///
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
157 /// them.
158 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
159   if (TL->getType().hasLocalQualifiers()) return false;
160   return TSTChecker().Visit(*TL);
161 }
162
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());
169   else
170     return SourceRange(getTypeofLoc(),
171                        getUnderlyingExpr()->getSourceRange().getEnd());
172 }
173
174
175 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
176   if (needsExtraLocalData())
177     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
178   else {
179     switch (getTypePtr()->getKind()) {
180     case BuiltinType::Void:
181       return TST_void;
182     case BuiltinType::Bool:
183       return TST_bool;
184     case BuiltinType::Char_U:
185     case BuiltinType::Char_S:
186       return TST_char;
187     case BuiltinType::Char16:
188       return TST_char16;        
189     case BuiltinType::Char32:
190       return TST_char32;
191     case BuiltinType::WChar_S:
192     case BuiltinType::WChar_U:
193       return TST_wchar;
194
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.
212         
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;
220     }
221   }
222   
223   return TST_unspecified;
224 }
225
226 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
227   while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
228     TL = PTL->getInnerLoc();
229   return TL;
230 }
231
232 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 
233                                         SourceLocation Loc) {
234   setKeywordLoc(Loc);
235   NestedNameSpecifierLocBuilder Builder;
236   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
237   setQualifierLoc(Builder.getWithLocInContext(Context));
238 }
239
240 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 
241                                            SourceLocation Loc) {
242   setKeywordLoc(Loc);
243   NestedNameSpecifierLocBuilder Builder;
244   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
245   setQualifierLoc(Builder.getWithLocInContext(Context));
246   setNameLoc(Loc);
247 }
248
249 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 
250                                                       unsigned NumArgs,
251                                                   const TemplateArgument *Args,
252                                               TemplateArgumentLocInfo *ArgInfos,
253                                                       SourceLocation Loc) {
254   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
255     switch (Args[i].getKind()) {
256     case TemplateArgument::Null: 
257     case TemplateArgument::Declaration:
258     case TemplateArgument::Integral:
259     case TemplateArgument::Pack:
260     case TemplateArgument::Expression:
261       // FIXME: Can we do better for declarations and integral values?
262       ArgInfos[i] = TemplateArgumentLocInfo();
263       break;
264       
265     case TemplateArgument::Type:
266       ArgInfos[i] = TemplateArgumentLocInfo(
267                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
268                                                            Loc));
269       break;
270         
271     case TemplateArgument::Template:
272       ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, 
273                                             SourceLocation());
274       break;
275       
276     case TemplateArgument::TemplateExpansion:
277       ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc);
278       break;
279     }
280   }
281 }
282