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 22//===----------------------------------------------------------------------===// 23// TypeLoc Implementation 24//===----------------------------------------------------------------------===// 25 26namespace { 27 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { 28 public: 29#define ABSTRACT_TYPELOC(CLASS, PARENT) 30#define TYPELOC(CLASS, PARENT) \ 31 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 32 return TyLoc.getLocalSourceRange(); \ 33 } 34#include "clang/AST/TypeLocNodes.def" 35 }; 36} 37 38SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { 39 if (TL.isNull()) return SourceRange(); 40 return TypeLocRanger().Visit(TL); 41} 42 43namespace { 44 class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> { 45 public: 46#define ABSTRACT_TYPELOC(CLASS, PARENT) 47#define TYPELOC(CLASS, PARENT) \ 48 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 49 return TyLoc.getLocalDataAlignment(); \ 50 } 51#include "clang/AST/TypeLocNodes.def" 52 }; 53} 54 55/// \brief Returns the alignment of the type source info data block. 56unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) { 57 if (Ty.isNull()) return 1; 58 return TypeAligner().Visit(TypeLoc(Ty, 0)); 59} 60 61namespace { 62 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { 63 public: 64#define ABSTRACT_TYPELOC(CLASS, PARENT) 65#define TYPELOC(CLASS, PARENT) \ 66 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 67 return TyLoc.getLocalDataSize(); \ 68 } 69#include "clang/AST/TypeLocNodes.def" 70 }; 71} 72 73/// \brief Returns the size of the type source info data block. 74unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { 75 unsigned Total = 0; 76 TypeLoc TyLoc(Ty, 0); 77 unsigned MaxAlign = 1; 78 while (!TyLoc.isNull()) { 79 unsigned Align = getLocalAlignmentForType(TyLoc.getType()); 80 MaxAlign = std::max(Align, MaxAlign); 81 Total = llvm::RoundUpToAlignment(Total, Align); 82 Total += TypeSizer().Visit(TyLoc); 83 TyLoc = TyLoc.getNextTypeLoc(); 84 } 85 Total = llvm::RoundUpToAlignment(Total, MaxAlign); 86 return Total; 87} 88 89namespace { 90 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { 91 public: 92#define ABSTRACT_TYPELOC(CLASS, PARENT) 93#define TYPELOC(CLASS, PARENT) \ 94 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 95 return TyLoc.getNextTypeLoc(); \ 96 } 97#include "clang/AST/TypeLocNodes.def" 98 }; 99} 100 101/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the 102/// TypeLoc is a PointerLoc and next TypeLoc is for "int". 103TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) { 104 return NextLoc().Visit(TL); 105} 106 107/// \brief Initializes a type location, and all of its children 108/// recursively, as if the entire tree had been written in the 109/// given location. 110void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 111 SourceLocation Loc) { 112 while (true) { 113 switch (TL.getTypeLocClass()) { 114#define ABSTRACT_TYPELOC(CLASS, PARENT) 115#define TYPELOC(CLASS, PARENT) \ 116 case CLASS: { \ 117 CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \ 118 TLCasted.initializeLocal(Context, Loc); \ 119 TL = TLCasted.getNextTypeLoc(); \ 120 if (!TL) return; \ 121 continue; \ 122 } 123#include "clang/AST/TypeLocNodes.def" 124 } 125 } 126} 127 128SourceLocation TypeLoc::getBeginLoc() const { 129 TypeLoc Cur = *this; 130 TypeLoc LeftMost = Cur; 131 while (true) { 132 switch (Cur.getTypeLocClass()) { 133 case Elaborated: 134 LeftMost = Cur; 135 break; 136 case FunctionProto: 137 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr() 138 ->hasTrailingReturn()) { 139 LeftMost = Cur; 140 break; 141 } 142 /* Fall through */ 143 case FunctionNoProto: 144 case ConstantArray: 145 case DependentSizedArray: 146 case IncompleteArray: 147 case VariableArray: 148 // FIXME: Currently QualifiedTypeLoc does not have a source range 149 case Qualified: 150 Cur = Cur.getNextTypeLoc(); 151 continue; 152 default: 153 if (!Cur.getLocalSourceRange().getBegin().isInvalid()) 154 LeftMost = Cur; 155 Cur = Cur.getNextTypeLoc(); 156 if (Cur.isNull()) 157 break; 158 continue; 159 } // switch 160 break; 161 } // while 162 return LeftMost.getLocalSourceRange().getBegin(); 163} 164 165SourceLocation TypeLoc::getEndLoc() const { 166 TypeLoc Cur = *this; 167 TypeLoc Last; 168 while (true) { 169 switch (Cur.getTypeLocClass()) { 170 default: 171 if (!Last) 172 Last = Cur; 173 return Last.getLocalSourceRange().getEnd(); 174 case Paren: 175 case ConstantArray: 176 case DependentSizedArray: 177 case IncompleteArray: 178 case VariableArray: 179 case FunctionNoProto: 180 Last = Cur; 181 break; 182 case FunctionProto: 183 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn()) 184 Last = TypeLoc(); 185 else 186 Last = Cur; 187 break; 188 case Pointer: 189 case BlockPointer: 190 case MemberPointer: 191 case LValueReference: 192 case RValueReference: 193 case PackExpansion: 194 if (!Last) 195 Last = Cur; 196 break; 197 case Qualified: 198 case Elaborated: 199 break; 200 } 201 Cur = Cur.getNextTypeLoc(); 202 } 203} 204 205 206namespace { 207 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { 208 // Overload resolution does the real work for us. 209 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } 210 static bool isTypeSpec(TypeLoc _) { return false; } 211 212#define ABSTRACT_TYPELOC(CLASS, PARENT) 213#define TYPELOC(CLASS, PARENT) \ 214 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 215 return isTypeSpec(TyLoc); \ 216 } 217#include "clang/AST/TypeLocNodes.def" 218 }; 219} 220 221 222/// \brief Determines if the given type loc corresponds to a 223/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in 224/// the type hierarchy, this is made somewhat complicated. 225/// 226/// There are a lot of types that currently use TypeSpecTypeLoc 227/// because it's a convenient base class. Ideally we would not accept 228/// those here, but ideally we would have better implementations for 229/// them. 230bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) { 231 if (TL.getType().hasLocalQualifiers()) return false; 232 return TSTChecker().Visit(TL); 233} 234 235// Reimplemented to account for GNU/C++ extension 236// typeof unary-expression 237// where there are no parentheses. 238SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { 239 if (getRParenLoc().isValid()) 240 return SourceRange(getTypeofLoc(), getRParenLoc()); 241 else 242 return SourceRange(getTypeofLoc(), 243 getUnderlyingExpr()->getSourceRange().getEnd()); 244} 245 246 247TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { 248 if (needsExtraLocalData()) 249 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); 250 switch (getTypePtr()->getKind()) { 251 case BuiltinType::Void: 252 return TST_void; 253 case BuiltinType::Bool: 254 return TST_bool; 255 case BuiltinType::Char_U: 256 case BuiltinType::Char_S: 257 return TST_char; 258 case BuiltinType::Char16: 259 return TST_char16; 260 case BuiltinType::Char32: 261 return TST_char32; 262 case BuiltinType::WChar_S: 263 case BuiltinType::WChar_U: 264 return TST_wchar; 265 case BuiltinType::UChar: 266 case BuiltinType::UShort: 267 case BuiltinType::UInt: 268 case BuiltinType::ULong: 269 case BuiltinType::ULongLong: 270 case BuiltinType::UInt128: 271 case BuiltinType::SChar: 272 case BuiltinType::Short: 273 case BuiltinType::Int: 274 case BuiltinType::Long: 275 case BuiltinType::LongLong: 276 case BuiltinType::Int128: 277 case BuiltinType::Half: 278 case BuiltinType::Float: 279 case BuiltinType::Double: 280 case BuiltinType::LongDouble: 281 llvm_unreachable("Builtin type needs extra local data!"); 282 // Fall through, if the impossible happens. 283 284 case BuiltinType::NullPtr: 285 case BuiltinType::Overload: 286 case BuiltinType::Dependent: 287 case BuiltinType::BoundMember: 288 case BuiltinType::UnknownAny: 289 case BuiltinType::ARCUnbridgedCast: 290 case BuiltinType::PseudoObject: 291 case BuiltinType::ObjCId: 292 case BuiltinType::ObjCClass: 293 case BuiltinType::ObjCSel: 294 case BuiltinType::OCLImage1d: 295 case BuiltinType::OCLImage1dArray: 296 case BuiltinType::OCLImage1dBuffer: 297 case BuiltinType::OCLImage2d: 298 case BuiltinType::OCLImage2dArray: 299 case BuiltinType::OCLImage3d: 300 case BuiltinType::OCLSampler: 301 case BuiltinType::OCLEvent: 302 case BuiltinType::BuiltinFn: 303 return TST_unspecified; 304 } 305 306 llvm_unreachable("Invalid BuiltinType Kind!"); 307} 308 309TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 310 while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>()) 311 TL = PTL.getInnerLoc(); 312 return TL; 313} 314 315void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 316 SourceLocation Loc) { 317 setElaboratedKeywordLoc(Loc); 318 NestedNameSpecifierLocBuilder Builder; 319 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 320 setQualifierLoc(Builder.getWithLocInContext(Context)); 321} 322 323void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 324 SourceLocation Loc) { 325 setElaboratedKeywordLoc(Loc); 326 NestedNameSpecifierLocBuilder Builder; 327 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 328 setQualifierLoc(Builder.getWithLocInContext(Context)); 329 setNameLoc(Loc); 330} 331 332void 333DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 334 SourceLocation Loc) { 335 setElaboratedKeywordLoc(Loc); 336 if (getTypePtr()->getQualifier()) { 337 NestedNameSpecifierLocBuilder Builder; 338 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 339 setQualifierLoc(Builder.getWithLocInContext(Context)); 340 } else { 341 setQualifierLoc(NestedNameSpecifierLoc()); 342 } 343 setTemplateKeywordLoc(Loc); 344 setTemplateNameLoc(Loc); 345 setLAngleLoc(Loc); 346 setRAngleLoc(Loc); 347 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), 348 getTypePtr()->getArgs(), 349 getArgInfos(), Loc); 350} 351 352void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 353 unsigned NumArgs, 354 const TemplateArgument *Args, 355 TemplateArgumentLocInfo *ArgInfos, 356 SourceLocation Loc) { 357 for (unsigned i = 0, e = NumArgs; i != e; ++i) { 358 switch (Args[i].getKind()) { 359 case TemplateArgument::Null: 360 llvm_unreachable("Impossible TemplateArgument"); 361 362 case TemplateArgument::Integral: 363 case TemplateArgument::Declaration: 364 case TemplateArgument::NullPtr: 365 ArgInfos[i] = TemplateArgumentLocInfo(); 366 break; 367 368 case TemplateArgument::Expression: 369 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); 370 break; 371 372 case TemplateArgument::Type: 373 ArgInfos[i] = TemplateArgumentLocInfo( 374 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 375 Loc)); 376 break; 377 378 case TemplateArgument::Template: 379 case TemplateArgument::TemplateExpansion: { 380 NestedNameSpecifierLocBuilder Builder; 381 TemplateName Template = Args[i].getAsTemplate(); 382 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) 383 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); 384 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) 385 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); 386 387 ArgInfos[i] = TemplateArgumentLocInfo( 388 Builder.getWithLocInContext(Context), 389 Loc, 390 Args[i].getKind() == TemplateArgument::Template 391 ? SourceLocation() 392 : Loc); 393 break; 394 } 395 396 case TemplateArgument::Pack: 397 ArgInfos[i] = TemplateArgumentLocInfo(); 398 break; 399 } 400 } 401} 402