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 
31 using namespace clang;
32 
33 static const unsigned TypeLocMaxDataAlign = alignof(void *);
34 
35 //===----------------------------------------------------------------------===//
36 // TypeLoc Implementation
37 //===----------------------------------------------------------------------===//
38 
39 namespace {
40 
41 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
42 public:
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 
53 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
54   if (TL.isNull()) return SourceRange();
55   return TypeLocRanger().Visit(TL);
56 }
57 
58 namespace {
59 
60 class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
61 public:
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.
73 unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
74   if (Ty.isNull()) return 1;
75   return TypeAligner().Visit(TypeLoc(Ty, nullptr));
76 }
77 
78 namespace {
79 
80 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
81 public:
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.
93 unsigned 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 
108 namespace {
109 
110 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
111 public:
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".
124 TypeLoc 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.
131 void 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 
149 namespace {
150 
151 class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
152   TypeLoc Source;
153 
154 public:
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 
167 void 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 
191 SourceLocation TypeLoc::getBeginLoc() const {
192   TypeLoc Cur = *this;
193   TypeLoc LeftMost = Cur;
194   while (true) {
195     switch (Cur.getTypeLocClass()) {
196     case Elaborated:
197       if (Cur.getLocalSourceRange().getBegin().isValid()) {
198         LeftMost = Cur;
199         break;
200       }
201       Cur = Cur.getNextTypeLoc();
202       if (Cur.isNull())
203         break;
204       continue;
205     case FunctionProto:
206       if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
207               ->hasTrailingReturn()) {
208         LeftMost = Cur;
209         break;
210       }
211       [[fallthrough]];
212     case FunctionNoProto:
213     case ConstantArray:
214     case DependentSizedArray:
215     case IncompleteArray:
216     case VariableArray:
217       // FIXME: Currently QualifiedTypeLoc does not have a source range
218     case Qualified:
219       Cur = Cur.getNextTypeLoc();
220       continue;
221     default:
222       if (Cur.getLocalSourceRange().getBegin().isValid())
223         LeftMost = Cur;
224       Cur = Cur.getNextTypeLoc();
225       if (Cur.isNull())
226         break;
227       continue;
228     } // switch
229     break;
230   } // while
231   return LeftMost.getLocalSourceRange().getBegin();
232 }
233 
234 SourceLocation TypeLoc::getEndLoc() const {
235   TypeLoc Cur = *this;
236   TypeLoc Last;
237   while (true) {
238     switch (Cur.getTypeLocClass()) {
239     default:
240       if (!Last)
241         Last = Cur;
242       return Last.getLocalSourceRange().getEnd();
243     case Paren:
244     case ConstantArray:
245     case DependentSizedArray:
246     case IncompleteArray:
247     case VariableArray:
248     case FunctionNoProto:
249       // The innermost type with suffix syntax always determines the end of the
250       // type.
251       Last = Cur;
252       break;
253     case FunctionProto:
254       if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
255         Last = TypeLoc();
256       else
257         Last = Cur;
258       break;
259     case ObjCObjectPointer:
260       // `id` and `id<...>` have no star location.
261       if (Cur.castAs<ObjCObjectPointerTypeLoc>().getStarLoc().isInvalid())
262         break;
263       [[fallthrough]];
264     case Pointer:
265     case BlockPointer:
266     case MemberPointer:
267     case LValueReference:
268     case RValueReference:
269     case PackExpansion:
270       // Types with prefix syntax only determine the end of the type if there
271       // is no suffix type.
272       if (!Last)
273         Last = Cur;
274       break;
275     case Qualified:
276     case Elaborated:
277       break;
278     }
279     Cur = Cur.getNextTypeLoc();
280   }
281 }
282 
283 namespace {
284 
285 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
286   // Overload resolution does the real work for us.
287   static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
288   static bool isTypeSpec(TypeLoc _) { return false; }
289 
290 #define ABSTRACT_TYPELOC(CLASS, PARENT)
291 #define TYPELOC(CLASS, PARENT) \
292   bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
293     return isTypeSpec(TyLoc); \
294   }
295 #include "clang/AST/TypeLocNodes.def"
296 };
297 
298 } // namespace
299 
300 /// Determines if the given type loc corresponds to a
301 /// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
302 /// the type hierarchy, this is made somewhat complicated.
303 ///
304 /// There are a lot of types that currently use TypeSpecTypeLoc
305 /// because it's a convenient base class.  Ideally we would not accept
306 /// those here, but ideally we would have better implementations for
307 /// them.
308 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
309   if (TL.getType().hasLocalQualifiers()) return false;
310   return TSTChecker().Visit(TL);
311 }
312 
313 bool TagTypeLoc::isDefinition() const {
314   TagDecl *D = getDecl();
315   return D->isCompleteDefinition() &&
316          (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc());
317 }
318 
319 // Reimplemented to account for GNU/C++ extension
320 //     typeof unary-expression
321 // where there are no parentheses.
322 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
323   if (getRParenLoc().isValid())
324     return SourceRange(getTypeofLoc(), getRParenLoc());
325   else
326     return SourceRange(getTypeofLoc(),
327                        getUnderlyingExpr()->getSourceRange().getEnd());
328 }
329 
330 
331 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
332   if (needsExtraLocalData())
333     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
334   switch (getTypePtr()->getKind()) {
335   case BuiltinType::Void:
336     return TST_void;
337   case BuiltinType::Bool:
338     return TST_bool;
339   case BuiltinType::Char_U:
340   case BuiltinType::Char_S:
341     return TST_char;
342   case BuiltinType::Char8:
343     return TST_char8;
344   case BuiltinType::Char16:
345     return TST_char16;
346   case BuiltinType::Char32:
347     return TST_char32;
348   case BuiltinType::WChar_S:
349   case BuiltinType::WChar_U:
350     return TST_wchar;
351   case BuiltinType::UChar:
352   case BuiltinType::UShort:
353   case BuiltinType::UInt:
354   case BuiltinType::ULong:
355   case BuiltinType::ULongLong:
356   case BuiltinType::UInt128:
357   case BuiltinType::SChar:
358   case BuiltinType::Short:
359   case BuiltinType::Int:
360   case BuiltinType::Long:
361   case BuiltinType::LongLong:
362   case BuiltinType::Int128:
363   case BuiltinType::Half:
364   case BuiltinType::Float:
365   case BuiltinType::Double:
366   case BuiltinType::LongDouble:
367   case BuiltinType::Float16:
368   case BuiltinType::Float128:
369   case BuiltinType::Ibm128:
370   case BuiltinType::ShortAccum:
371   case BuiltinType::Accum:
372   case BuiltinType::LongAccum:
373   case BuiltinType::UShortAccum:
374   case BuiltinType::UAccum:
375   case BuiltinType::ULongAccum:
376   case BuiltinType::ShortFract:
377   case BuiltinType::Fract:
378   case BuiltinType::LongFract:
379   case BuiltinType::UShortFract:
380   case BuiltinType::UFract:
381   case BuiltinType::ULongFract:
382   case BuiltinType::SatShortAccum:
383   case BuiltinType::SatAccum:
384   case BuiltinType::SatLongAccum:
385   case BuiltinType::SatUShortAccum:
386   case BuiltinType::SatUAccum:
387   case BuiltinType::SatULongAccum:
388   case BuiltinType::SatShortFract:
389   case BuiltinType::SatFract:
390   case BuiltinType::SatLongFract:
391   case BuiltinType::SatUShortFract:
392   case BuiltinType::SatUFract:
393   case BuiltinType::SatULongFract:
394   case BuiltinType::BFloat16:
395     llvm_unreachable("Builtin type needs extra local data!");
396     // Fall through, if the impossible happens.
397 
398   case BuiltinType::NullPtr:
399   case BuiltinType::Overload:
400   case BuiltinType::Dependent:
401   case BuiltinType::BoundMember:
402   case BuiltinType::UnknownAny:
403   case BuiltinType::ARCUnbridgedCast:
404   case BuiltinType::PseudoObject:
405   case BuiltinType::ObjCId:
406   case BuiltinType::ObjCClass:
407   case BuiltinType::ObjCSel:
408 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
409   case BuiltinType::Id:
410 #include "clang/Basic/OpenCLImageTypes.def"
411 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
412   case BuiltinType::Id:
413 #include "clang/Basic/OpenCLExtensionTypes.def"
414   case BuiltinType::OCLSampler:
415   case BuiltinType::OCLEvent:
416   case BuiltinType::OCLClkEvent:
417   case BuiltinType::OCLQueue:
418   case BuiltinType::OCLReserveID:
419 #define SVE_TYPE(Name, Id, SingletonId) \
420   case BuiltinType::Id:
421 #include "clang/Basic/AArch64SVEACLETypes.def"
422 #define PPC_VECTOR_TYPE(Name, Id, Size) \
423   case BuiltinType::Id:
424 #include "clang/Basic/PPCTypes.def"
425 #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
426 #include "clang/Basic/RISCVVTypes.def"
427 #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
428 #include "clang/Basic/WebAssemblyReferenceTypes.def"
429   case BuiltinType::BuiltinFn:
430   case BuiltinType::IncompleteMatrixIdx:
431   case BuiltinType::OMPArraySection:
432   case BuiltinType::OMPArrayShaping:
433   case BuiltinType::OMPIterator:
434     return TST_unspecified;
435   }
436 
437   llvm_unreachable("Invalid BuiltinType Kind!");
438 }
439 
440 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
441   while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
442     TL = PTL.getInnerLoc();
443   return TL;
444 }
445 
446 SourceLocation TypeLoc::findNullabilityLoc() const {
447   if (auto ATL = getAs<AttributedTypeLoc>()) {
448     const Attr *A = ATL.getAttr();
449     if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) ||
450               isa<TypeNullUnspecifiedAttr>(A)))
451       return A->getLocation();
452   }
453 
454   return {};
455 }
456 
457 TypeLoc TypeLoc::findExplicitQualifierLoc() const {
458   // Qualified types.
459   if (auto qual = getAs<QualifiedTypeLoc>())
460     return qual;
461 
462   TypeLoc loc = IgnoreParens();
463 
464   // Attributed types.
465   if (auto attr = loc.getAs<AttributedTypeLoc>()) {
466     if (attr.isQualifier()) return attr;
467     return attr.getModifiedLoc().findExplicitQualifierLoc();
468   }
469 
470   // C11 _Atomic types.
471   if (auto atomic = loc.getAs<AtomicTypeLoc>()) {
472     return atomic;
473   }
474 
475   return {};
476 }
477 
478 void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
479                                            SourceLocation Loc) {
480   setNameLoc(Loc);
481   if (!getNumProtocols()) return;
482 
483   setProtocolLAngleLoc(Loc);
484   setProtocolRAngleLoc(Loc);
485   for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
486     setProtocolLoc(i, Loc);
487 }
488 
489 void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
490                                         SourceLocation Loc) {
491   setHasBaseTypeAsWritten(true);
492   setTypeArgsLAngleLoc(Loc);
493   setTypeArgsRAngleLoc(Loc);
494   for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
495     setTypeArgTInfo(i,
496                    Context.getTrivialTypeSourceInfo(
497                      getTypePtr()->getTypeArgsAsWritten()[i], Loc));
498   }
499   setProtocolLAngleLoc(Loc);
500   setProtocolRAngleLoc(Loc);
501   for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
502     setProtocolLoc(i, Loc);
503 }
504 
505 SourceRange AttributedTypeLoc::getLocalSourceRange() const {
506   // Note that this does *not* include the range of the attribute
507   // enclosure, e.g.:
508   //    __attribute__((foo(bar)))
509   //    ^~~~~~~~~~~~~~~        ~~
510   // or
511   //    [[foo(bar)]]
512   //    ^~        ~~
513   // That enclosure doesn't necessarily belong to a single attribute
514   // anyway.
515   return getAttr() ? getAttr()->getRange() : SourceRange();
516 }
517 
518 SourceRange BTFTagAttributedTypeLoc::getLocalSourceRange() const {
519   return getAttr() ? getAttr()->getRange() : SourceRange();
520 }
521 
522 void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
523                                        SourceLocation Loc) {
524   TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
525       ::initializeLocal(Context, Loc);
526   this->getLocalData()->UnmodifiedTInfo =
527       Context.getTrivialTypeSourceInfo(getUnmodifiedType(), Loc);
528 }
529 
530 void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context,
531                                        SourceLocation Loc) {
532     setKWLoc(Loc);
533     setRParenLoc(Loc);
534     setLParenLoc(Loc);
535     this->setUnderlyingTInfo(
536         Context.getTrivialTypeSourceInfo(getTypePtr()->getBaseType(), Loc));
537 }
538 
539 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
540                                         SourceLocation Loc) {
541   if (isEmpty())
542     return;
543   setElaboratedKeywordLoc(Loc);
544   NestedNameSpecifierLocBuilder Builder;
545   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
546   setQualifierLoc(Builder.getWithLocInContext(Context));
547 }
548 
549 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
550                                            SourceLocation Loc) {
551   setElaboratedKeywordLoc(Loc);
552   NestedNameSpecifierLocBuilder Builder;
553   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
554   setQualifierLoc(Builder.getWithLocInContext(Context));
555   setNameLoc(Loc);
556 }
557 
558 void
559 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
560                                                         SourceLocation Loc) {
561   setElaboratedKeywordLoc(Loc);
562   if (getTypePtr()->getQualifier()) {
563     NestedNameSpecifierLocBuilder Builder;
564     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
565     setQualifierLoc(Builder.getWithLocInContext(Context));
566   } else {
567     setQualifierLoc(NestedNameSpecifierLoc());
568   }
569   setTemplateKeywordLoc(Loc);
570   setTemplateNameLoc(Loc);
571   setLAngleLoc(Loc);
572   setRAngleLoc(Loc);
573   TemplateSpecializationTypeLoc::initializeArgLocs(
574       Context, getTypePtr()->template_arguments(), getArgInfos(), Loc);
575 }
576 
577 void TemplateSpecializationTypeLoc::initializeArgLocs(
578     ASTContext &Context, ArrayRef<TemplateArgument> Args,
579     TemplateArgumentLocInfo *ArgInfos, SourceLocation Loc) {
580   for (unsigned i = 0, e = Args.size(); i != e; ++i) {
581     switch (Args[i].getKind()) {
582     case TemplateArgument::Null:
583       llvm_unreachable("Impossible TemplateArgument");
584 
585     case TemplateArgument::Integral:
586     case TemplateArgument::Declaration:
587     case TemplateArgument::NullPtr:
588       ArgInfos[i] = TemplateArgumentLocInfo();
589       break;
590 
591     case TemplateArgument::Expression:
592       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
593       break;
594 
595     case TemplateArgument::Type:
596       ArgInfos[i] = TemplateArgumentLocInfo(
597                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
598                                                            Loc));
599       break;
600 
601     case TemplateArgument::Template:
602     case TemplateArgument::TemplateExpansion: {
603       NestedNameSpecifierLocBuilder Builder;
604       TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
605       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
606         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
607       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
608         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
609 
610       ArgInfos[i] = TemplateArgumentLocInfo(
611           Context, Builder.getWithLocInContext(Context), Loc,
612           Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
613                                                           : Loc);
614       break;
615     }
616 
617     case TemplateArgument::Pack:
618       ArgInfos[i] = TemplateArgumentLocInfo();
619       break;
620     }
621   }
622 }
623 
624 DeclarationNameInfo AutoTypeLoc::getConceptNameInfo() const {
625   return DeclarationNameInfo(getNamedConcept()->getDeclName(),
626                              getLocalData()->ConceptNameLoc);
627 }
628 
629 void AutoTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) {
630   setNestedNameSpecifierLoc(NestedNameSpecifierLoc());
631   setTemplateKWLoc(Loc);
632   setConceptNameLoc(Loc);
633   setFoundDecl(nullptr);
634   setRAngleLoc(Loc);
635   setLAngleLoc(Loc);
636   setRParenLoc(Loc);
637   TemplateSpecializationTypeLoc::initializeArgLocs(
638       Context, getTypePtr()->getTypeConstraintArguments(), getArgInfos(), Loc);
639   setNameLoc(Loc);
640 }
641 
642 
643 namespace {
644 
645   class GetContainedAutoTypeLocVisitor :
646     public TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc> {
647   public:
648     using TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc>::Visit;
649 
650     TypeLoc VisitAutoTypeLoc(AutoTypeLoc TL) {
651       return TL;
652     }
653 
654     // Only these types can contain the desired 'auto' type.
655 
656     TypeLoc VisitElaboratedTypeLoc(ElaboratedTypeLoc T) {
657       return Visit(T.getNamedTypeLoc());
658     }
659 
660     TypeLoc VisitQualifiedTypeLoc(QualifiedTypeLoc T) {
661       return Visit(T.getUnqualifiedLoc());
662     }
663 
664     TypeLoc VisitPointerTypeLoc(PointerTypeLoc T) {
665       return Visit(T.getPointeeLoc());
666     }
667 
668     TypeLoc VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) {
669       return Visit(T.getPointeeLoc());
670     }
671 
672     TypeLoc VisitReferenceTypeLoc(ReferenceTypeLoc T) {
673       return Visit(T.getPointeeLoc());
674     }
675 
676     TypeLoc VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) {
677       return Visit(T.getPointeeLoc());
678     }
679 
680     TypeLoc VisitArrayTypeLoc(ArrayTypeLoc T) {
681       return Visit(T.getElementLoc());
682     }
683 
684     TypeLoc VisitFunctionTypeLoc(FunctionTypeLoc T) {
685       return Visit(T.getReturnLoc());
686     }
687 
688     TypeLoc VisitParenTypeLoc(ParenTypeLoc T) {
689       return Visit(T.getInnerLoc());
690     }
691 
692     TypeLoc VisitAttributedTypeLoc(AttributedTypeLoc T) {
693       return Visit(T.getModifiedLoc());
694     }
695 
696     TypeLoc VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc T) {
697       return Visit(T.getWrappedLoc());
698     }
699 
700     TypeLoc VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc T) {
701       return Visit(T.getInnerLoc());
702     }
703 
704     TypeLoc VisitAdjustedTypeLoc(AdjustedTypeLoc T) {
705       return Visit(T.getOriginalLoc());
706     }
707 
708     TypeLoc VisitPackExpansionTypeLoc(PackExpansionTypeLoc T) {
709       return Visit(T.getPatternLoc());
710     }
711   };
712 
713 } // namespace
714 
715 AutoTypeLoc TypeLoc::getContainedAutoTypeLoc() const {
716   TypeLoc Res = GetContainedAutoTypeLocVisitor().Visit(*this);
717   if (Res.isNull())
718     return AutoTypeLoc();
719   return Res.getAs<AutoTypeLoc>();
720 }
721