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