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