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