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