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
22static const unsigned TypeLocMaxDataAlign = llvm::alignOf<void *>();
23
24//===----------------------------------------------------------------------===//
25// TypeLoc Implementation
26//===----------------------------------------------------------------------===//
27
28namespace {
29  class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
30  public:
31#define ABSTRACT_TYPELOC(CLASS, PARENT)
32#define TYPELOC(CLASS, PARENT) \
33    SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
34      return TyLoc.getLocalSourceRange(); \
35    }
36#include "clang/AST/TypeLocNodes.def"
37  };
38}
39
40SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
41  if (TL.isNull()) return SourceRange();
42  return TypeLocRanger().Visit(TL);
43}
44
45namespace {
46  class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
47  public:
48#define ABSTRACT_TYPELOC(CLASS, PARENT)
49#define TYPELOC(CLASS, PARENT) \
50    unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
51      return TyLoc.getLocalDataAlignment(); \
52    }
53#include "clang/AST/TypeLocNodes.def"
54  };
55}
56
57/// \brief Returns the alignment of the type source info data block.
58unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
59  if (Ty.isNull()) return 1;
60  return TypeAligner().Visit(TypeLoc(Ty, nullptr));
61}
62
63namespace {
64  class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
65  public:
66#define ABSTRACT_TYPELOC(CLASS, PARENT)
67#define TYPELOC(CLASS, PARENT) \
68    unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
69      return TyLoc.getLocalDataSize(); \
70    }
71#include "clang/AST/TypeLocNodes.def"
72  };
73}
74
75/// \brief Returns the size of the type source info data block.
76unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
77  unsigned Total = 0;
78  TypeLoc TyLoc(Ty, nullptr);
79  unsigned MaxAlign = 1;
80  while (!TyLoc.isNull()) {
81    unsigned Align = getLocalAlignmentForType(TyLoc.getType());
82    MaxAlign = std::max(Align, MaxAlign);
83    Total = llvm::RoundUpToAlignment(Total, Align);
84    Total += TypeSizer().Visit(TyLoc);
85    TyLoc = TyLoc.getNextTypeLoc();
86  }
87  Total = llvm::RoundUpToAlignment(Total, MaxAlign);
88  return Total;
89}
90
91namespace {
92  class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
93  public:
94#define ABSTRACT_TYPELOC(CLASS, PARENT)
95#define TYPELOC(CLASS, PARENT) \
96    TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
97      return TyLoc.getNextTypeLoc(); \
98    }
99#include "clang/AST/TypeLocNodes.def"
100  };
101}
102
103/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
104/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
105TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
106  return NextLoc().Visit(TL);
107}
108
109/// \brief Initializes a type location, and all of its children
110/// recursively, as if the entire tree had been written in the
111/// given location.
112void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
113                             SourceLocation Loc) {
114  while (true) {
115    switch (TL.getTypeLocClass()) {
116#define ABSTRACT_TYPELOC(CLASS, PARENT)
117#define TYPELOC(CLASS, PARENT)        \
118    case CLASS: {                     \
119      CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
120      TLCasted.initializeLocal(Context, Loc);  \
121      TL = TLCasted.getNextTypeLoc(); \
122      if (!TL) return;                \
123      continue;                       \
124    }
125#include "clang/AST/TypeLocNodes.def"
126    }
127  }
128}
129
130namespace {
131  class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
132    TypeLoc Source;
133  public:
134    TypeLocCopier(TypeLoc source) : Source(source) { }
135
136#define ABSTRACT_TYPELOC(CLASS, PARENT)
137#define TYPELOC(CLASS, PARENT)                          \
138    void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) {   \
139      dest.copyLocal(Source.castAs<CLASS##TypeLoc>());  \
140    }
141#include "clang/AST/TypeLocNodes.def"
142  };
143}
144
145
146void TypeLoc::copy(TypeLoc other) {
147  assert(getFullDataSize() == other.getFullDataSize());
148
149  // If both data pointers are aligned to the maximum alignment, we
150  // can memcpy because getFullDataSize() accurately reflects the
151  // layout of the data.
152  if (reinterpret_cast<uintptr_t>(Data)
153        == llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(Data),
154                                    TypeLocMaxDataAlign) &&
155      reinterpret_cast<uintptr_t>(other.Data)
156        == llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(other.Data),
157                                    TypeLocMaxDataAlign)) {
158    memcpy(Data, other.Data, getFullDataSize());
159    return;
160  }
161
162  // Copy each of the pieces.
163  TypeLoc TL(getType(), Data);
164  do {
165    TypeLocCopier(other).Visit(TL);
166    other = other.getNextTypeLoc();
167  } while ((TL = TL.getNextTypeLoc()));
168}
169
170SourceLocation TypeLoc::getBeginLoc() const {
171  TypeLoc Cur = *this;
172  TypeLoc LeftMost = Cur;
173  while (true) {
174    switch (Cur.getTypeLocClass()) {
175    case Elaborated:
176      LeftMost = Cur;
177      break;
178    case FunctionProto:
179      if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
180              ->hasTrailingReturn()) {
181        LeftMost = Cur;
182        break;
183      }
184      /* Fall through */
185    case FunctionNoProto:
186    case ConstantArray:
187    case DependentSizedArray:
188    case IncompleteArray:
189    case VariableArray:
190      // FIXME: Currently QualifiedTypeLoc does not have a source range
191    case Qualified:
192      Cur = Cur.getNextTypeLoc();
193      continue;
194    default:
195      if (Cur.getLocalSourceRange().getBegin().isValid())
196        LeftMost = Cur;
197      Cur = Cur.getNextTypeLoc();
198      if (Cur.isNull())
199        break;
200      continue;
201    } // switch
202    break;
203  } // while
204  return LeftMost.getLocalSourceRange().getBegin();
205}
206
207SourceLocation TypeLoc::getEndLoc() const {
208  TypeLoc Cur = *this;
209  TypeLoc Last;
210  while (true) {
211    switch (Cur.getTypeLocClass()) {
212    default:
213      if (!Last)
214	Last = Cur;
215      return Last.getLocalSourceRange().getEnd();
216    case Paren:
217    case ConstantArray:
218    case DependentSizedArray:
219    case IncompleteArray:
220    case VariableArray:
221    case FunctionNoProto:
222      Last = Cur;
223      break;
224    case FunctionProto:
225      if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
226        Last = TypeLoc();
227      else
228        Last = Cur;
229      break;
230    case Pointer:
231    case BlockPointer:
232    case MemberPointer:
233    case LValueReference:
234    case RValueReference:
235    case PackExpansion:
236      if (!Last)
237	Last = Cur;
238      break;
239    case Qualified:
240    case Elaborated:
241      break;
242    }
243    Cur = Cur.getNextTypeLoc();
244  }
245}
246
247
248namespace {
249  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
250    // Overload resolution does the real work for us.
251    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
252    static bool isTypeSpec(TypeLoc _) { return false; }
253
254#define ABSTRACT_TYPELOC(CLASS, PARENT)
255#define TYPELOC(CLASS, PARENT) \
256    bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
257      return isTypeSpec(TyLoc); \
258    }
259#include "clang/AST/TypeLocNodes.def"
260  };
261}
262
263
264/// \brief Determines if the given type loc corresponds to a
265/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
266/// the type hierarchy, this is made somewhat complicated.
267///
268/// There are a lot of types that currently use TypeSpecTypeLoc
269/// because it's a convenient base class.  Ideally we would not accept
270/// those here, but ideally we would have better implementations for
271/// them.
272bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
273  if (TL.getType().hasLocalQualifiers()) return false;
274  return TSTChecker().Visit(TL);
275}
276
277// Reimplemented to account for GNU/C++ extension
278//     typeof unary-expression
279// where there are no parentheses.
280SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
281  if (getRParenLoc().isValid())
282    return SourceRange(getTypeofLoc(), getRParenLoc());
283  else
284    return SourceRange(getTypeofLoc(),
285                       getUnderlyingExpr()->getSourceRange().getEnd());
286}
287
288
289TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
290  if (needsExtraLocalData())
291    return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
292  switch (getTypePtr()->getKind()) {
293  case BuiltinType::Void:
294    return TST_void;
295  case BuiltinType::Bool:
296    return TST_bool;
297  case BuiltinType::Char_U:
298  case BuiltinType::Char_S:
299    return TST_char;
300  case BuiltinType::Char16:
301    return TST_char16;
302  case BuiltinType::Char32:
303    return TST_char32;
304  case BuiltinType::WChar_S:
305  case BuiltinType::WChar_U:
306    return TST_wchar;
307  case BuiltinType::UChar:
308  case BuiltinType::UShort:
309  case BuiltinType::UInt:
310  case BuiltinType::ULong:
311  case BuiltinType::ULongLong:
312  case BuiltinType::UInt128:
313  case BuiltinType::SChar:
314  case BuiltinType::Short:
315  case BuiltinType::Int:
316  case BuiltinType::Long:
317  case BuiltinType::LongLong:
318  case BuiltinType::Int128:
319  case BuiltinType::Half:
320  case BuiltinType::Float:
321  case BuiltinType::Double:
322  case BuiltinType::LongDouble:
323    llvm_unreachable("Builtin type needs extra local data!");
324    // Fall through, if the impossible happens.
325
326  case BuiltinType::NullPtr:
327  case BuiltinType::Overload:
328  case BuiltinType::Dependent:
329  case BuiltinType::BoundMember:
330  case BuiltinType::UnknownAny:
331  case BuiltinType::ARCUnbridgedCast:
332  case BuiltinType::PseudoObject:
333  case BuiltinType::ObjCId:
334  case BuiltinType::ObjCClass:
335  case BuiltinType::ObjCSel:
336  case BuiltinType::OCLImage1d:
337  case BuiltinType::OCLImage1dArray:
338  case BuiltinType::OCLImage1dBuffer:
339  case BuiltinType::OCLImage2d:
340  case BuiltinType::OCLImage2dArray:
341  case BuiltinType::OCLImage2dDepth:
342  case BuiltinType::OCLImage2dArrayDepth:
343  case BuiltinType::OCLImage2dMSAA:
344  case BuiltinType::OCLImage2dArrayMSAA:
345  case BuiltinType::OCLImage2dMSAADepth:
346  case BuiltinType::OCLImage2dArrayMSAADepth:
347  case BuiltinType::OCLImage3d:
348  case BuiltinType::OCLSampler:
349  case BuiltinType::OCLEvent:
350  case BuiltinType::OCLClkEvent:
351  case BuiltinType::OCLQueue:
352  case BuiltinType::OCLNDRange:
353  case BuiltinType::OCLReserveID:
354  case BuiltinType::BuiltinFn:
355  case BuiltinType::OMPArraySection:
356    return TST_unspecified;
357  }
358
359  llvm_unreachable("Invalid BuiltinType Kind!");
360}
361
362TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
363  while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
364    TL = PTL.getInnerLoc();
365  return TL;
366}
367
368SourceLocation TypeLoc::findNullabilityLoc() const {
369  if (auto attributedLoc = getAs<AttributedTypeLoc>()) {
370    if (attributedLoc.getAttrKind() == AttributedType::attr_nullable ||
371        attributedLoc.getAttrKind() == AttributedType::attr_nonnull ||
372        attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified)
373      return attributedLoc.getAttrNameLoc();
374  }
375
376  return SourceLocation();
377}
378
379TypeLoc TypeLoc::findExplicitQualifierLoc() const {
380  // Qualified types.
381  if (auto qual = getAs<QualifiedTypeLoc>())
382    return qual;
383
384  TypeLoc loc = IgnoreParens();
385
386  // Attributed types.
387  if (auto attr = loc.getAs<AttributedTypeLoc>()) {
388    if (attr.isQualifier()) return attr;
389    return attr.getModifiedLoc().findExplicitQualifierLoc();
390  }
391
392  // C11 _Atomic types.
393  if (auto atomic = loc.getAs<AtomicTypeLoc>()) {
394    return atomic;
395  }
396
397  return TypeLoc();
398}
399
400void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
401                                        SourceLocation Loc) {
402  setHasBaseTypeAsWritten(true);
403  setTypeArgsLAngleLoc(Loc);
404  setTypeArgsRAngleLoc(Loc);
405  for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
406    setTypeArgTInfo(i,
407                   Context.getTrivialTypeSourceInfo(
408                     getTypePtr()->getTypeArgsAsWritten()[i], Loc));
409  }
410  setProtocolLAngleLoc(Loc);
411  setProtocolRAngleLoc(Loc);
412  for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
413    setProtocolLoc(i, Loc);
414}
415
416void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
417                                       SourceLocation Loc) {
418  TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
419      ::initializeLocal(Context, Loc);
420  this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
421      getUnderlyingType(), Loc);
422}
423
424void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
425                                        SourceLocation Loc) {
426  setElaboratedKeywordLoc(Loc);
427  NestedNameSpecifierLocBuilder Builder;
428  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
429  setQualifierLoc(Builder.getWithLocInContext(Context));
430}
431
432void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
433                                           SourceLocation Loc) {
434  setElaboratedKeywordLoc(Loc);
435  NestedNameSpecifierLocBuilder Builder;
436  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
437  setQualifierLoc(Builder.getWithLocInContext(Context));
438  setNameLoc(Loc);
439}
440
441void
442DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
443                                                        SourceLocation Loc) {
444  setElaboratedKeywordLoc(Loc);
445  if (getTypePtr()->getQualifier()) {
446    NestedNameSpecifierLocBuilder Builder;
447    Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
448    setQualifierLoc(Builder.getWithLocInContext(Context));
449  } else {
450    setQualifierLoc(NestedNameSpecifierLoc());
451  }
452  setTemplateKeywordLoc(Loc);
453  setTemplateNameLoc(Loc);
454  setLAngleLoc(Loc);
455  setRAngleLoc(Loc);
456  TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
457                                                   getTypePtr()->getArgs(),
458                                                   getArgInfos(), Loc);
459}
460
461void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
462                                                      unsigned NumArgs,
463                                                  const TemplateArgument *Args,
464                                              TemplateArgumentLocInfo *ArgInfos,
465                                                      SourceLocation Loc) {
466  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
467    switch (Args[i].getKind()) {
468    case TemplateArgument::Null:
469      llvm_unreachable("Impossible TemplateArgument");
470
471    case TemplateArgument::Integral:
472    case TemplateArgument::Declaration:
473    case TemplateArgument::NullPtr:
474      ArgInfos[i] = TemplateArgumentLocInfo();
475      break;
476
477    case TemplateArgument::Expression:
478      ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
479      break;
480
481    case TemplateArgument::Type:
482      ArgInfos[i] = TemplateArgumentLocInfo(
483                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
484                                                           Loc));
485      break;
486
487    case TemplateArgument::Template:
488    case TemplateArgument::TemplateExpansion: {
489      NestedNameSpecifierLocBuilder Builder;
490      TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
491      if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
492        Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
493      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
494        Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
495
496      ArgInfos[i] = TemplateArgumentLocInfo(
497          Builder.getWithLocInContext(Context), Loc,
498          Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
499                                                          : Loc);
500      break;
501    }
502
503    case TemplateArgument::Pack:
504      ArgInfos[i] = TemplateArgumentLocInfo();
505      break;
506    }
507  }
508}
509