TypeLoc.cpp revision b6744efecba58792cce20d2d7b9ee39927c5422e
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 while (true) { 122 switch (Cur.getTypeLocClass()) { 123 default: 124 break; 125 case Qualified: 126 case Elaborated: 127 Cur = Cur.getNextTypeLoc(); 128 continue; 129 } 130 break; 131 } 132 return Cur.getLocalSourceRange().getEnd(); 133} 134 135 136namespace { 137 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { 138 // Overload resolution does the real work for us. 139 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } 140 static bool isTypeSpec(TypeLoc _) { return false; } 141 142#define ABSTRACT_TYPELOC(CLASS, PARENT) 143#define TYPELOC(CLASS, PARENT) \ 144 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 145 return isTypeSpec(TyLoc); \ 146 } 147#include "clang/AST/TypeLocNodes.def" 148 }; 149} 150 151 152/// \brief Determines if the given type loc corresponds to a 153/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in 154/// the type hierarchy, this is made somewhat complicated. 155/// 156/// There are a lot of types that currently use TypeSpecTypeLoc 157/// because it's a convenient base class. Ideally we would not accept 158/// those here, but ideally we would have better implementations for 159/// them. 160bool TypeSpecTypeLoc::classof(const TypeLoc *TL) { 161 if (TL->getType().hasLocalQualifiers()) return false; 162 return TSTChecker().Visit(*TL); 163} 164 165// Reimplemented to account for GNU/C++ extension 166// typeof unary-expression 167// where there are no parentheses. 168SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { 169 if (getRParenLoc().isValid()) 170 return SourceRange(getTypeofLoc(), getRParenLoc()); 171 else 172 return SourceRange(getTypeofLoc(), 173 getUnderlyingExpr()->getSourceRange().getEnd()); 174} 175 176 177TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { 178 if (needsExtraLocalData()) 179 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); 180 else { 181 switch (getTypePtr()->getKind()) { 182 case BuiltinType::Void: 183 return TST_void; 184 case BuiltinType::Bool: 185 return TST_bool; 186 case BuiltinType::Char_U: 187 case BuiltinType::Char_S: 188 return TST_char; 189 case BuiltinType::Char16: 190 return TST_char16; 191 case BuiltinType::Char32: 192 return TST_char32; 193 case BuiltinType::WChar_S: 194 case BuiltinType::WChar_U: 195 return TST_wchar; 196 197 case BuiltinType::UChar: 198 case BuiltinType::UShort: 199 case BuiltinType::UInt: 200 case BuiltinType::ULong: 201 case BuiltinType::ULongLong: 202 case BuiltinType::UInt128: 203 case BuiltinType::SChar: 204 case BuiltinType::Short: 205 case BuiltinType::Int: 206 case BuiltinType::Long: 207 case BuiltinType::LongLong: 208 case BuiltinType::Int128: 209 case BuiltinType::Float: 210 case BuiltinType::Double: 211 case BuiltinType::LongDouble: 212 llvm_unreachable("Builtin type needs extra local data!"); 213 // Fall through, if the impossible happens. 214 215 case BuiltinType::NullPtr: 216 case BuiltinType::Overload: 217 case BuiltinType::Dependent: 218 case BuiltinType::ObjCId: 219 case BuiltinType::ObjCClass: 220 case BuiltinType::ObjCSel: 221 return TST_unspecified; 222 } 223 } 224 225 return TST_unspecified; 226} 227 228TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 229 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) 230 TL = PTL->getInnerLoc(); 231 return TL; 232} 233 234void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 235 SourceLocation Loc) { 236 setKeywordLoc(Loc); 237 NestedNameSpecifierLocBuilder Builder; 238 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 239 setQualifierLoc(Builder.getWithLocInContext(Context)); 240} 241 242void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 243 SourceLocation Loc) { 244 setKeywordLoc(Loc); 245 NestedNameSpecifierLocBuilder Builder; 246 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 247 setQualifierLoc(Builder.getWithLocInContext(Context)); 248 setNameLoc(Loc); 249} 250 251void 252DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 253 SourceLocation Loc) { 254 setKeywordLoc(Loc); 255 if (getTypePtr()->getQualifier()) { 256 NestedNameSpecifierLocBuilder Builder; 257 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 258 setQualifierLoc(Builder.getWithLocInContext(Context)); 259 } else { 260 setQualifierLoc(NestedNameSpecifierLoc()); 261 } 262 263 setNameLoc(Loc); 264 setLAngleLoc(Loc); 265 setRAngleLoc(Loc); 266 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), 267 getTypePtr()->getArgs(), 268 getArgInfos(), Loc); 269} 270 271void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 272 unsigned NumArgs, 273 const TemplateArgument *Args, 274 TemplateArgumentLocInfo *ArgInfos, 275 SourceLocation Loc) { 276 for (unsigned i = 0, e = NumArgs; i != e; ++i) { 277 switch (Args[i].getKind()) { 278 case TemplateArgument::Null: 279 case TemplateArgument::Declaration: 280 case TemplateArgument::Integral: 281 case TemplateArgument::Pack: 282 case TemplateArgument::Expression: 283 // FIXME: Can we do better for declarations and integral values? 284 ArgInfos[i] = TemplateArgumentLocInfo(); 285 break; 286 287 case TemplateArgument::Type: 288 ArgInfos[i] = TemplateArgumentLocInfo( 289 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 290 Loc)); 291 break; 292 293 case TemplateArgument::Template: 294 case TemplateArgument::TemplateExpansion: { 295 NestedNameSpecifierLocBuilder Builder; 296 TemplateName Template = Args[i].getAsTemplate(); 297 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) 298 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); 299 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) 300 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); 301 302 ArgInfos[i] = TemplateArgumentLocInfo( 303 Builder.getWithLocInContext(Context), 304 Loc, 305 Args[i].getKind() == TemplateArgument::Template 306 ? SourceLocation() 307 : Loc); 308 break; 309 } 310 } 311 } 312} 313 314