TypeLoc.cpp revision b13621d08e20ac7aa550e05896de8a57ee99c1e8
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" 20using namespace clang; 21 22//===----------------------------------------------------------------------===// 23// TypeLoc Implementation 24//===----------------------------------------------------------------------===// 25 26namespace { 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 38SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { 39 if (TL.isNull()) return SourceRange(); 40 return TypeLocRanger().Visit(TL); 41} 42 43namespace { 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. 56unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { 57 if (Ty.isNull()) return 0; 58 return TypeSizer().Visit(TypeLoc(Ty, 0)); 59} 60 61namespace { 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". 75TypeLoc 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. 82void 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 100SourceLocation 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 136SourceLocation 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 177namespace { 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. 201bool 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. 209SourceRange 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 218TypeSpecifierType 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::OCLImage1d: 266 case BuiltinType::OCLImage1dArray: 267 case BuiltinType::OCLImage1dBuffer: 268 case BuiltinType::OCLImage2d: 269 case BuiltinType::OCLImage2dArray: 270 case BuiltinType::OCLImage3d: 271 case BuiltinType::BuiltinFn: 272 return TST_unspecified; 273 } 274 275 llvm_unreachable("Invalid BuiltinType Kind!"); 276} 277 278TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 279 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) 280 TL = PTL->getInnerLoc(); 281 return TL; 282} 283 284void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 285 SourceLocation Loc) { 286 setElaboratedKeywordLoc(Loc); 287 NestedNameSpecifierLocBuilder Builder; 288 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 289 setQualifierLoc(Builder.getWithLocInContext(Context)); 290} 291 292void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 293 SourceLocation Loc) { 294 setElaboratedKeywordLoc(Loc); 295 NestedNameSpecifierLocBuilder Builder; 296 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 297 setQualifierLoc(Builder.getWithLocInContext(Context)); 298 setNameLoc(Loc); 299} 300 301void 302DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 303 SourceLocation Loc) { 304 setElaboratedKeywordLoc(Loc); 305 if (getTypePtr()->getQualifier()) { 306 NestedNameSpecifierLocBuilder Builder; 307 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 308 setQualifierLoc(Builder.getWithLocInContext(Context)); 309 } else { 310 setQualifierLoc(NestedNameSpecifierLoc()); 311 } 312 setTemplateKeywordLoc(Loc); 313 setTemplateNameLoc(Loc); 314 setLAngleLoc(Loc); 315 setRAngleLoc(Loc); 316 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), 317 getTypePtr()->getArgs(), 318 getArgInfos(), Loc); 319} 320 321void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 322 unsigned NumArgs, 323 const TemplateArgument *Args, 324 TemplateArgumentLocInfo *ArgInfos, 325 SourceLocation Loc) { 326 for (unsigned i = 0, e = NumArgs; i != e; ++i) { 327 switch (Args[i].getKind()) { 328 case TemplateArgument::Null: 329 case TemplateArgument::Declaration: 330 case TemplateArgument::Integral: 331 case TemplateArgument::NullPtr: 332 llvm_unreachable("Impossible TemplateArgument"); 333 334 case TemplateArgument::Expression: 335 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); 336 break; 337 338 case TemplateArgument::Type: 339 ArgInfos[i] = TemplateArgumentLocInfo( 340 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 341 Loc)); 342 break; 343 344 case TemplateArgument::Template: 345 case TemplateArgument::TemplateExpansion: { 346 NestedNameSpecifierLocBuilder Builder; 347 TemplateName Template = Args[i].getAsTemplate(); 348 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) 349 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); 350 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) 351 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); 352 353 ArgInfos[i] = TemplateArgumentLocInfo( 354 Builder.getWithLocInContext(Context), 355 Loc, 356 Args[i].getKind() == TemplateArgument::Template 357 ? SourceLocation() 358 : Loc); 359 break; 360 } 361 362 case TemplateArgument::Pack: 363 ArgInfos[i] = TemplateArgumentLocInfo(); 364 break; 365 } 366 } 367} 368