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