]> granicus.if.org Git - clang/blob - lib/AST/TypeLoc.cpp
Add OpenCL samplers as Clang builtin types and check sampler related restrictions.
[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 = cast<CLASS##TypeLoc>(TL); \
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 (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) {
110         LeftMost = Cur;
111         break;
112       }
113       /* Fall through */
114     case FunctionNoProto:
115     case ConstantArray:
116     case DependentSizedArray:
117     case IncompleteArray:
118     case VariableArray:
119       // FIXME: Currently QualifiedTypeLoc does not have a source range
120     case Qualified:
121       Cur = Cur.getNextTypeLoc();
122       continue;
123     default:
124       if (!Cur.getLocalSourceRange().getBegin().isInvalid())
125         LeftMost = Cur;
126       Cur = Cur.getNextTypeLoc();
127       if (Cur.isNull())
128         break;
129       continue;
130     } // switch
131     break;
132   } // while
133   return LeftMost.getLocalSourceRange().getBegin();
134 }
135
136 SourceLocation TypeLoc::getEndLoc() const {
137   TypeLoc Cur = *this;
138   TypeLoc Last;
139   while (true) {
140     switch (Cur.getTypeLocClass()) {
141     default:
142       if (!Last)
143         Last = Cur;
144       return Last.getLocalSourceRange().getEnd();
145     case Paren:
146     case ConstantArray:
147     case DependentSizedArray:
148     case IncompleteArray:
149     case VariableArray:
150     case FunctionNoProto:
151       Last = Cur;
152       break;
153     case FunctionProto:
154       if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn())
155         Last = TypeLoc();
156       else
157         Last = Cur;
158       break;
159     case Pointer:
160     case BlockPointer:
161     case MemberPointer:
162     case LValueReference:
163     case RValueReference:
164     case PackExpansion:
165       if (!Last)
166         Last = Cur;
167       break;
168     case Qualified:
169     case Elaborated:
170       break;
171     }
172     Cur = Cur.getNextTypeLoc();
173   }
174 }
175
176
177 namespace {
178   struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
179     // Overload resolution does the real work for us.
180     static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
181     static bool isTypeSpec(TypeLoc _) { return false; }
182
183 #define ABSTRACT_TYPELOC(CLASS, PARENT)
184 #define TYPELOC(CLASS, PARENT) \
185     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
186       return isTypeSpec(TyLoc); \
187     }
188 #include "clang/AST/TypeLocNodes.def"
189   };
190 }
191
192
193 /// \brief Determines if the given type loc corresponds to a
194 /// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
195 /// the type hierarchy, this is made somewhat complicated.
196 ///
197 /// There are a lot of types that currently use TypeSpecTypeLoc
198 /// because it's a convenient base class.  Ideally we would not accept
199 /// those here, but ideally we would have better implementations for
200 /// them.
201 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
202   if (TL->getType().hasLocalQualifiers()) return false;
203   return TSTChecker().Visit(*TL);
204 }
205
206 // Reimplemented to account for GNU/C++ extension
207 //     typeof unary-expression
208 // where there are no parentheses.
209 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
210   if (getRParenLoc().isValid())
211     return SourceRange(getTypeofLoc(), getRParenLoc());
212   else
213     return SourceRange(getTypeofLoc(),
214                        getUnderlyingExpr()->getSourceRange().getEnd());
215 }
216
217
218 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
219   if (needsExtraLocalData())
220     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
221   switch (getTypePtr()->getKind()) {
222   case BuiltinType::Void:
223     return TST_void;
224   case BuiltinType::Bool:
225     return TST_bool;
226   case BuiltinType::Char_U:
227   case BuiltinType::Char_S:
228     return TST_char;
229   case BuiltinType::Char16:
230     return TST_char16;
231   case BuiltinType::Char32:
232     return TST_char32;
233   case BuiltinType::WChar_S:
234   case BuiltinType::WChar_U:
235     return TST_wchar;
236   case BuiltinType::UChar:
237   case BuiltinType::UShort:
238   case BuiltinType::UInt:
239   case BuiltinType::ULong:
240   case BuiltinType::ULongLong:
241   case BuiltinType::UInt128:
242   case BuiltinType::SChar:
243   case BuiltinType::Short:
244   case BuiltinType::Int:
245   case BuiltinType::Long:
246   case BuiltinType::LongLong:
247   case BuiltinType::Int128:
248   case BuiltinType::Half:
249   case BuiltinType::Float:
250   case BuiltinType::Double:
251   case BuiltinType::LongDouble:
252     llvm_unreachable("Builtin type needs extra local data!");
253     // Fall through, if the impossible happens.
254       
255   case BuiltinType::NullPtr:
256   case BuiltinType::Overload:
257   case BuiltinType::Dependent:
258   case BuiltinType::BoundMember:
259   case BuiltinType::UnknownAny:
260   case BuiltinType::ARCUnbridgedCast:
261   case BuiltinType::PseudoObject:
262   case BuiltinType::ObjCId:
263   case BuiltinType::ObjCClass:
264   case BuiltinType::ObjCSel:
265   case BuiltinType::OCLImage1d:
266   case BuiltinType::OCLImage1dArray:
267   case BuiltinType::OCLImage1dBuffer:
268   case BuiltinType::OCLImage2d:
269   case BuiltinType::OCLImage2dArray:
270   case BuiltinType::OCLImage3d:
271   case BuiltinType::OCLSampler:
272   case BuiltinType::OCLEvent:
273   case BuiltinType::BuiltinFn:
274     return TST_unspecified;
275   }
276
277   llvm_unreachable("Invalid BuiltinType Kind!");
278 }
279
280 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
281   while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
282     TL = PTL->getInnerLoc();
283   return TL;
284 }
285
286 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 
287                                         SourceLocation Loc) {
288   setElaboratedKeywordLoc(Loc);
289   NestedNameSpecifierLocBuilder Builder;
290   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
291   setQualifierLoc(Builder.getWithLocInContext(Context));
292 }
293
294 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 
295                                            SourceLocation Loc) {
296   setElaboratedKeywordLoc(Loc);
297   NestedNameSpecifierLocBuilder Builder;
298   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
299   setQualifierLoc(Builder.getWithLocInContext(Context));
300   setNameLoc(Loc);
301 }
302
303 void
304 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
305                                                         SourceLocation Loc) {
306   setElaboratedKeywordLoc(Loc);
307   if (getTypePtr()->getQualifier()) {
308     NestedNameSpecifierLocBuilder Builder;
309     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
310     setQualifierLoc(Builder.getWithLocInContext(Context));
311   } else {
312     setQualifierLoc(NestedNameSpecifierLoc());
313   }
314   setTemplateKeywordLoc(Loc);
315   setTemplateNameLoc(Loc);
316   setLAngleLoc(Loc);
317   setRAngleLoc(Loc);
318   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
319                                                    getTypePtr()->getArgs(),
320                                                    getArgInfos(), Loc);
321 }
322
323 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 
324                                                       unsigned NumArgs,
325                                                   const TemplateArgument *Args,
326                                               TemplateArgumentLocInfo *ArgInfos,
327                                                       SourceLocation Loc) {
328   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
329     switch (Args[i].getKind()) {
330     case TemplateArgument::Null: 
331     case TemplateArgument::Declaration:
332     case TemplateArgument::Integral:
333     case TemplateArgument::NullPtr:
334       llvm_unreachable("Impossible TemplateArgument");
335
336     case TemplateArgument::Expression:
337       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
338       break;
339       
340     case TemplateArgument::Type:
341       ArgInfos[i] = TemplateArgumentLocInfo(
342                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
343                                                            Loc));
344       break;
345
346     case TemplateArgument::Template:
347     case TemplateArgument::TemplateExpansion: {
348       NestedNameSpecifierLocBuilder Builder;
349       TemplateName Template = Args[i].getAsTemplate();
350       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
351         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
352       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
353         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
354       
355       ArgInfos[i] = TemplateArgumentLocInfo(
356                                            Builder.getWithLocInContext(Context),
357                                             Loc, 
358                                 Args[i].getKind() == TemplateArgument::Template
359                                             ? SourceLocation()
360                                             : Loc);
361       break;
362     }
363
364     case TemplateArgument::Pack:
365       ArgInfos[i] = TemplateArgumentLocInfo();
366       break;
367     }
368   }
369 }