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