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