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