]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / 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     case DependentName:
106     case DependentTemplateSpecialization:
107       break;
108     default:
109       TypeLoc Next = Cur.getNextTypeLoc();
110       if (Next.isNull()) break;
111       Cur = Next;
112       continue;
113     }
114     break;
115   }
116   return Cur.getLocalSourceRange().getBegin();
117 }
118
119 SourceLocation TypeLoc::getEndLoc() const {
120   TypeLoc Cur = *this;
121   TypeLoc Last;
122   while (true) {
123     switch (Cur.getTypeLocClass()) {
124     default:
125       if (!Last)
126         Last = Cur;
127       return Last.getLocalSourceRange().getEnd();
128     case Paren:
129     case ConstantArray:
130     case DependentSizedArray:
131     case IncompleteArray:
132     case VariableArray:
133     case FunctionProto:
134     case FunctionNoProto:
135       Last = Cur;
136       break;
137     case Pointer:
138     case BlockPointer:
139     case MemberPointer:
140     case LValueReference:
141     case RValueReference:
142     case PackExpansion:
143       if (!Last)
144         Last = Cur;
145       break;
146     case Qualified:
147     case Elaborated:
148       break;
149     }
150     Cur = Cur.getNextTypeLoc();
151   }
152 }
153
154
155 namespace {
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; }
160
161 #define ABSTRACT_TYPELOC(CLASS, PARENT)
162 #define TYPELOC(CLASS, PARENT) \
163     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
164       return isTypeSpec(TyLoc); \
165     }
166 #include "clang/AST/TypeLocNodes.def"
167   };
168 }
169
170
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.
174 ///
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
178 /// them.
179 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
180   if (TL->getType().hasLocalQualifiers()) return false;
181   return TSTChecker().Visit(*TL);
182 }
183
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());
190   else
191     return SourceRange(getTypeofLoc(),
192                        getUnderlyingExpr()->getSourceRange().getEnd());
193 }
194
195
196 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
197   if (needsExtraLocalData())
198     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
199   else {
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
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::Half:
229     case BuiltinType::Float:
230     case BuiltinType::Double:
231     case BuiltinType::LongDouble:
232       llvm_unreachable("Builtin type needs extra local data!");
233       // Fall through, if the impossible happens.
234         
235     case BuiltinType::NullPtr:
236     case BuiltinType::Overload:
237     case BuiltinType::Dependent:
238     case BuiltinType::BoundMember:
239     case BuiltinType::UnknownAny:
240     case BuiltinType::ObjCId:
241     case BuiltinType::ObjCClass:
242     case BuiltinType::ObjCSel:
243       return TST_unspecified;
244     }
245   }
246   
247   return TST_unspecified;
248 }
249
250 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
251   while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
252     TL = PTL->getInnerLoc();
253   return TL;
254 }
255
256 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 
257                                         SourceLocation Loc) {
258   setKeywordLoc(Loc);
259   NestedNameSpecifierLocBuilder Builder;
260   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
261   setQualifierLoc(Builder.getWithLocInContext(Context));
262 }
263
264 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 
265                                            SourceLocation Loc) {
266   setKeywordLoc(Loc);
267   NestedNameSpecifierLocBuilder Builder;
268   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
269   setQualifierLoc(Builder.getWithLocInContext(Context));
270   setNameLoc(Loc);
271 }
272
273 void 
274 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 
275                                                         SourceLocation Loc) {
276   setKeywordLoc(Loc);
277   if (getTypePtr()->getQualifier()) {
278     NestedNameSpecifierLocBuilder Builder;
279     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
280     setQualifierLoc(Builder.getWithLocInContext(Context));
281   } else {
282     setQualifierLoc(NestedNameSpecifierLoc());
283   }
284   
285   setNameLoc(Loc);
286   setLAngleLoc(Loc);
287   setRAngleLoc(Loc);
288   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
289                                                    getTypePtr()->getArgs(),
290                                                    getArgInfos(), Loc);
291 }
292
293 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 
294                                                       unsigned NumArgs,
295                                                   const TemplateArgument *Args,
296                                               TemplateArgumentLocInfo *ArgInfos,
297                                                       SourceLocation Loc) {
298   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
299     switch (Args[i].getKind()) {
300     case TemplateArgument::Null: 
301     case TemplateArgument::Declaration:
302     case TemplateArgument::Integral:
303     case TemplateArgument::Pack:
304     case TemplateArgument::Expression:
305       // FIXME: Can we do better for declarations and integral values?
306       ArgInfos[i] = TemplateArgumentLocInfo();
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 }
335