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"
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// TypeLoc Implementation
24//===----------------------------------------------------------------------===//
25
26namespace {
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
38SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
39  if (TL.isNull()) return SourceRange();
40  return TypeLocRanger().Visit(TL);
41}
42
43namespace {
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.
56unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
57  if (Ty.isNull()) return 1;
58  return TypeAligner().Visit(TypeLoc(Ty, nullptr));
59}
60
61namespace {
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.
74unsigned 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
89namespace {
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".
103TypeLoc 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.
110void 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
128SourceLocation 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
165SourceLocation 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
206namespace {
207  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
208    // Overload resolution does the real work for us.
209    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
210    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.
230bool 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.
238SourceRange 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
247TypeSpecifierType 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
309TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
310  while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
311    TL = PTL.getInnerLoc();
312  return TL;
313}
314
315void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
316                                        SourceLocation Loc) {
317  setElaboratedKeywordLoc(Loc);
318  NestedNameSpecifierLocBuilder Builder;
319  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
320  setQualifierLoc(Builder.getWithLocInContext(Context));
321}
322
323void DependentNameTypeLoc::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  setNameLoc(Loc);
330}
331
332void
333DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
334                                                        SourceLocation Loc) {
335  setElaboratedKeywordLoc(Loc);
336  if (getTypePtr()->getQualifier()) {
337    NestedNameSpecifierLocBuilder Builder;
338    Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
339    setQualifierLoc(Builder.getWithLocInContext(Context));
340  } else {
341    setQualifierLoc(NestedNameSpecifierLoc());
342  }
343  setTemplateKeywordLoc(Loc);
344  setTemplateNameLoc(Loc);
345  setLAngleLoc(Loc);
346  setRAngleLoc(Loc);
347  TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
348                                                   getTypePtr()->getArgs(),
349                                                   getArgInfos(), Loc);
350}
351
352void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
353                                                      unsigned NumArgs,
354                                                  const TemplateArgument *Args,
355                                              TemplateArgumentLocInfo *ArgInfos,
356                                                      SourceLocation Loc) {
357  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
358    switch (Args[i].getKind()) {
359    case TemplateArgument::Null:
360      llvm_unreachable("Impossible TemplateArgument");
361
362    case TemplateArgument::Integral:
363    case TemplateArgument::Declaration:
364    case TemplateArgument::NullPtr:
365      ArgInfos[i] = TemplateArgumentLocInfo();
366      break;
367
368    case TemplateArgument::Expression:
369      ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
370      break;
371
372    case TemplateArgument::Type:
373      ArgInfos[i] = TemplateArgumentLocInfo(
374                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
375                                                           Loc));
376      break;
377
378    case TemplateArgument::Template:
379    case TemplateArgument::TemplateExpansion: {
380      NestedNameSpecifierLocBuilder Builder;
381      TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
382      if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
383        Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
384      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
385        Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
386
387      ArgInfos[i] = TemplateArgumentLocInfo(
388          Builder.getWithLocInContext(Context), Loc,
389          Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
390                                                          : Loc);
391      break;
392    }
393
394    case TemplateArgument::Pack:
395      ArgInfos[i] = TemplateArgumentLocInfo();
396      break;
397    }
398  }
399}
400