TypeLoc.cpp revision 218893
1198092Srdivacky//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===// 2198092Srdivacky// 3198092Srdivacky// The LLVM Compiler Infrastructure 4198092Srdivacky// 5198092Srdivacky// This file is distributed under the University of Illinois Open Source 6198092Srdivacky// License. See LICENSE.TXT for details. 7198092Srdivacky// 8198092Srdivacky//===----------------------------------------------------------------------===// 9198092Srdivacky// 10198092Srdivacky// This file defines the TypeLoc subclasses implementations. 11198092Srdivacky// 12198092Srdivacky//===----------------------------------------------------------------------===// 13198092Srdivacky 14198112Srdivacky#include "llvm/Support/raw_ostream.h" 15198092Srdivacky#include "clang/AST/TypeLocVisitor.h" 16202379Srdivacky#include "clang/AST/Expr.h" 17202879Srdivacky#include "llvm/Support/ErrorHandling.h" 18198092Srdivackyusing namespace clang; 19198092Srdivacky 20198092Srdivacky//===----------------------------------------------------------------------===// 21198092Srdivacky// TypeLoc Implementation 22198092Srdivacky//===----------------------------------------------------------------------===// 23198092Srdivacky 24198092Srdivackynamespace { 25198398Srdivacky class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { 26198398Srdivacky public: 27198398Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT) 28198112Srdivacky#define TYPELOC(CLASS, PARENT) \ 29198398Srdivacky SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 30208600Srdivacky return TyLoc.getLocalSourceRange(); \ 31198398Srdivacky } 32198092Srdivacky#include "clang/AST/TypeLocNodes.def" 33198398Srdivacky }; 34198092Srdivacky} 35198092Srdivacky 36208600SrdivackySourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { 37198398Srdivacky if (TL.isNull()) return SourceRange(); 38198398Srdivacky return TypeLocRanger().Visit(TL); 39198092Srdivacky} 40198092Srdivacky 41198092Srdivackynamespace { 42198398Srdivacky class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { 43198398Srdivacky public: 44198398Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT) 45198112Srdivacky#define TYPELOC(CLASS, PARENT) \ 46198398Srdivacky unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 47198398Srdivacky return TyLoc.getFullDataSize(); \ 48198398Srdivacky } 49198092Srdivacky#include "clang/AST/TypeLocNodes.def" 50198398Srdivacky }; 51198092Srdivacky} 52198092Srdivacky 53198092Srdivacky/// \brief Returns the size of the type source info data block. 54198112Srdivackyunsigned TypeLoc::getFullDataSizeForType(QualType Ty) { 55198112Srdivacky if (Ty.isNull()) return 0; 56198112Srdivacky return TypeSizer().Visit(TypeLoc(Ty, 0)); 57198092Srdivacky} 58198092Srdivacky 59198092Srdivackynamespace { 60198398Srdivacky class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { 61198398Srdivacky public: 62198398Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT) 63198398Srdivacky#define TYPELOC(CLASS, PARENT) \ 64198398Srdivacky TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 65198398Srdivacky return TyLoc.getNextTypeLoc(); \ 66198398Srdivacky } 67198092Srdivacky#include "clang/AST/TypeLocNodes.def" 68198398Srdivacky }; 69198092Srdivacky} 70198092Srdivacky 71198092Srdivacky/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the 72198092Srdivacky/// TypeLoc is a PointerLoc and next TypeLoc is for "int". 73198398SrdivackyTypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) { 74198398Srdivacky return NextLoc().Visit(TL); 75198092Srdivacky} 76198092Srdivacky 77198398Srdivacky/// \brief Initializes a type location, and all of its children 78198398Srdivacky/// recursively, as if the entire tree had been written in the 79198398Srdivacky/// given location. 80218893Sdimvoid TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 81218893Sdim SourceLocation Loc) { 82208600Srdivacky while (true) { 83208600Srdivacky switch (TL.getTypeLocClass()) { 84208600Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT) 85208600Srdivacky#define TYPELOC(CLASS, PARENT) \ 86208600Srdivacky case CLASS: { \ 87208600Srdivacky CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \ 88218893Sdim TLCasted.initializeLocal(Context, Loc); \ 89208600Srdivacky TL = TLCasted.getNextTypeLoc(); \ 90208600Srdivacky if (!TL) return; \ 91208600Srdivacky continue; \ 92208600Srdivacky } 93208600Srdivacky#include "clang/AST/TypeLocNodes.def" 94208600Srdivacky } 95208600Srdivacky } 96198092Srdivacky} 97200583Srdivacky 98208600SrdivackySourceLocation TypeLoc::getBeginLoc() const { 99208600Srdivacky TypeLoc Cur = *this; 100208600Srdivacky while (true) { 101208600Srdivacky switch (Cur.getTypeLocClass()) { 102208600Srdivacky // FIXME: Currently QualifiedTypeLoc does not have a source range 103208600Srdivacky // case Qualified: 104208600Srdivacky case Elaborated: 105208600Srdivacky break; 106208600Srdivacky default: 107208600Srdivacky TypeLoc Next = Cur.getNextTypeLoc(); 108208600Srdivacky if (Next.isNull()) break; 109208600Srdivacky Cur = Next; 110208600Srdivacky continue; 111208600Srdivacky } 112208600Srdivacky break; 113208600Srdivacky } 114208600Srdivacky return Cur.getLocalSourceRange().getBegin(); 115208600Srdivacky} 116208600Srdivacky 117208600SrdivackySourceLocation TypeLoc::getEndLoc() const { 118208600Srdivacky TypeLoc Cur = *this; 119208600Srdivacky while (true) { 120208600Srdivacky switch (Cur.getTypeLocClass()) { 121208600Srdivacky default: 122208600Srdivacky break; 123208600Srdivacky case Qualified: 124208600Srdivacky case Elaborated: 125208600Srdivacky Cur = Cur.getNextTypeLoc(); 126208600Srdivacky continue; 127208600Srdivacky } 128208600Srdivacky break; 129208600Srdivacky } 130208600Srdivacky return Cur.getLocalSourceRange().getEnd(); 131208600Srdivacky} 132208600Srdivacky 133208600Srdivacky 134200583Srdivackynamespace { 135200583Srdivacky struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { 136200583Srdivacky // Overload resolution does the real work for us. 137200583Srdivacky static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } 138200583Srdivacky static bool isTypeSpec(TypeLoc _) { return false; } 139200583Srdivacky 140200583Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT) 141200583Srdivacky#define TYPELOC(CLASS, PARENT) \ 142200583Srdivacky bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 143200583Srdivacky return isTypeSpec(TyLoc); \ 144200583Srdivacky } 145200583Srdivacky#include "clang/AST/TypeLocNodes.def" 146200583Srdivacky }; 147200583Srdivacky} 148200583Srdivacky 149200583Srdivacky 150200583Srdivacky/// \brief Determines if the given type loc corresponds to a 151200583Srdivacky/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in 152200583Srdivacky/// the type hierarchy, this is made somewhat complicated. 153200583Srdivacky/// 154200583Srdivacky/// There are a lot of types that currently use TypeSpecTypeLoc 155200583Srdivacky/// because it's a convenient base class. Ideally we would not accept 156200583Srdivacky/// those here, but ideally we would have better implementations for 157200583Srdivacky/// them. 158200583Srdivackybool TypeSpecTypeLoc::classof(const TypeLoc *TL) { 159200583Srdivacky if (TL->getType().hasLocalQualifiers()) return false; 160200583Srdivacky return TSTChecker().Visit(*TL); 161200583Srdivacky} 162202379Srdivacky 163202379Srdivacky// Reimplemented to account for GNU/C++ extension 164202379Srdivacky// typeof unary-expression 165202379Srdivacky// where there are no parentheses. 166208600SrdivackySourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { 167202379Srdivacky if (getRParenLoc().isValid()) 168202379Srdivacky return SourceRange(getTypeofLoc(), getRParenLoc()); 169202379Srdivacky else 170202379Srdivacky return SourceRange(getTypeofLoc(), 171202379Srdivacky getUnderlyingExpr()->getSourceRange().getEnd()); 172202379Srdivacky} 173202879Srdivacky 174202879Srdivacky 175202879SrdivackyTypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { 176202879Srdivacky if (needsExtraLocalData()) 177202879Srdivacky return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); 178202879Srdivacky else { 179202879Srdivacky switch (getTypePtr()->getKind()) { 180202879Srdivacky case BuiltinType::Void: 181202879Srdivacky return TST_void; 182202879Srdivacky case BuiltinType::Bool: 183202879Srdivacky return TST_bool; 184202879Srdivacky case BuiltinType::Char_U: 185202879Srdivacky case BuiltinType::Char_S: 186202879Srdivacky return TST_char; 187202879Srdivacky case BuiltinType::Char16: 188202879Srdivacky return TST_char16; 189202879Srdivacky case BuiltinType::Char32: 190202879Srdivacky return TST_char32; 191218893Sdim case BuiltinType::WChar_S: 192218893Sdim case BuiltinType::WChar_U: 193202879Srdivacky return TST_wchar; 194218893Sdim 195202879Srdivacky case BuiltinType::UChar: 196202879Srdivacky case BuiltinType::UShort: 197202879Srdivacky case BuiltinType::UInt: 198202879Srdivacky case BuiltinType::ULong: 199202879Srdivacky case BuiltinType::ULongLong: 200202879Srdivacky case BuiltinType::UInt128: 201202879Srdivacky case BuiltinType::SChar: 202202879Srdivacky case BuiltinType::Short: 203202879Srdivacky case BuiltinType::Int: 204202879Srdivacky case BuiltinType::Long: 205202879Srdivacky case BuiltinType::LongLong: 206202879Srdivacky case BuiltinType::Int128: 207202879Srdivacky case BuiltinType::Float: 208202879Srdivacky case BuiltinType::Double: 209202879Srdivacky case BuiltinType::LongDouble: 210202879Srdivacky llvm_unreachable("Builtin type needs extra local data!"); 211202879Srdivacky // Fall through, if the impossible happens. 212202879Srdivacky 213202879Srdivacky case BuiltinType::NullPtr: 214202879Srdivacky case BuiltinType::Overload: 215202879Srdivacky case BuiltinType::Dependent: 216202879Srdivacky case BuiltinType::ObjCId: 217202879Srdivacky case BuiltinType::ObjCClass: 218202879Srdivacky case BuiltinType::ObjCSel: 219202879Srdivacky return TST_unspecified; 220202879Srdivacky } 221202879Srdivacky } 222202879Srdivacky 223202879Srdivacky return TST_unspecified; 224202879Srdivacky} 225218893Sdim 226218893SdimTypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 227218893Sdim while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) 228218893Sdim TL = PTL->getInnerLoc(); 229218893Sdim return TL; 230218893Sdim} 231218893Sdim 232218893Sdimvoid TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 233218893Sdim unsigned NumArgs, 234218893Sdim const TemplateArgument *Args, 235218893Sdim TemplateArgumentLocInfo *ArgInfos, 236218893Sdim SourceLocation Loc) { 237218893Sdim for (unsigned i = 0, e = NumArgs; i != e; ++i) { 238218893Sdim switch (Args[i].getKind()) { 239218893Sdim case TemplateArgument::Null: 240218893Sdim case TemplateArgument::Declaration: 241218893Sdim case TemplateArgument::Integral: 242218893Sdim case TemplateArgument::Pack: 243218893Sdim case TemplateArgument::Expression: 244218893Sdim // FIXME: Can we do better for declarations and integral values? 245218893Sdim ArgInfos[i] = TemplateArgumentLocInfo(); 246218893Sdim break; 247218893Sdim 248218893Sdim case TemplateArgument::Type: 249218893Sdim ArgInfos[i] = TemplateArgumentLocInfo( 250218893Sdim Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 251218893Sdim Loc)); 252218893Sdim break; 253218893Sdim 254218893Sdim case TemplateArgument::Template: 255218893Sdim ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, 256218893Sdim SourceLocation()); 257218893Sdim break; 258218893Sdim 259218893Sdim case TemplateArgument::TemplateExpansion: 260218893Sdim ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc); 261218893Sdim break; 262218893Sdim } 263218893Sdim } 264218893Sdim} 265218893Sdim 266