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