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