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 
getLocalSourceRangeImpl(TypeLoc TL)38 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
39   if (TL.isNull()) return SourceRange();
40   return TypeLocRanger().Visit(TL);
41 }
42 
43 namespace {
44   class TypeAligner : public TypeLocVisitor<TypeAligner, 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.getLocalDataAlignment(); \
50     }
51 #include "clang/AST/TypeLocNodes.def"
52   };
53 }
54 
55 /// \brief Returns the alignment of the type source info data block.
getLocalAlignmentForType(QualType Ty)56 unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
57   if (Ty.isNull()) return 1;
58   return TypeAligner().Visit(TypeLoc(Ty, nullptr));
59 }
60 
61 namespace {
62   class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
63   public:
64 #define ABSTRACT_TYPELOC(CLASS, PARENT)
65 #define TYPELOC(CLASS, PARENT) \
66     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
67       return TyLoc.getLocalDataSize(); \
68     }
69 #include "clang/AST/TypeLocNodes.def"
70   };
71 }
72 
73 /// \brief Returns the size of the type source info data block.
getFullDataSizeForType(QualType Ty)74 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
75   unsigned Total = 0;
76   TypeLoc TyLoc(Ty, nullptr);
77   unsigned MaxAlign = 1;
78   while (!TyLoc.isNull()) {
79     unsigned Align = getLocalAlignmentForType(TyLoc.getType());
80     MaxAlign = std::max(Align, MaxAlign);
81     Total = llvm::RoundUpToAlignment(Total, Align);
82     Total += TypeSizer().Visit(TyLoc);
83     TyLoc = TyLoc.getNextTypeLoc();
84   }
85   Total = llvm::RoundUpToAlignment(Total, MaxAlign);
86   return Total;
87 }
88 
89 namespace {
90   class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
91   public:
92 #define ABSTRACT_TYPELOC(CLASS, PARENT)
93 #define TYPELOC(CLASS, PARENT) \
94     TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
95       return TyLoc.getNextTypeLoc(); \
96     }
97 #include "clang/AST/TypeLocNodes.def"
98   };
99 }
100 
101 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
102 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
getNextTypeLocImpl(TypeLoc TL)103 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
104   return NextLoc().Visit(TL);
105 }
106 
107 /// \brief Initializes a type location, and all of its children
108 /// recursively, as if the entire tree had been written in the
109 /// given location.
initializeImpl(ASTContext & Context,TypeLoc TL,SourceLocation Loc)110 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
111                              SourceLocation Loc) {
112   while (true) {
113     switch (TL.getTypeLocClass()) {
114 #define ABSTRACT_TYPELOC(CLASS, PARENT)
115 #define TYPELOC(CLASS, PARENT)        \
116     case CLASS: {                     \
117       CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
118       TLCasted.initializeLocal(Context, Loc);  \
119       TL = TLCasted.getNextTypeLoc(); \
120       if (!TL) return;                \
121       continue;                       \
122     }
123 #include "clang/AST/TypeLocNodes.def"
124     }
125   }
126 }
127 
getBeginLoc() const128 SourceLocation TypeLoc::getBeginLoc() const {
129   TypeLoc Cur = *this;
130   TypeLoc LeftMost = Cur;
131   while (true) {
132     switch (Cur.getTypeLocClass()) {
133     case Elaborated:
134       LeftMost = Cur;
135       break;
136     case FunctionProto:
137       if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
138               ->hasTrailingReturn()) {
139         LeftMost = Cur;
140         break;
141       }
142       /* Fall through */
143     case FunctionNoProto:
144     case ConstantArray:
145     case DependentSizedArray:
146     case IncompleteArray:
147     case VariableArray:
148       // FIXME: Currently QualifiedTypeLoc does not have a source range
149     case Qualified:
150       Cur = Cur.getNextTypeLoc();
151       continue;
152     default:
153       if (!Cur.getLocalSourceRange().getBegin().isInvalid())
154         LeftMost = Cur;
155       Cur = Cur.getNextTypeLoc();
156       if (Cur.isNull())
157         break;
158       continue;
159     } // switch
160     break;
161   } // while
162   return LeftMost.getLocalSourceRange().getBegin();
163 }
164 
getEndLoc() const165 SourceLocation TypeLoc::getEndLoc() const {
166   TypeLoc Cur = *this;
167   TypeLoc Last;
168   while (true) {
169     switch (Cur.getTypeLocClass()) {
170     default:
171       if (!Last)
172 	Last = Cur;
173       return Last.getLocalSourceRange().getEnd();
174     case Paren:
175     case ConstantArray:
176     case DependentSizedArray:
177     case IncompleteArray:
178     case VariableArray:
179     case FunctionNoProto:
180       Last = Cur;
181       break;
182     case FunctionProto:
183       if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
184         Last = TypeLoc();
185       else
186         Last = Cur;
187       break;
188     case Pointer:
189     case BlockPointer:
190     case MemberPointer:
191     case LValueReference:
192     case RValueReference:
193     case PackExpansion:
194       if (!Last)
195 	Last = Cur;
196       break;
197     case Qualified:
198     case Elaborated:
199       break;
200     }
201     Cur = Cur.getNextTypeLoc();
202   }
203 }
204 
205 
206 namespace {
207   struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
208     // Overload resolution does the real work for us.
isTypeSpec__anone4cb4f9c0511::TSTChecker209     static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
isTypeSpec__anone4cb4f9c0511::TSTChecker210     static bool isTypeSpec(TypeLoc _) { return false; }
211 
212 #define ABSTRACT_TYPELOC(CLASS, PARENT)
213 #define TYPELOC(CLASS, PARENT) \
214     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
215       return isTypeSpec(TyLoc); \
216     }
217 #include "clang/AST/TypeLocNodes.def"
218   };
219 }
220 
221 
222 /// \brief Determines if the given type loc corresponds to a
223 /// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
224 /// the type hierarchy, this is made somewhat complicated.
225 ///
226 /// There are a lot of types that currently use TypeSpecTypeLoc
227 /// because it's a convenient base class.  Ideally we would not accept
228 /// those here, but ideally we would have better implementations for
229 /// them.
isKind(const TypeLoc & TL)230 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
231   if (TL.getType().hasLocalQualifiers()) return false;
232   return TSTChecker().Visit(TL);
233 }
234 
235 // Reimplemented to account for GNU/C++ extension
236 //     typeof unary-expression
237 // where there are no parentheses.
getLocalSourceRange() const238 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
239   if (getRParenLoc().isValid())
240     return SourceRange(getTypeofLoc(), getRParenLoc());
241   else
242     return SourceRange(getTypeofLoc(),
243                        getUnderlyingExpr()->getSourceRange().getEnd());
244 }
245 
246 
getWrittenTypeSpec() const247 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
248   if (needsExtraLocalData())
249     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
250   switch (getTypePtr()->getKind()) {
251   case BuiltinType::Void:
252     return TST_void;
253   case BuiltinType::Bool:
254     return TST_bool;
255   case BuiltinType::Char_U:
256   case BuiltinType::Char_S:
257     return TST_char;
258   case BuiltinType::Char16:
259     return TST_char16;
260   case BuiltinType::Char32:
261     return TST_char32;
262   case BuiltinType::WChar_S:
263   case BuiltinType::WChar_U:
264     return TST_wchar;
265   case BuiltinType::UChar:
266   case BuiltinType::UShort:
267   case BuiltinType::UInt:
268   case BuiltinType::ULong:
269   case BuiltinType::ULongLong:
270   case BuiltinType::UInt128:
271   case BuiltinType::SChar:
272   case BuiltinType::Short:
273   case BuiltinType::Int:
274   case BuiltinType::Long:
275   case BuiltinType::LongLong:
276   case BuiltinType::Int128:
277   case BuiltinType::Half:
278   case BuiltinType::Float:
279   case BuiltinType::Double:
280   case BuiltinType::LongDouble:
281     llvm_unreachable("Builtin type needs extra local data!");
282     // Fall through, if the impossible happens.
283 
284   case BuiltinType::NullPtr:
285   case BuiltinType::Overload:
286   case BuiltinType::Dependent:
287   case BuiltinType::BoundMember:
288   case BuiltinType::UnknownAny:
289   case BuiltinType::ARCUnbridgedCast:
290   case BuiltinType::PseudoObject:
291   case BuiltinType::ObjCId:
292   case BuiltinType::ObjCClass:
293   case BuiltinType::ObjCSel:
294   case BuiltinType::OCLImage1d:
295   case BuiltinType::OCLImage1dArray:
296   case BuiltinType::OCLImage1dBuffer:
297   case BuiltinType::OCLImage2d:
298   case BuiltinType::OCLImage2dArray:
299   case BuiltinType::OCLImage3d:
300   case BuiltinType::OCLSampler:
301   case BuiltinType::OCLEvent:
302   case BuiltinType::BuiltinFn:
303     return TST_unspecified;
304   }
305 
306   llvm_unreachable("Invalid BuiltinType Kind!");
307 }
308 
IgnoreParensImpl(TypeLoc TL)309 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
310   while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
311     TL = PTL.getInnerLoc();
312   return TL;
313 }
314 
initializeLocal(ASTContext & Context,SourceLocation Loc)315 void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
316                                        SourceLocation Loc) {
317   TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
318       ::initializeLocal(Context, Loc);
319   this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
320       getUnderlyingType(), Loc);
321 }
322 
initializeLocal(ASTContext & Context,SourceLocation Loc)323 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
324                                         SourceLocation Loc) {
325   setElaboratedKeywordLoc(Loc);
326   NestedNameSpecifierLocBuilder Builder;
327   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
328   setQualifierLoc(Builder.getWithLocInContext(Context));
329 }
330 
initializeLocal(ASTContext & Context,SourceLocation Loc)331 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
332                                            SourceLocation Loc) {
333   setElaboratedKeywordLoc(Loc);
334   NestedNameSpecifierLocBuilder Builder;
335   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
336   setQualifierLoc(Builder.getWithLocInContext(Context));
337   setNameLoc(Loc);
338 }
339 
340 void
initializeLocal(ASTContext & Context,SourceLocation Loc)341 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
342                                                         SourceLocation Loc) {
343   setElaboratedKeywordLoc(Loc);
344   if (getTypePtr()->getQualifier()) {
345     NestedNameSpecifierLocBuilder Builder;
346     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
347     setQualifierLoc(Builder.getWithLocInContext(Context));
348   } else {
349     setQualifierLoc(NestedNameSpecifierLoc());
350   }
351   setTemplateKeywordLoc(Loc);
352   setTemplateNameLoc(Loc);
353   setLAngleLoc(Loc);
354   setRAngleLoc(Loc);
355   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
356                                                    getTypePtr()->getArgs(),
357                                                    getArgInfos(), Loc);
358 }
359 
initializeArgLocs(ASTContext & Context,unsigned NumArgs,const TemplateArgument * Args,TemplateArgumentLocInfo * ArgInfos,SourceLocation Loc)360 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
361                                                       unsigned NumArgs,
362                                                   const TemplateArgument *Args,
363                                               TemplateArgumentLocInfo *ArgInfos,
364                                                       SourceLocation Loc) {
365   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
366     switch (Args[i].getKind()) {
367     case TemplateArgument::Null:
368       llvm_unreachable("Impossible TemplateArgument");
369 
370     case TemplateArgument::Integral:
371     case TemplateArgument::Declaration:
372     case TemplateArgument::NullPtr:
373       ArgInfos[i] = TemplateArgumentLocInfo();
374       break;
375 
376     case TemplateArgument::Expression:
377       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
378       break;
379 
380     case TemplateArgument::Type:
381       ArgInfos[i] = TemplateArgumentLocInfo(
382                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
383                                                            Loc));
384       break;
385 
386     case TemplateArgument::Template:
387     case TemplateArgument::TemplateExpansion: {
388       NestedNameSpecifierLocBuilder Builder;
389       TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
390       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
391         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
392       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
393         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
394 
395       ArgInfos[i] = TemplateArgumentLocInfo(
396           Builder.getWithLocInContext(Context), Loc,
397           Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
398                                                           : Loc);
399       break;
400     }
401 
402     case TemplateArgument::Pack:
403       ArgInfos[i] = TemplateArgumentLocInfo();
404       break;
405     }
406   }
407 }
408