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