]> granicus.if.org Git - clang/blob - lib/AST/TypeLoc.cpp
Change the representation of builtin functions in the AST
[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/ASTContext.h"
17 #include "clang/AST/Expr.h"
18 #include "llvm/Support/ErrorHandling.h"
19 using namespace clang;
20
21 //===----------------------------------------------------------------------===//
22 // TypeLoc Implementation
23 //===----------------------------------------------------------------------===//
24
25 namespace {
26   class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
27   public:
28 #define ABSTRACT_TYPELOC(CLASS, PARENT)
29 #define TYPELOC(CLASS, PARENT) \
30     SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
31       return TyLoc.getLocalSourceRange(); \
32     }
33 #include "clang/AST/TypeLocNodes.def"
34   };
35 }
36
37 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
38   if (TL.isNull()) return SourceRange();
39   return TypeLocRanger().Visit(TL);
40 }
41
42 namespace {
43   class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
44   public:
45 #define ABSTRACT_TYPELOC(CLASS, PARENT)
46 #define TYPELOC(CLASS, PARENT) \
47     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
48       return TyLoc.getFullDataSize(); \
49     }
50 #include "clang/AST/TypeLocNodes.def"
51   };
52 }
53
54 /// \brief Returns the size of the type source info data block.
55 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
56   if (Ty.isNull()) return 0;
57   return TypeSizer().Visit(TypeLoc(Ty, 0));
58 }
59
60 namespace {
61   class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
62   public:
63 #define ABSTRACT_TYPELOC(CLASS, PARENT)
64 #define TYPELOC(CLASS, PARENT) \
65     TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
66       return TyLoc.getNextTypeLoc(); \
67     }
68 #include "clang/AST/TypeLocNodes.def"
69   };
70 }
71
72 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
73 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
74 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
75   return NextLoc().Visit(TL);
76 }
77
78 /// \brief Initializes a type location, and all of its children
79 /// recursively, as if the entire tree had been written in the
80 /// given location.
81 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 
82                              SourceLocation Loc) {
83   while (true) {
84     switch (TL.getTypeLocClass()) {
85 #define ABSTRACT_TYPELOC(CLASS, PARENT)
86 #define TYPELOC(CLASS, PARENT)        \
87     case CLASS: {                     \
88       CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
89       TLCasted.initializeLocal(Context, Loc);  \
90       TL = TLCasted.getNextTypeLoc(); \
91       if (!TL) return;                \
92       continue;                       \
93     }
94 #include "clang/AST/TypeLocNodes.def"
95     }
96   }
97 }
98
99 SourceLocation TypeLoc::getBeginLoc() const {
100   TypeLoc Cur = *this;
101   while (true) {
102     switch (Cur.getTypeLocClass()) {
103     // FIXME: Currently QualifiedTypeLoc does not have a source range
104     // case Qualified:
105     case Elaborated:
106     case DependentName:
107     case DependentTemplateSpecialization:
108       break;
109     default:
110       TypeLoc Next = Cur.getNextTypeLoc();
111       if (Next.isNull()) break;
112       Cur = Next;
113       continue;
114     }
115     break;
116   }
117   return Cur.getLocalSourceRange().getBegin();
118 }
119
120 SourceLocation TypeLoc::getEndLoc() const {
121   TypeLoc Cur = *this;
122   TypeLoc Last;
123   while (true) {
124     switch (Cur.getTypeLocClass()) {
125     default:
126       if (!Last)
127         Last = Cur;
128       return Last.getLocalSourceRange().getEnd();
129     case Paren:
130     case ConstantArray:
131     case DependentSizedArray:
132     case IncompleteArray:
133     case VariableArray:
134     case FunctionProto:
135     case FunctionNoProto:
136       Last = Cur;
137       break;
138     case Pointer:
139     case BlockPointer:
140     case MemberPointer:
141     case LValueReference:
142     case RValueReference:
143     case PackExpansion:
144       if (!Last)
145         Last = Cur;
146       break;
147     case Qualified:
148     case Elaborated:
149       break;
150     }
151     Cur = Cur.getNextTypeLoc();
152   }
153 }
154
155
156 namespace {
157   struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
158     // Overload resolution does the real work for us.
159     static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
160     static bool isTypeSpec(TypeLoc _) { return false; }
161
162 #define ABSTRACT_TYPELOC(CLASS, PARENT)
163 #define TYPELOC(CLASS, PARENT) \
164     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
165       return isTypeSpec(TyLoc); \
166     }
167 #include "clang/AST/TypeLocNodes.def"
168   };
169 }
170
171
172 /// \brief Determines if the given type loc corresponds to a
173 /// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
174 /// the type hierarchy, this is made somewhat complicated.
175 ///
176 /// There are a lot of types that currently use TypeSpecTypeLoc
177 /// because it's a convenient base class.  Ideally we would not accept
178 /// those here, but ideally we would have better implementations for
179 /// them.
180 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
181   if (TL->getType().hasLocalQualifiers()) return false;
182   return TSTChecker().Visit(*TL);
183 }
184
185 // Reimplemented to account for GNU/C++ extension
186 //     typeof unary-expression
187 // where there are no parentheses.
188 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
189   if (getRParenLoc().isValid())
190     return SourceRange(getTypeofLoc(), getRParenLoc());
191   else
192     return SourceRange(getTypeofLoc(),
193                        getUnderlyingExpr()->getSourceRange().getEnd());
194 }
195
196
197 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
198   if (needsExtraLocalData())
199     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
200   switch (getTypePtr()->getKind()) {
201   case BuiltinType::Void:
202     return TST_void;
203   case BuiltinType::Bool:
204     return TST_bool;
205   case BuiltinType::Char_U:
206   case BuiltinType::Char_S:
207     return TST_char;
208   case BuiltinType::Char16:
209     return TST_char16;
210   case BuiltinType::Char32:
211     return TST_char32;
212   case BuiltinType::WChar_S:
213   case BuiltinType::WChar_U:
214     return TST_wchar;
215   case BuiltinType::UChar:
216   case BuiltinType::UShort:
217   case BuiltinType::UInt:
218   case BuiltinType::ULong:
219   case BuiltinType::ULongLong:
220   case BuiltinType::UInt128:
221   case BuiltinType::SChar:
222   case BuiltinType::Short:
223   case BuiltinType::Int:
224   case BuiltinType::Long:
225   case BuiltinType::LongLong:
226   case BuiltinType::Int128:
227   case BuiltinType::Half:
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.
233       
234   case BuiltinType::NullPtr:
235   case BuiltinType::Overload:
236   case BuiltinType::Dependent:
237   case BuiltinType::BoundMember:
238   case BuiltinType::UnknownAny:
239   case BuiltinType::ARCUnbridgedCast:
240   case BuiltinType::PseudoObject:
241   case BuiltinType::ObjCId:
242   case BuiltinType::ObjCClass:
243   case BuiltinType::ObjCSel:
244   case BuiltinType::BuiltinFn:
245     return TST_unspecified;
246   }
247
248   llvm_unreachable("Invalid BuiltinType Kind!");
249 }
250
251 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
252   while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
253     TL = PTL->getInnerLoc();
254   return TL;
255 }
256
257 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 
258                                         SourceLocation Loc) {
259   setElaboratedKeywordLoc(Loc);
260   NestedNameSpecifierLocBuilder Builder;
261   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
262   setQualifierLoc(Builder.getWithLocInContext(Context));
263 }
264
265 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 
266                                            SourceLocation Loc) {
267   setElaboratedKeywordLoc(Loc);
268   NestedNameSpecifierLocBuilder Builder;
269   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
270   setQualifierLoc(Builder.getWithLocInContext(Context));
271   setNameLoc(Loc);
272 }
273
274 void
275 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
276                                                         SourceLocation Loc) {
277   setElaboratedKeywordLoc(Loc);
278   if (getTypePtr()->getQualifier()) {
279     NestedNameSpecifierLocBuilder Builder;
280     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
281     setQualifierLoc(Builder.getWithLocInContext(Context));
282   } else {
283     setQualifierLoc(NestedNameSpecifierLoc());
284   }
285   setTemplateKeywordLoc(Loc);
286   setTemplateNameLoc(Loc);
287   setLAngleLoc(Loc);
288   setRAngleLoc(Loc);
289   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
290                                                    getTypePtr()->getArgs(),
291                                                    getArgInfos(), Loc);
292 }
293
294 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 
295                                                       unsigned NumArgs,
296                                                   const TemplateArgument *Args,
297                                               TemplateArgumentLocInfo *ArgInfos,
298                                                       SourceLocation Loc) {
299   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
300     switch (Args[i].getKind()) {
301     case TemplateArgument::Null: 
302     case TemplateArgument::Declaration:
303     case TemplateArgument::Integral:
304     case TemplateArgument::Pack:
305     case TemplateArgument::Expression:
306       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
307       break;
308       
309     case TemplateArgument::Type:
310       ArgInfos[i] = TemplateArgumentLocInfo(
311                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
312                                                            Loc));
313       break;
314         
315     case TemplateArgument::Template:
316     case TemplateArgument::TemplateExpansion: {
317       NestedNameSpecifierLocBuilder Builder;
318       TemplateName Template = Args[i].getAsTemplate();
319       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
320         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
321       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
322         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
323       
324       ArgInfos[i] = TemplateArgumentLocInfo(
325                                            Builder.getWithLocInContext(Context),
326                                             Loc, 
327                                 Args[i].getKind() == TemplateArgument::Template
328                                             ? SourceLocation()
329                                             : Loc);
330       break;
331     }        
332     }
333   }
334 }