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/ASTContext.h" 15 #include "clang/AST/Expr.h" 16 #include "clang/AST/NestedNameSpecifier.h" 17 #include "clang/AST/TemplateBase.h" 18 #include "clang/AST/TemplateName.h" 19 #include "clang/AST/TypeLocVisitor.h" 20 #include "clang/Basic/SourceLocation.h" 21 #include "clang/Basic/Specifiers.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include "llvm/Support/MathExtras.h" 24 #include <algorithm> 25 #include <cassert> 26 #include <cstdint> 27 #include <cstring> 28 29 using namespace clang; 30 31 static const unsigned TypeLocMaxDataAlign = alignof(void *); 32 33 //===----------------------------------------------------------------------===// 34 // TypeLoc Implementation 35 //===----------------------------------------------------------------------===// 36 37 namespace { 38 39 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { 40 public: 41 #define ABSTRACT_TYPELOC(CLASS, PARENT) 42 #define TYPELOC(CLASS, PARENT) \ 43 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 44 return TyLoc.getLocalSourceRange(); \ 45 } 46 #include "clang/AST/TypeLocNodes.def" 47 }; 48 49 } // namespace 50 51 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { 52 if (TL.isNull()) return SourceRange(); 53 return TypeLocRanger().Visit(TL); 54 } 55 56 namespace { 57 58 class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> { 59 public: 60 #define ABSTRACT_TYPELOC(CLASS, PARENT) 61 #define TYPELOC(CLASS, PARENT) \ 62 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 63 return TyLoc.getLocalDataAlignment(); \ 64 } 65 #include "clang/AST/TypeLocNodes.def" 66 }; 67 68 } // namespace 69 70 /// Returns the alignment of the type source info data block. 71 unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) { 72 if (Ty.isNull()) return 1; 73 return TypeAligner().Visit(TypeLoc(Ty, nullptr)); 74 } 75 76 namespace { 77 78 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { 79 public: 80 #define ABSTRACT_TYPELOC(CLASS, PARENT) 81 #define TYPELOC(CLASS, PARENT) \ 82 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 83 return TyLoc.getLocalDataSize(); \ 84 } 85 #include "clang/AST/TypeLocNodes.def" 86 }; 87 88 } // namespace 89 90 /// Returns the size of the type source info data block. 91 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { 92 unsigned Total = 0; 93 TypeLoc TyLoc(Ty, nullptr); 94 unsigned MaxAlign = 1; 95 while (!TyLoc.isNull()) { 96 unsigned Align = getLocalAlignmentForType(TyLoc.getType()); 97 MaxAlign = std::max(Align, MaxAlign); 98 Total = llvm::alignTo(Total, Align); 99 Total += TypeSizer().Visit(TyLoc); 100 TyLoc = TyLoc.getNextTypeLoc(); 101 } 102 Total = llvm::alignTo(Total, MaxAlign); 103 return Total; 104 } 105 106 namespace { 107 108 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { 109 public: 110 #define ABSTRACT_TYPELOC(CLASS, PARENT) 111 #define TYPELOC(CLASS, PARENT) \ 112 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 113 return TyLoc.getNextTypeLoc(); \ 114 } 115 #include "clang/AST/TypeLocNodes.def" 116 }; 117 118 } // namespace 119 120 /// Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the 121 /// TypeLoc is a PointerLoc and next TypeLoc is for "int". 122 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) { 123 return NextLoc().Visit(TL); 124 } 125 126 /// Initializes a type location, and all of its children 127 /// recursively, as if the entire tree had been written in the 128 /// given location. 129 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 130 SourceLocation Loc) { 131 while (true) { 132 switch (TL.getTypeLocClass()) { 133 #define ABSTRACT_TYPELOC(CLASS, PARENT) 134 #define TYPELOC(CLASS, PARENT) \ 135 case CLASS: { \ 136 CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \ 137 TLCasted.initializeLocal(Context, Loc); \ 138 TL = TLCasted.getNextTypeLoc(); \ 139 if (!TL) return; \ 140 continue; \ 141 } 142 #include "clang/AST/TypeLocNodes.def" 143 } 144 } 145 } 146 147 namespace { 148 149 class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> { 150 TypeLoc Source; 151 152 public: 153 TypeLocCopier(TypeLoc source) : Source(source) {} 154 155 #define ABSTRACT_TYPELOC(CLASS, PARENT) 156 #define TYPELOC(CLASS, PARENT) \ 157 void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \ 158 dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \ 159 } 160 #include "clang/AST/TypeLocNodes.def" 161 }; 162 163 } // namespace 164 165 void TypeLoc::copy(TypeLoc other) { 166 assert(getFullDataSize() == other.getFullDataSize()); 167 168 // If both data pointers are aligned to the maximum alignment, we 169 // can memcpy because getFullDataSize() accurately reflects the 170 // layout of the data. 171 if (reinterpret_cast<uintptr_t>(Data) == 172 llvm::alignTo(reinterpret_cast<uintptr_t>(Data), 173 TypeLocMaxDataAlign) && 174 reinterpret_cast<uintptr_t>(other.Data) == 175 llvm::alignTo(reinterpret_cast<uintptr_t>(other.Data), 176 TypeLocMaxDataAlign)) { 177 memcpy(Data, other.Data, getFullDataSize()); 178 return; 179 } 180 181 // Copy each of the pieces. 182 TypeLoc TL(getType(), Data); 183 do { 184 TypeLocCopier(other).Visit(TL); 185 other = other.getNextTypeLoc(); 186 } while ((TL = TL.getNextTypeLoc())); 187 } 188 189 SourceLocation TypeLoc::getBeginLoc() const { 190 TypeLoc Cur = *this; 191 TypeLoc LeftMost = Cur; 192 while (true) { 193 switch (Cur.getTypeLocClass()) { 194 case Elaborated: 195 LeftMost = Cur; 196 break; 197 case FunctionProto: 198 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr() 199 ->hasTrailingReturn()) { 200 LeftMost = Cur; 201 break; 202 } 203 LLVM_FALLTHROUGH; 204 case FunctionNoProto: 205 case ConstantArray: 206 case DependentSizedArray: 207 case IncompleteArray: 208 case VariableArray: 209 // FIXME: Currently QualifiedTypeLoc does not have a source range 210 case Qualified: 211 Cur = Cur.getNextTypeLoc(); 212 continue; 213 default: 214 if (Cur.getLocalSourceRange().getBegin().isValid()) 215 LeftMost = Cur; 216 Cur = Cur.getNextTypeLoc(); 217 if (Cur.isNull()) 218 break; 219 continue; 220 } // switch 221 break; 222 } // while 223 return LeftMost.getLocalSourceRange().getBegin(); 224 } 225 226 SourceLocation TypeLoc::getEndLoc() const { 227 TypeLoc Cur = *this; 228 TypeLoc Last; 229 while (true) { 230 switch (Cur.getTypeLocClass()) { 231 default: 232 if (!Last) 233 Last = Cur; 234 return Last.getLocalSourceRange().getEnd(); 235 case Paren: 236 case ConstantArray: 237 case DependentSizedArray: 238 case IncompleteArray: 239 case VariableArray: 240 case FunctionNoProto: 241 Last = Cur; 242 break; 243 case FunctionProto: 244 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn()) 245 Last = TypeLoc(); 246 else 247 Last = Cur; 248 break; 249 case Pointer: 250 case BlockPointer: 251 case MemberPointer: 252 case LValueReference: 253 case RValueReference: 254 case PackExpansion: 255 if (!Last) 256 Last = Cur; 257 break; 258 case Qualified: 259 case Elaborated: 260 break; 261 } 262 Cur = Cur.getNextTypeLoc(); 263 } 264 } 265 266 namespace { 267 268 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { 269 // Overload resolution does the real work for us. 270 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } 271 static bool isTypeSpec(TypeLoc _) { return false; } 272 273 #define ABSTRACT_TYPELOC(CLASS, PARENT) 274 #define TYPELOC(CLASS, PARENT) \ 275 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 276 return isTypeSpec(TyLoc); \ 277 } 278 #include "clang/AST/TypeLocNodes.def" 279 }; 280 281 } // namespace 282 283 /// Determines if the given type loc corresponds to a 284 /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in 285 /// the type hierarchy, this is made somewhat complicated. 286 /// 287 /// There are a lot of types that currently use TypeSpecTypeLoc 288 /// because it's a convenient base class. Ideally we would not accept 289 /// those here, but ideally we would have better implementations for 290 /// them. 291 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) { 292 if (TL.getType().hasLocalQualifiers()) return false; 293 return TSTChecker().Visit(TL); 294 } 295 296 // Reimplemented to account for GNU/C++ extension 297 // typeof unary-expression 298 // where there are no parentheses. 299 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { 300 if (getRParenLoc().isValid()) 301 return SourceRange(getTypeofLoc(), getRParenLoc()); 302 else 303 return SourceRange(getTypeofLoc(), 304 getUnderlyingExpr()->getSourceRange().getEnd()); 305 } 306 307 308 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { 309 if (needsExtraLocalData()) 310 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); 311 switch (getTypePtr()->getKind()) { 312 case BuiltinType::Void: 313 return TST_void; 314 case BuiltinType::Bool: 315 return TST_bool; 316 case BuiltinType::Char_U: 317 case BuiltinType::Char_S: 318 return TST_char; 319 case BuiltinType::Char8: 320 return TST_char8; 321 case BuiltinType::Char16: 322 return TST_char16; 323 case BuiltinType::Char32: 324 return TST_char32; 325 case BuiltinType::WChar_S: 326 case BuiltinType::WChar_U: 327 return TST_wchar; 328 case BuiltinType::UChar: 329 case BuiltinType::UShort: 330 case BuiltinType::UInt: 331 case BuiltinType::ULong: 332 case BuiltinType::ULongLong: 333 case BuiltinType::UInt128: 334 case BuiltinType::SChar: 335 case BuiltinType::Short: 336 case BuiltinType::Int: 337 case BuiltinType::Long: 338 case BuiltinType::LongLong: 339 case BuiltinType::Int128: 340 case BuiltinType::Half: 341 case BuiltinType::Float: 342 case BuiltinType::Double: 343 case BuiltinType::LongDouble: 344 case BuiltinType::Float16: 345 case BuiltinType::Float128: 346 case BuiltinType::ShortAccum: 347 case BuiltinType::Accum: 348 case BuiltinType::LongAccum: 349 case BuiltinType::UShortAccum: 350 case BuiltinType::UAccum: 351 case BuiltinType::ULongAccum: 352 case BuiltinType::ShortFract: 353 case BuiltinType::Fract: 354 case BuiltinType::LongFract: 355 case BuiltinType::UShortFract: 356 case BuiltinType::UFract: 357 case BuiltinType::ULongFract: 358 case BuiltinType::SatShortAccum: 359 case BuiltinType::SatAccum: 360 case BuiltinType::SatLongAccum: 361 case BuiltinType::SatUShortAccum: 362 case BuiltinType::SatUAccum: 363 case BuiltinType::SatULongAccum: 364 case BuiltinType::SatShortFract: 365 case BuiltinType::SatFract: 366 case BuiltinType::SatLongFract: 367 case BuiltinType::SatUShortFract: 368 case BuiltinType::SatUFract: 369 case BuiltinType::SatULongFract: 370 llvm_unreachable("Builtin type needs extra local data!"); 371 // Fall through, if the impossible happens. 372 373 case BuiltinType::NullPtr: 374 case BuiltinType::Overload: 375 case BuiltinType::Dependent: 376 case BuiltinType::BoundMember: 377 case BuiltinType::UnknownAny: 378 case BuiltinType::ARCUnbridgedCast: 379 case BuiltinType::PseudoObject: 380 case BuiltinType::ObjCId: 381 case BuiltinType::ObjCClass: 382 case BuiltinType::ObjCSel: 383 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ 384 case BuiltinType::Id: 385 #include "clang/Basic/OpenCLImageTypes.def" 386 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ 387 case BuiltinType::Id: 388 #include "clang/Basic/OpenCLExtensionTypes.def" 389 case BuiltinType::OCLSampler: 390 case BuiltinType::OCLEvent: 391 case BuiltinType::OCLClkEvent: 392 case BuiltinType::OCLQueue: 393 case BuiltinType::OCLReserveID: 394 #define SVE_TYPE(Name, Id, SingletonId) \ 395 case BuiltinType::Id: 396 #include "clang/Basic/AArch64SVEACLETypes.def" 397 case BuiltinType::BuiltinFn: 398 case BuiltinType::OMPArraySection: 399 return TST_unspecified; 400 } 401 402 llvm_unreachable("Invalid BuiltinType Kind!"); 403 } 404 405 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 406 while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>()) 407 TL = PTL.getInnerLoc(); 408 return TL; 409 } 410 411 SourceLocation TypeLoc::findNullabilityLoc() const { 412 if (auto ATL = getAs<AttributedTypeLoc>()) { 413 const Attr *A = ATL.getAttr(); 414 if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) || 415 isa<TypeNullUnspecifiedAttr>(A))) 416 return A->getLocation(); 417 } 418 419 return {}; 420 } 421 422 TypeLoc TypeLoc::findExplicitQualifierLoc() const { 423 // Qualified types. 424 if (auto qual = getAs<QualifiedTypeLoc>()) 425 return qual; 426 427 TypeLoc loc = IgnoreParens(); 428 429 // Attributed types. 430 if (auto attr = loc.getAs<AttributedTypeLoc>()) { 431 if (attr.isQualifier()) return attr; 432 return attr.getModifiedLoc().findExplicitQualifierLoc(); 433 } 434 435 // C11 _Atomic types. 436 if (auto atomic = loc.getAs<AtomicTypeLoc>()) { 437 return atomic; 438 } 439 440 return {}; 441 } 442 443 void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, 444 SourceLocation Loc) { 445 setNameLoc(Loc); 446 if (!getNumProtocols()) return; 447 448 setProtocolLAngleLoc(Loc); 449 setProtocolRAngleLoc(Loc); 450 for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) 451 setProtocolLoc(i, Loc); 452 } 453 454 void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, 455 SourceLocation Loc) { 456 setHasBaseTypeAsWritten(true); 457 setTypeArgsLAngleLoc(Loc); 458 setTypeArgsRAngleLoc(Loc); 459 for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) { 460 setTypeArgTInfo(i, 461 Context.getTrivialTypeSourceInfo( 462 getTypePtr()->getTypeArgsAsWritten()[i], Loc)); 463 } 464 setProtocolLAngleLoc(Loc); 465 setProtocolRAngleLoc(Loc); 466 for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) 467 setProtocolLoc(i, Loc); 468 } 469 470 void TypeOfTypeLoc::initializeLocal(ASTContext &Context, 471 SourceLocation Loc) { 472 TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> 473 ::initializeLocal(Context, Loc); 474 this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo( 475 getUnderlyingType(), Loc); 476 } 477 478 void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context, 479 SourceLocation Loc) { 480 setKWLoc(Loc); 481 setRParenLoc(Loc); 482 setLParenLoc(Loc); 483 this->setUnderlyingTInfo( 484 Context.getTrivialTypeSourceInfo(getTypePtr()->getBaseType(), Loc)); 485 } 486 487 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 488 SourceLocation Loc) { 489 setElaboratedKeywordLoc(Loc); 490 NestedNameSpecifierLocBuilder Builder; 491 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 492 setQualifierLoc(Builder.getWithLocInContext(Context)); 493 } 494 495 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 496 SourceLocation Loc) { 497 setElaboratedKeywordLoc(Loc); 498 NestedNameSpecifierLocBuilder Builder; 499 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 500 setQualifierLoc(Builder.getWithLocInContext(Context)); 501 setNameLoc(Loc); 502 } 503 504 void 505 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 506 SourceLocation Loc) { 507 setElaboratedKeywordLoc(Loc); 508 if (getTypePtr()->getQualifier()) { 509 NestedNameSpecifierLocBuilder Builder; 510 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 511 setQualifierLoc(Builder.getWithLocInContext(Context)); 512 } else { 513 setQualifierLoc(NestedNameSpecifierLoc()); 514 } 515 setTemplateKeywordLoc(Loc); 516 setTemplateNameLoc(Loc); 517 setLAngleLoc(Loc); 518 setRAngleLoc(Loc); 519 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), 520 getTypePtr()->getArgs(), 521 getArgInfos(), Loc); 522 } 523 524 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 525 unsigned NumArgs, 526 const TemplateArgument *Args, 527 TemplateArgumentLocInfo *ArgInfos, 528 SourceLocation Loc) { 529 for (unsigned i = 0, e = NumArgs; i != e; ++i) { 530 switch (Args[i].getKind()) { 531 case TemplateArgument::Null: 532 llvm_unreachable("Impossible TemplateArgument"); 533 534 case TemplateArgument::Integral: 535 case TemplateArgument::Declaration: 536 case TemplateArgument::NullPtr: 537 ArgInfos[i] = TemplateArgumentLocInfo(); 538 break; 539 540 case TemplateArgument::Expression: 541 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); 542 break; 543 544 case TemplateArgument::Type: 545 ArgInfos[i] = TemplateArgumentLocInfo( 546 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 547 Loc)); 548 break; 549 550 case TemplateArgument::Template: 551 case TemplateArgument::TemplateExpansion: { 552 NestedNameSpecifierLocBuilder Builder; 553 TemplateName Template = Args[i].getAsTemplateOrTemplatePattern(); 554 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) 555 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); 556 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) 557 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); 558 559 ArgInfos[i] = TemplateArgumentLocInfo( 560 Builder.getWithLocInContext(Context), Loc, 561 Args[i].getKind() == TemplateArgument::Template ? SourceLocation() 562 : Loc); 563 break; 564 } 565 566 case TemplateArgument::Pack: 567 ArgInfos[i] = TemplateArgumentLocInfo(); 568 break; 569 } 570 } 571 } 572