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