TypeLoc.cpp revision 239cbb023c8da689e7722f7146914eed9755e368
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 break; 106 default: 107 TypeLoc Next = Cur.getNextTypeLoc(); 108 if (Next.isNull()) break; 109 Cur = Next; 110 continue; 111 } 112 break; 113 } 114 return Cur.getLocalSourceRange().getBegin(); 115} 116 117SourceLocation TypeLoc::getEndLoc() const { 118 TypeLoc Cur = *this; 119 while (true) { 120 switch (Cur.getTypeLocClass()) { 121 default: 122 break; 123 case Qualified: 124 case Elaborated: 125 Cur = Cur.getNextTypeLoc(); 126 continue; 127 } 128 break; 129 } 130 return Cur.getLocalSourceRange().getEnd(); 131} 132 133 134namespace { 135 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { 136 // Overload resolution does the real work for us. 137 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } 138 static bool isTypeSpec(TypeLoc _) { return false; } 139 140#define ABSTRACT_TYPELOC(CLASS, PARENT) 141#define TYPELOC(CLASS, PARENT) \ 142 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 143 return isTypeSpec(TyLoc); \ 144 } 145#include "clang/AST/TypeLocNodes.def" 146 }; 147} 148 149 150/// \brief Determines if the given type loc corresponds to a 151/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in 152/// the type hierarchy, this is made somewhat complicated. 153/// 154/// There are a lot of types that currently use TypeSpecTypeLoc 155/// because it's a convenient base class. Ideally we would not accept 156/// those here, but ideally we would have better implementations for 157/// them. 158bool TypeSpecTypeLoc::classof(const TypeLoc *TL) { 159 if (TL->getType().hasLocalQualifiers()) return false; 160 return TSTChecker().Visit(*TL); 161} 162 163// Reimplemented to account for GNU/C++ extension 164// typeof unary-expression 165// where there are no parentheses. 166SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { 167 if (getRParenLoc().isValid()) 168 return SourceRange(getTypeofLoc(), getRParenLoc()); 169 else 170 return SourceRange(getTypeofLoc(), 171 getUnderlyingExpr()->getSourceRange().getEnd()); 172} 173 174 175TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { 176 if (needsExtraLocalData()) 177 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); 178 else { 179 switch (getTypePtr()->getKind()) { 180 case BuiltinType::Void: 181 return TST_void; 182 case BuiltinType::Bool: 183 return TST_bool; 184 case BuiltinType::Char_U: 185 case BuiltinType::Char_S: 186 return TST_char; 187 case BuiltinType::Char16: 188 return TST_char16; 189 case BuiltinType::Char32: 190 return TST_char32; 191 case BuiltinType::WChar_S: 192 case BuiltinType::WChar_U: 193 return TST_wchar; 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 226TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 227 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) 228 TL = PTL->getInnerLoc(); 229 return TL; 230} 231 232void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 233 SourceLocation Loc) { 234 setKeywordLoc(Loc); 235 NestedNameSpecifierLocBuilder Builder; 236 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 237 setQualifierLoc(Builder.getWithLocInContext(Context)); 238} 239 240void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 241 SourceLocation Loc) { 242 setKeywordLoc(Loc); 243 NestedNameSpecifierLocBuilder Builder; 244 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 245 setQualifierLoc(Builder.getWithLocInContext(Context)); 246 setNameLoc(Loc); 247} 248 249void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 250 unsigned NumArgs, 251 const TemplateArgument *Args, 252 TemplateArgumentLocInfo *ArgInfos, 253 SourceLocation Loc) { 254 for (unsigned i = 0, e = NumArgs; i != e; ++i) { 255 switch (Args[i].getKind()) { 256 case TemplateArgument::Null: 257 case TemplateArgument::Declaration: 258 case TemplateArgument::Integral: 259 case TemplateArgument::Pack: 260 case TemplateArgument::Expression: 261 // FIXME: Can we do better for declarations and integral values? 262 ArgInfos[i] = TemplateArgumentLocInfo(); 263 break; 264 265 case TemplateArgument::Type: 266 ArgInfos[i] = TemplateArgumentLocInfo( 267 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 268 Loc)); 269 break; 270 271 case TemplateArgument::Template: 272 ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, 273 SourceLocation()); 274 break; 275 276 case TemplateArgument::TemplateExpansion: 277 ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc); 278 break; 279 } 280 } 281} 282 283