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