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    llvm_unreachable("Builtin type needs extra local data!");
379    // Fall through, if the impossible happens.
380
381  case BuiltinType::NullPtr:
382  case BuiltinType::Overload:
383  case BuiltinType::Dependent:
384  case BuiltinType::BoundMember:
385  case BuiltinType::UnknownAny:
386  case BuiltinType::ARCUnbridgedCast:
387  case BuiltinType::PseudoObject:
388  case BuiltinType::ObjCId:
389  case BuiltinType::ObjCClass:
390  case BuiltinType::ObjCSel:
391#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
392  case BuiltinType::Id:
393#include "clang/Basic/OpenCLImageTypes.def"
394#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
395  case BuiltinType::Id:
396#include "clang/Basic/OpenCLExtensionTypes.def"
397  case BuiltinType::OCLSampler:
398  case BuiltinType::OCLEvent:
399  case BuiltinType::OCLClkEvent:
400  case BuiltinType::OCLQueue:
401  case BuiltinType::OCLReserveID:
402#define SVE_TYPE(Name, Id, SingletonId) \
403  case BuiltinType::Id:
404#include "clang/Basic/AArch64SVEACLETypes.def"
405  case BuiltinType::BuiltinFn:
406  case BuiltinType::OMPArraySection:
407    return TST_unspecified;
408  }
409
410  llvm_unreachable("Invalid BuiltinType Kind!");
411}
412
413TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
414  while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
415    TL = PTL.getInnerLoc();
416  return TL;
417}
418
419SourceLocation TypeLoc::findNullabilityLoc() const {
420  if (auto ATL = getAs<AttributedTypeLoc>()) {
421    const Attr *A = ATL.getAttr();
422    if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) ||
423              isa<TypeNullUnspecifiedAttr>(A)))
424      return A->getLocation();
425  }
426
427  return {};
428}
429
430TypeLoc TypeLoc::findExplicitQualifierLoc() const {
431  // Qualified types.
432  if (auto qual = getAs<QualifiedTypeLoc>())
433    return qual;
434
435  TypeLoc loc = IgnoreParens();
436
437  // Attributed types.
438  if (auto attr = loc.getAs<AttributedTypeLoc>()) {
439    if (attr.isQualifier()) return attr;
440    return attr.getModifiedLoc().findExplicitQualifierLoc();
441  }
442
443  // C11 _Atomic types.
444  if (auto atomic = loc.getAs<AtomicTypeLoc>()) {
445    return atomic;
446  }
447
448  return {};
449}
450
451void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
452                                           SourceLocation Loc) {
453  setNameLoc(Loc);
454  if (!getNumProtocols()) return;
455
456  setProtocolLAngleLoc(Loc);
457  setProtocolRAngleLoc(Loc);
458  for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
459    setProtocolLoc(i, Loc);
460}
461
462void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
463                                        SourceLocation Loc) {
464  setHasBaseTypeAsWritten(true);
465  setTypeArgsLAngleLoc(Loc);
466  setTypeArgsRAngleLoc(Loc);
467  for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
468    setTypeArgTInfo(i,
469                   Context.getTrivialTypeSourceInfo(
470                     getTypePtr()->getTypeArgsAsWritten()[i], Loc));
471  }
472  setProtocolLAngleLoc(Loc);
473  setProtocolRAngleLoc(Loc);
474  for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
475    setProtocolLoc(i, Loc);
476}
477
478SourceRange AttributedTypeLoc::getLocalSourceRange() const {
479  // Note that this does *not* include the range of the attribute
480  // enclosure, e.g.:
481  //    __attribute__((foo(bar)))
482  //    ^~~~~~~~~~~~~~~        ~~
483  // or
484  //    [[foo(bar)]]
485  //    ^~        ~~
486  // That enclosure doesn't necessarily belong to a single attribute
487  // anyway.
488  return getAttr() ? getAttr()->getRange() : SourceRange();
489}
490
491void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
492                                       SourceLocation Loc) {
493  TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
494      ::initializeLocal(Context, Loc);
495  this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
496      getUnderlyingType(), Loc);
497}
498
499void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context,
500                                       SourceLocation Loc) {
501    setKWLoc(Loc);
502    setRParenLoc(Loc);
503    setLParenLoc(Loc);
504    this->setUnderlyingTInfo(
505        Context.getTrivialTypeSourceInfo(getTypePtr()->getBaseType(), Loc));
506}
507
508void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
509                                        SourceLocation Loc) {
510  setElaboratedKeywordLoc(Loc);
511  NestedNameSpecifierLocBuilder Builder;
512  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
513  setQualifierLoc(Builder.getWithLocInContext(Context));
514}
515
516void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
517                                           SourceLocation Loc) {
518  setElaboratedKeywordLoc(Loc);
519  NestedNameSpecifierLocBuilder Builder;
520  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
521  setQualifierLoc(Builder.getWithLocInContext(Context));
522  setNameLoc(Loc);
523}
524
525void
526DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
527                                                        SourceLocation Loc) {
528  setElaboratedKeywordLoc(Loc);
529  if (getTypePtr()->getQualifier()) {
530    NestedNameSpecifierLocBuilder Builder;
531    Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
532    setQualifierLoc(Builder.getWithLocInContext(Context));
533  } else {
534    setQualifierLoc(NestedNameSpecifierLoc());
535  }
536  setTemplateKeywordLoc(Loc);
537  setTemplateNameLoc(Loc);
538  setLAngleLoc(Loc);
539  setRAngleLoc(Loc);
540  TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
541                                                   getTypePtr()->getArgs(),
542                                                   getArgInfos(), Loc);
543}
544
545void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
546                                                      unsigned NumArgs,
547                                                  const TemplateArgument *Args,
548                                              TemplateArgumentLocInfo *ArgInfos,
549                                                      SourceLocation Loc) {
550  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
551    switch (Args[i].getKind()) {
552    case TemplateArgument::Null:
553      llvm_unreachable("Impossible TemplateArgument");
554
555    case TemplateArgument::Integral:
556    case TemplateArgument::Declaration:
557    case TemplateArgument::NullPtr:
558      ArgInfos[i] = TemplateArgumentLocInfo();
559      break;
560
561    case TemplateArgument::Expression:
562      ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
563      break;
564
565    case TemplateArgument::Type:
566      ArgInfos[i] = TemplateArgumentLocInfo(
567                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
568                                                           Loc));
569      break;
570
571    case TemplateArgument::Template:
572    case TemplateArgument::TemplateExpansion: {
573      NestedNameSpecifierLocBuilder Builder;
574      TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
575      if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
576        Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
577      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
578        Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
579
580      ArgInfos[i] = TemplateArgumentLocInfo(
581          Builder.getWithLocInContext(Context), Loc,
582          Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
583                                                          : Loc);
584      break;
585    }
586
587    case TemplateArgument::Pack:
588      ArgInfos[i] = TemplateArgumentLocInfo();
589      break;
590    }
591  }
592}
593
594DeclarationNameInfo AutoTypeLoc::getConceptNameInfo() const {
595  return DeclarationNameInfo(getNamedConcept()->getDeclName(),
596                             getLocalData()->ConceptNameLoc);
597}
598
599void AutoTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) {
600  setNestedNameSpecifierLoc(NestedNameSpecifierLoc());
601  setTemplateKWLoc(Loc);
602  setConceptNameLoc(Loc);
603  setFoundDecl(nullptr);
604  setRAngleLoc(Loc);
605  setLAngleLoc(Loc);
606  TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
607                                                   getTypePtr()->getArgs(),
608                                                   getArgInfos(), Loc);
609  setNameLoc(Loc);
610}
611
612
613namespace {
614
615  class GetContainedAutoTypeLocVisitor :
616    public TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc> {
617  public:
618    using TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc>::Visit;
619
620    TypeLoc VisitAutoTypeLoc(AutoTypeLoc TL) {
621      return TL;
622    }
623
624    // Only these types can contain the desired 'auto' type.
625
626    TypeLoc VisitElaboratedTypeLoc(ElaboratedTypeLoc T) {
627      return Visit(T.getNamedTypeLoc());
628    }
629
630    TypeLoc VisitQualifiedTypeLoc(QualifiedTypeLoc T) {
631      return Visit(T.getUnqualifiedLoc());
632    }
633
634    TypeLoc VisitPointerTypeLoc(PointerTypeLoc T) {
635      return Visit(T.getPointeeLoc());
636    }
637
638    TypeLoc VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) {
639      return Visit(T.getPointeeLoc());
640    }
641
642    TypeLoc VisitReferenceTypeLoc(ReferenceTypeLoc T) {
643      return Visit(T.getPointeeLoc());
644    }
645
646    TypeLoc VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) {
647      return Visit(T.getPointeeLoc());
648    }
649
650    TypeLoc VisitArrayTypeLoc(ArrayTypeLoc T) {
651      return Visit(T.getElementLoc());
652    }
653
654    TypeLoc VisitFunctionTypeLoc(FunctionTypeLoc T) {
655      return Visit(T.getReturnLoc());
656    }
657
658    TypeLoc VisitParenTypeLoc(ParenTypeLoc T) {
659      return Visit(T.getInnerLoc());
660    }
661
662    TypeLoc VisitAttributedTypeLoc(AttributedTypeLoc T) {
663      return Visit(T.getModifiedLoc());
664    }
665
666    TypeLoc VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc T) {
667      return Visit(T.getInnerLoc());
668    }
669
670    TypeLoc VisitAdjustedTypeLoc(AdjustedTypeLoc T) {
671      return Visit(T.getOriginalLoc());
672    }
673
674    TypeLoc VisitPackExpansionTypeLoc(PackExpansionTypeLoc T) {
675      return Visit(T.getPatternLoc());
676    }
677  };
678
679} // namespace
680
681AutoTypeLoc TypeLoc::getContainedAutoTypeLoc() const {
682  TypeLoc Res = GetContainedAutoTypeLocVisitor().Visit(*this);
683  if (Res.isNull())
684    return AutoTypeLoc();
685  return Res.getAs<AutoTypeLoc>();
686}
687