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