TypeLoc.cpp revision ba6f816d633e3b88c38c6896c2d78d19489650f2
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(TypeLoc TL, SourceLocation Loc) { 81 while (true) { 82 switch (TL.getTypeLocClass()) { 83#define ABSTRACT_TYPELOC(CLASS, PARENT) 84#define TYPELOC(CLASS, PARENT) \ 85 case CLASS: { \ 86 CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \ 87 TLCasted.initializeLocal(Loc); \ 88 TL = TLCasted.getNextTypeLoc(); \ 89 if (!TL) return; \ 90 continue; \ 91 } 92#include "clang/AST/TypeLocNodes.def" 93 } 94 } 95} 96 97SourceLocation TypeLoc::getBeginLoc() const { 98 TypeLoc Cur = *this; 99 while (true) { 100 switch (Cur.getTypeLocClass()) { 101 // FIXME: Currently QualifiedTypeLoc does not have a source range 102 // case Qualified: 103 case Elaborated: 104 break; 105 default: 106 TypeLoc Next = Cur.getNextTypeLoc(); 107 if (Next.isNull()) break; 108 Cur = Next; 109 continue; 110 } 111 break; 112 } 113 return Cur.getLocalSourceRange().getBegin(); 114} 115 116SourceLocation TypeLoc::getEndLoc() const { 117 TypeLoc Cur = *this; 118 while (true) { 119 switch (Cur.getTypeLocClass()) { 120 default: 121 break; 122 case Qualified: 123 case Elaborated: 124 Cur = Cur.getNextTypeLoc(); 125 continue; 126 } 127 break; 128 } 129 return Cur.getLocalSourceRange().getEnd(); 130} 131 132 133namespace { 134 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { 135 // Overload resolution does the real work for us. 136 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } 137 static bool isTypeSpec(TypeLoc _) { return false; } 138 139#define ABSTRACT_TYPELOC(CLASS, PARENT) 140#define TYPELOC(CLASS, PARENT) \ 141 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 142 return isTypeSpec(TyLoc); \ 143 } 144#include "clang/AST/TypeLocNodes.def" 145 }; 146} 147 148 149/// \brief Determines if the given type loc corresponds to a 150/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in 151/// the type hierarchy, this is made somewhat complicated. 152/// 153/// There are a lot of types that currently use TypeSpecTypeLoc 154/// because it's a convenient base class. Ideally we would not accept 155/// those here, but ideally we would have better implementations for 156/// them. 157bool TypeSpecTypeLoc::classof(const TypeLoc *TL) { 158 if (TL->getType().hasLocalQualifiers()) return false; 159 return TSTChecker().Visit(*TL); 160} 161 162// Reimplemented to account for GNU/C++ extension 163// typeof unary-expression 164// where there are no parentheses. 165SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { 166 if (getRParenLoc().isValid()) 167 return SourceRange(getTypeofLoc(), getRParenLoc()); 168 else 169 return SourceRange(getTypeofLoc(), 170 getUnderlyingExpr()->getSourceRange().getEnd()); 171} 172 173 174TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { 175 if (needsExtraLocalData()) 176 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); 177 else { 178 switch (getTypePtr()->getKind()) { 179 case BuiltinType::Void: 180 return TST_void; 181 case BuiltinType::Bool: 182 return TST_bool; 183 case BuiltinType::Char_U: 184 case BuiltinType::Char_S: 185 return TST_char; 186 case BuiltinType::Char16: 187 return TST_char16; 188 case BuiltinType::Char32: 189 return TST_char32; 190 case BuiltinType::WChar: 191 return TST_wchar; 192 case BuiltinType::UndeducedAuto: 193 return TST_auto; 194 195 case BuiltinType::UChar: 196 case BuiltinType::UShort: 197 case BuiltinType::UInt: 198 case BuiltinType::ULong: 199 case BuiltinType::ULongLong: 200 case BuiltinType::UInt128: 201 case BuiltinType::SChar: 202 case BuiltinType::Short: 203 case BuiltinType::Int: 204 case BuiltinType::Long: 205 case BuiltinType::LongLong: 206 case BuiltinType::Int128: 207 case BuiltinType::Float: 208 case BuiltinType::Double: 209 case BuiltinType::LongDouble: 210 llvm_unreachable("Builtin type needs extra local data!"); 211 // Fall through, if the impossible happens. 212 213 case BuiltinType::NullPtr: 214 case BuiltinType::Overload: 215 case BuiltinType::Dependent: 216 case BuiltinType::ObjCId: 217 case BuiltinType::ObjCClass: 218 case BuiltinType::ObjCSel: 219 return TST_unspecified; 220 } 221 } 222 223 return TST_unspecified; 224} 225