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