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" 20 using namespace clang; 21 22 //===----------------------------------------------------------------------===// 23 // TypeLoc Implementation 24 //===----------------------------------------------------------------------===// 25 26 namespace { 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 38 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { 39 if (TL.isNull()) return SourceRange(); 40 return TypeLocRanger().Visit(TL); 41 } 42 43 namespace { 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. 56 unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) { 57 if (Ty.isNull()) return 1; 58 return TypeAligner().Visit(TypeLoc(Ty, 0)); 59 } 60 61 namespace { 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. 74 unsigned 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 89 namespace { 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". 103 TypeLoc 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. 110 void 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 128 SourceLocation 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 165 SourceLocation 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 206 namespace { 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. 230 bool 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. 238 SourceRange 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 247 TypeSpecifierType 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 309 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 310 while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>()) 311 TL = PTL.getInnerLoc(); 312 return TL; 313 } 314 315 void 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 323 void 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 332 void 333 DependentTemplateSpecializationTypeLoc::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 352 void 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