TypeLoc.cpp revision 55fc873017f10f6f566b182b70f6fc22aefa3464
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::BuiltinFn: 266 return TST_unspecified; 267 } 268 269 llvm_unreachable("Invalid BuiltinType Kind!"); 270} 271 272TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 273 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) 274 TL = PTL->getInnerLoc(); 275 return TL; 276} 277 278void 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 286void 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 295void 296DependentTemplateSpecializationTypeLoc::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 315void 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