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 else { 200 switch (getTypePtr()->getKind()) { 201 case BuiltinType::Void: 202 return TST_void; 203 case BuiltinType::Bool: 204 return TST_bool; 205 case BuiltinType::Char_U: 206 case BuiltinType::Char_S: 207 return TST_char; 208 case BuiltinType::Char16: 209 return TST_char16; 210 case BuiltinType::Char32: 211 return TST_char32; 212 case BuiltinType::WChar_S: 213 case BuiltinType::WChar_U: 214 return TST_wchar; 215 216 case BuiltinType::UChar: 217 case BuiltinType::UShort: 218 case BuiltinType::UInt: 219 case BuiltinType::ULong: 220 case BuiltinType::ULongLong: 221 case BuiltinType::UInt128: 222 case BuiltinType::SChar: 223 case BuiltinType::Short: 224 case BuiltinType::Int: 225 case BuiltinType::Long: 226 case BuiltinType::LongLong: 227 case BuiltinType::Int128: 228 case BuiltinType::Float: 229 case BuiltinType::Double: 230 case BuiltinType::LongDouble: 231 llvm_unreachable("Builtin type needs extra local data!"); 232 // Fall through, if the impossible happens. 233 234 case BuiltinType::NullPtr: 235 case BuiltinType::Overload: 236 case BuiltinType::Dependent: 237 case BuiltinType::BoundMember: 238 case BuiltinType::UnknownAny: 239 case BuiltinType::ObjCId: 240 case BuiltinType::ObjCClass: 241 case BuiltinType::ObjCSel: 242 return TST_unspecified; 243 } 244 } 245 246 return TST_unspecified; 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 setKeywordLoc(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 setKeywordLoc(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 setKeywordLoc(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 284 setNameLoc(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 // FIXME: Can we do better for declarations and integral values? 305 ArgInfos[i] = TemplateArgumentLocInfo(); 306 break; 307 308 case TemplateArgument::Type: 309 ArgInfos[i] = TemplateArgumentLocInfo( 310 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 311 Loc)); 312 break; 313 314 case TemplateArgument::Template: 315 case TemplateArgument::TemplateExpansion: { 316 NestedNameSpecifierLocBuilder Builder; 317 TemplateName Template = Args[i].getAsTemplate(); 318 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) 319 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); 320 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) 321 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); 322 323 ArgInfos[i] = TemplateArgumentLocInfo( 324 Builder.getWithLocInContext(Context), 325 Loc, 326 Args[i].getKind() == TemplateArgument::Template 327 ? SourceLocation() 328 : Loc); 329 break; 330 } 331 } 332 } 333 } 334 335