]> granicus.if.org Git - clang/blob - lib/AST/TypeLoc.cpp
Drop the ASTContext.h include from Stmt.h and fix up transitive users.
[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/ASTContext.h"
17 #include "clang/AST/Expr.h"
18 #include "llvm/Support/ErrorHandling.h"
19 using namespace clang;
20
21 //===----------------------------------------------------------------------===//
22 // TypeLoc Implementation
23 //===----------------------------------------------------------------------===//
24
25 namespace {
26   class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
27   public:
28 #define ABSTRACT_TYPELOC(CLASS, PARENT)
29 #define TYPELOC(CLASS, PARENT) \
30     SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
31       return TyLoc.getLocalSourceRange(); \
32     }
33 #include "clang/AST/TypeLocNodes.def"
34   };
35 }
36
37 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
38   if (TL.isNull()) return SourceRange();
39   return TypeLocRanger().Visit(TL);
40 }
41
42 namespace {
43   class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
44   public:
45 #define ABSTRACT_TYPELOC(CLASS, PARENT)
46 #define TYPELOC(CLASS, PARENT) \
47     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
48       return TyLoc.getFullDataSize(); \
49     }
50 #include "clang/AST/TypeLocNodes.def"
51   };
52 }
53
54 /// \brief Returns the size of the type source info data block.
55 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
56   if (Ty.isNull()) return 0;
57   return TypeSizer().Visit(TypeLoc(Ty, 0));
58 }
59
60 namespace {
61   class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
62   public:
63 #define ABSTRACT_TYPELOC(CLASS, PARENT)
64 #define TYPELOC(CLASS, PARENT) \
65     TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
66       return TyLoc.getNextTypeLoc(); \
67     }
68 #include "clang/AST/TypeLocNodes.def"
69   };
70 }
71
72 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
73 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
74 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
75   return NextLoc().Visit(TL);
76 }
77
78 /// \brief Initializes a type location, and all of its children
79 /// recursively, as if the entire tree had been written in the
80 /// given location.
81 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 
82                              SourceLocation Loc) {
83   while (true) {
84     switch (TL.getTypeLocClass()) {
85 #define ABSTRACT_TYPELOC(CLASS, PARENT)
86 #define TYPELOC(CLASS, PARENT)        \
87     case CLASS: {                     \
88       CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
89       TLCasted.initializeLocal(Context, Loc);  \
90       TL = TLCasted.getNextTypeLoc(); \
91       if (!TL) return;                \
92       continue;                       \
93     }
94 #include "clang/AST/TypeLocNodes.def"
95     }
96   }
97 }
98
99 SourceLocation TypeLoc::getBeginLoc() const {
100   TypeLoc Cur = *this;
101   while (true) {
102     switch (Cur.getTypeLocClass()) {
103     // FIXME: Currently QualifiedTypeLoc does not have a source range
104     // case Qualified:
105     case Elaborated:
106     case DependentName:
107     case DependentTemplateSpecialization:
108       break;
109     default:
110       TypeLoc Next = Cur.getNextTypeLoc();
111       if (Next.isNull()) break;
112       Cur = Next;
113       continue;
114     }
115     break;
116   }
117   return Cur.getLocalSourceRange().getBegin();
118 }
119
120 SourceLocation TypeLoc::getEndLoc() const {
121   TypeLoc Cur = *this;
122   TypeLoc Last;
123   while (true) {
124     switch (Cur.getTypeLocClass()) {
125     default:
126       if (!Last)
127         Last = Cur;
128       return Last.getLocalSourceRange().getEnd();
129     case Paren:
130     case ConstantArray:
131     case DependentSizedArray:
132     case IncompleteArray:
133     case VariableArray:
134     case FunctionProto:
135     case FunctionNoProto:
136       Last = Cur;
137       break;
138     case Pointer:
139     case BlockPointer:
140     case MemberPointer:
141     case LValueReference:
142     case RValueReference:
143     case PackExpansion:
144       if (!Last)
145         Last = Cur;
146       break;
147     case Qualified:
148     case Elaborated:
149       break;
150     }
151     Cur = Cur.getNextTypeLoc();
152   }
153 }
154
155
156 namespace {
157   struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
158     // Overload resolution does the real work for us.
159     static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
160     static bool isTypeSpec(TypeLoc _) { return false; }
161
162 #define ABSTRACT_TYPELOC(CLASS, PARENT)
163 #define TYPELOC(CLASS, PARENT) \
164     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
165       return isTypeSpec(TyLoc); \
166     }
167 #include "clang/AST/TypeLocNodes.def"
168   };
169 }
170
171
172 /// \brief Determines if the given type loc corresponds to a
173 /// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
174 /// the type hierarchy, this is made somewhat complicated.
175 ///
176 /// There are a lot of types that currently use TypeSpecTypeLoc
177 /// because it's a convenient base class.  Ideally we would not accept
178 /// those here, but ideally we would have better implementations for
179 /// them.
180 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
181   if (TL->getType().hasLocalQualifiers()) return false;
182   return TSTChecker().Visit(*TL);
183 }
184
185 // Reimplemented to account for GNU/C++ extension
186 //     typeof unary-expression
187 // where there are no parentheses.
188 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
189   if (getRParenLoc().isValid())
190     return SourceRange(getTypeofLoc(), getRParenLoc());
191   else
192     return SourceRange(getTypeofLoc(),
193                        getUnderlyingExpr()->getSourceRange().getEnd());
194 }
195
196
197 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
198   if (needsExtraLocalData())
199     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
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   case BuiltinType::UChar:
216   case BuiltinType::UShort:
217   case BuiltinType::UInt:
218   case BuiltinType::ULong:
219   case BuiltinType::ULongLong:
220   case BuiltinType::UInt128:
221   case BuiltinType::SChar:
222   case BuiltinType::Short:
223   case BuiltinType::Int:
224   case BuiltinType::Long:
225   case BuiltinType::LongLong:
226   case BuiltinType::Int128:
227   case BuiltinType::Half:
228   case BuiltinType::Float:
229   case BuiltinType::Double:
230   case BuiltinType::LongDouble:
231     llvm_unreachable("Builtin type needs extra local data!");
232     // Fall through, if the impossible happens.
233       
234   case BuiltinType::NullPtr:
235   case BuiltinType::Overload:
236   case BuiltinType::Dependent:
237   case BuiltinType::BoundMember:
238   case BuiltinType::UnknownAny:
239   case BuiltinType::ARCUnbridgedCast:
240   case BuiltinType::PseudoObject:
241   case BuiltinType::ObjCId:
242   case BuiltinType::ObjCClass:
243   case BuiltinType::ObjCSel:
244     return TST_unspecified;
245   }
246
247   llvm_unreachable("Invalid BuiltinType Kind!");
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   setElaboratedKeywordLoc(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   setElaboratedKeywordLoc(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   setElaboratedKeywordLoc(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   setTemplateKeywordLoc(Loc);
285   setTemplateNameLoc(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       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
306       break;
307       
308     case TemplateArgument::Type:
309       ArgInfos[i] = TemplateArgumentLocInfo(
310                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
311                                                            Loc));
312       break;
313         
314     case TemplateArgument::Template:
315     case TemplateArgument::TemplateExpansion: {
316       NestedNameSpecifierLocBuilder Builder;
317       TemplateName Template = Args[i].getAsTemplate();
318       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
319         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
320       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
321         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
322       
323       ArgInfos[i] = TemplateArgumentLocInfo(
324                                            Builder.getWithLocInContext(Context),
325                                             Loc, 
326                                 Args[i].getKind() == TemplateArgument::Template
327                                             ? SourceLocation()
328                                             : Loc);
329       break;
330     }        
331     }
332   }
333 }