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