TypeLoc.cpp revision a1b852f8e1bee5ed3604ee483803cef39ce57a20
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" 18using namespace clang; 19 20//===----------------------------------------------------------------------===// 21// TypeLoc Implementation 22//===----------------------------------------------------------------------===// 23 24namespace { 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 36SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { 37 if (TL.isNull()) return SourceRange(); 38 return TypeLocRanger().Visit(TL); 39} 40 41namespace { 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. 54unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { 55 if (Ty.isNull()) return 0; 56 return TypeSizer().Visit(TypeLoc(Ty, 0)); 57} 58 59namespace { 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". 73TypeLoc 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. 80void 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 98SourceLocation 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 119SourceLocation 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 155namespace { 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. 179bool 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. 187SourceRange 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 196TypeSpecifierType 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::Half: 229 case BuiltinType::Float: 230 case BuiltinType::Double: 231 case BuiltinType::LongDouble: 232 llvm_unreachable("Builtin type needs extra local data!"); 233 // Fall through, if the impossible happens. 234 235 case BuiltinType::NullPtr: 236 case BuiltinType::Overload: 237 case BuiltinType::Dependent: 238 case BuiltinType::BoundMember: 239 case BuiltinType::UnknownAny: 240 case BuiltinType::ARCUnbridgedCast: 241 case BuiltinType::PseudoObject: 242 case BuiltinType::ObjCId: 243 case BuiltinType::ObjCClass: 244 case BuiltinType::ObjCSel: 245 return TST_unspecified; 246 } 247 } 248 249 return TST_unspecified; 250} 251 252TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 253 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) 254 TL = PTL->getInnerLoc(); 255 return TL; 256} 257 258void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 259 SourceLocation Loc) { 260 setKeywordLoc(Loc); 261 NestedNameSpecifierLocBuilder Builder; 262 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 263 setQualifierLoc(Builder.getWithLocInContext(Context)); 264} 265 266void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 267 SourceLocation Loc) { 268 setKeywordLoc(Loc); 269 NestedNameSpecifierLocBuilder Builder; 270 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 271 setQualifierLoc(Builder.getWithLocInContext(Context)); 272 setNameLoc(Loc); 273} 274 275void 276DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 277 SourceLocation Loc) { 278 setKeywordLoc(Loc); 279 if (getTypePtr()->getQualifier()) { 280 NestedNameSpecifierLocBuilder Builder; 281 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 282 setQualifierLoc(Builder.getWithLocInContext(Context)); 283 } else { 284 setQualifierLoc(NestedNameSpecifierLoc()); 285 } 286 287 setNameLoc(Loc); 288 setLAngleLoc(Loc); 289 setRAngleLoc(Loc); 290 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), 291 getTypePtr()->getArgs(), 292 getArgInfos(), Loc); 293} 294 295void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 296 unsigned NumArgs, 297 const TemplateArgument *Args, 298 TemplateArgumentLocInfo *ArgInfos, 299 SourceLocation Loc) { 300 for (unsigned i = 0, e = NumArgs; i != e; ++i) { 301 switch (Args[i].getKind()) { 302 case TemplateArgument::Null: 303 case TemplateArgument::Declaration: 304 case TemplateArgument::Integral: 305 case TemplateArgument::Pack: 306 case TemplateArgument::Expression: 307 // FIXME: Can we do better for declarations and integral values? 308 ArgInfos[i] = TemplateArgumentLocInfo(); 309 break; 310 311 case TemplateArgument::Type: 312 ArgInfos[i] = TemplateArgumentLocInfo( 313 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 314 Loc)); 315 break; 316 317 case TemplateArgument::Template: 318 case TemplateArgument::TemplateExpansion: { 319 NestedNameSpecifierLocBuilder Builder; 320 TemplateName Template = Args[i].getAsTemplate(); 321 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) 322 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); 323 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) 324 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); 325 326 ArgInfos[i] = TemplateArgumentLocInfo( 327 Builder.getWithLocInContext(Context), 328 Loc, 329 Args[i].getKind() == TemplateArgument::Template 330 ? SourceLocation() 331 : Loc); 332 break; 333 } 334 } 335 } 336} 337 338