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::BuiltinFn: 266 return TST_unspecified; 267 } 268 269 llvm_unreachable("Invalid BuiltinType Kind!"); 270 } 271 272 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 273 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) 274 TL = PTL->getInnerLoc(); 275 return TL; 276 } 277 278 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 279 SourceLocation Loc) { 280 setElaboratedKeywordLoc(Loc); 281 NestedNameSpecifierLocBuilder Builder; 282 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 283 setQualifierLoc(Builder.getWithLocInContext(Context)); 284 } 285 286 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 287 SourceLocation Loc) { 288 setElaboratedKeywordLoc(Loc); 289 NestedNameSpecifierLocBuilder Builder; 290 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 291 setQualifierLoc(Builder.getWithLocInContext(Context)); 292 setNameLoc(Loc); 293 } 294 295 void 296 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 297 SourceLocation Loc) { 298 setElaboratedKeywordLoc(Loc); 299 if (getTypePtr()->getQualifier()) { 300 NestedNameSpecifierLocBuilder Builder; 301 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 302 setQualifierLoc(Builder.getWithLocInContext(Context)); 303 } else { 304 setQualifierLoc(NestedNameSpecifierLoc()); 305 } 306 setTemplateKeywordLoc(Loc); 307 setTemplateNameLoc(Loc); 308 setLAngleLoc(Loc); 309 setRAngleLoc(Loc); 310 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), 311 getTypePtr()->getArgs(), 312 getArgInfos(), Loc); 313 } 314 315 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 316 unsigned NumArgs, 317 const TemplateArgument *Args, 318 TemplateArgumentLocInfo *ArgInfos, 319 SourceLocation Loc) { 320 for (unsigned i = 0, e = NumArgs; i != e; ++i) { 321 switch (Args[i].getKind()) { 322 case TemplateArgument::Null: 323 case TemplateArgument::Declaration: 324 case TemplateArgument::Integral: 325 case TemplateArgument::NullPtr: 326 llvm_unreachable("Impossible TemplateArgument"); 327 328 case TemplateArgument::Expression: 329 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); 330 break; 331 332 case TemplateArgument::Type: 333 ArgInfos[i] = TemplateArgumentLocInfo( 334 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 335 Loc)); 336 break; 337 338 case TemplateArgument::Template: 339 case TemplateArgument::TemplateExpansion: { 340 NestedNameSpecifierLocBuilder Builder; 341 TemplateName Template = Args[i].getAsTemplate(); 342 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) 343 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); 344 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) 345 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); 346 347 ArgInfos[i] = TemplateArgumentLocInfo( 348 Builder.getWithLocInContext(Context), 349 Loc, 350 Args[i].getKind() == TemplateArgument::Template 351 ? SourceLocation() 352 : Loc); 353 break; 354 } 355 356 case TemplateArgument::Pack: 357 ArgInfos[i] = TemplateArgumentLocInfo(); 358 break; 359 } 360 } 361 } 362