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