]> granicus.if.org Git - clang/blob - lib/AST/TypeLoc.cpp
Sort all of Clang's files under 'lib', and fix up the broken headers
[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::BuiltinFn:
266     return TST_unspecified;
267   }
268
269   llvm_unreachable("Invalid BuiltinType Kind!");
270 }
271
272 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
273   while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
274     TL = PTL->getInnerLoc();
275   return TL;
276 }
277
278 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 
279                                         SourceLocation Loc) {
280   setElaboratedKeywordLoc(Loc);
281   NestedNameSpecifierLocBuilder Builder;
282   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
283   setQualifierLoc(Builder.getWithLocInContext(Context));
284 }
285
286 void DependentNameTypeLoc::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   setNameLoc(Loc);
293 }
294
295 void
296 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
297                                                         SourceLocation Loc) {
298   setElaboratedKeywordLoc(Loc);
299   if (getTypePtr()->getQualifier()) {
300     NestedNameSpecifierLocBuilder Builder;
301     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
302     setQualifierLoc(Builder.getWithLocInContext(Context));
303   } else {
304     setQualifierLoc(NestedNameSpecifierLoc());
305   }
306   setTemplateKeywordLoc(Loc);
307   setTemplateNameLoc(Loc);
308   setLAngleLoc(Loc);
309   setRAngleLoc(Loc);
310   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
311                                                    getTypePtr()->getArgs(),
312                                                    getArgInfos(), Loc);
313 }
314
315 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 
316                                                       unsigned NumArgs,
317                                                   const TemplateArgument *Args,
318                                               TemplateArgumentLocInfo *ArgInfos,
319                                                       SourceLocation Loc) {
320   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
321     switch (Args[i].getKind()) {
322     case TemplateArgument::Null: 
323     case TemplateArgument::Declaration:
324     case TemplateArgument::Integral:
325     case TemplateArgument::NullPtr:
326       llvm_unreachable("Impossible TemplateArgument");
327
328     case TemplateArgument::Expression:
329       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
330       break;
331       
332     case TemplateArgument::Type:
333       ArgInfos[i] = TemplateArgumentLocInfo(
334                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
335                                                            Loc));
336       break;
337
338     case TemplateArgument::Template:
339     case TemplateArgument::TemplateExpansion: {
340       NestedNameSpecifierLocBuilder Builder;
341       TemplateName Template = Args[i].getAsTemplate();
342       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
343         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
344       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
345         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
346       
347       ArgInfos[i] = TemplateArgumentLocInfo(
348                                            Builder.getWithLocInContext(Context),
349                                             Loc, 
350                                 Args[i].getKind() == TemplateArgument::Template
351                                             ? SourceLocation()
352                                             : Loc);
353       break;
354     }
355
356     case TemplateArgument::Pack:
357       ArgInfos[i] = TemplateArgumentLocInfo();
358       break;
359     }
360   }
361 }