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