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/ASTContext.h" 17#include "clang/AST/Expr.h" 18#include "llvm/Support/ErrorHandling.h" 19using namespace clang; 20 21//===----------------------------------------------------------------------===// 22// TypeLoc Implementation 23//===----------------------------------------------------------------------===// 24 25namespace { 26 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { 27 public: 28#define ABSTRACT_TYPELOC(CLASS, PARENT) 29#define TYPELOC(CLASS, PARENT) \ 30 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 31 return TyLoc.getLocalSourceRange(); \ 32 } 33#include "clang/AST/TypeLocNodes.def" 34 }; 35} 36 37SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { 38 if (TL.isNull()) return SourceRange(); 39 return TypeLocRanger().Visit(TL); 40} 41 42namespace { 43 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { 44 public: 45#define ABSTRACT_TYPELOC(CLASS, PARENT) 46#define TYPELOC(CLASS, PARENT) \ 47 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 48 return TyLoc.getFullDataSize(); \ 49 } 50#include "clang/AST/TypeLocNodes.def" 51 }; 52} 53 54/// \brief Returns the size of the type source info data block. 55unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { 56 if (Ty.isNull()) return 0; 57 return TypeSizer().Visit(TypeLoc(Ty, 0)); 58} 59 60namespace { 61 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { 62 public: 63#define ABSTRACT_TYPELOC(CLASS, PARENT) 64#define TYPELOC(CLASS, PARENT) \ 65 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 66 return TyLoc.getNextTypeLoc(); \ 67 } 68#include "clang/AST/TypeLocNodes.def" 69 }; 70} 71 72/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the 73/// TypeLoc is a PointerLoc and next TypeLoc is for "int". 74TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) { 75 return NextLoc().Visit(TL); 76} 77 78/// \brief Initializes a type location, and all of its children 79/// recursively, as if the entire tree had been written in the 80/// given location. 81void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 82 SourceLocation Loc) { 83 while (true) { 84 switch (TL.getTypeLocClass()) { 85#define ABSTRACT_TYPELOC(CLASS, PARENT) 86#define TYPELOC(CLASS, PARENT) \ 87 case CLASS: { \ 88 CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \ 89 TLCasted.initializeLocal(Context, Loc); \ 90 TL = TLCasted.getNextTypeLoc(); \ 91 if (!TL) return; \ 92 continue; \ 93 } 94#include "clang/AST/TypeLocNodes.def" 95 } 96 } 97} 98 99SourceLocation TypeLoc::getBeginLoc() const { 100 TypeLoc Cur = *this; 101 while (true) { 102 switch (Cur.getTypeLocClass()) { 103 // FIXME: Currently QualifiedTypeLoc does not have a source range 104 // case Qualified: 105 case Elaborated: 106 case DependentName: 107 case DependentTemplateSpecialization: 108 break; 109 default: 110 TypeLoc Next = Cur.getNextTypeLoc(); 111 if (Next.isNull()) break; 112 Cur = Next; 113 continue; 114 } 115 break; 116 } 117 return Cur.getLocalSourceRange().getBegin(); 118} 119 120SourceLocation TypeLoc::getEndLoc() const { 121 TypeLoc Cur = *this; 122 TypeLoc Last; 123 while (true) { 124 switch (Cur.getTypeLocClass()) { 125 default: 126 if (!Last) 127 Last = Cur; 128 return Last.getLocalSourceRange().getEnd(); 129 case Paren: 130 case ConstantArray: 131 case DependentSizedArray: 132 case IncompleteArray: 133 case VariableArray: 134 case FunctionProto: 135 case FunctionNoProto: 136 Last = Cur; 137 break; 138 case Pointer: 139 case BlockPointer: 140 case MemberPointer: 141 case LValueReference: 142 case RValueReference: 143 case PackExpansion: 144 if (!Last) 145 Last = Cur; 146 break; 147 case Qualified: 148 case Elaborated: 149 break; 150 } 151 Cur = Cur.getNextTypeLoc(); 152 } 153} 154 155 156namespace { 157 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { 158 // Overload resolution does the real work for us. 159 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } 160 static bool isTypeSpec(TypeLoc _) { return false; } 161 162#define ABSTRACT_TYPELOC(CLASS, PARENT) 163#define TYPELOC(CLASS, PARENT) \ 164 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 165 return isTypeSpec(TyLoc); \ 166 } 167#include "clang/AST/TypeLocNodes.def" 168 }; 169} 170 171 172/// \brief Determines if the given type loc corresponds to a 173/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in 174/// the type hierarchy, this is made somewhat complicated. 175/// 176/// There are a lot of types that currently use TypeSpecTypeLoc 177/// because it's a convenient base class. Ideally we would not accept 178/// those here, but ideally we would have better implementations for 179/// them. 180bool TypeSpecTypeLoc::classof(const TypeLoc *TL) { 181 if (TL->getType().hasLocalQualifiers()) return false; 182 return TSTChecker().Visit(*TL); 183} 184 185// Reimplemented to account for GNU/C++ extension 186// typeof unary-expression 187// where there are no parentheses. 188SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { 189 if (getRParenLoc().isValid()) 190 return SourceRange(getTypeofLoc(), getRParenLoc()); 191 else 192 return SourceRange(getTypeofLoc(), 193 getUnderlyingExpr()->getSourceRange().getEnd()); 194} 195 196 197TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { 198 if (needsExtraLocalData()) 199 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); 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 case BuiltinType::UChar: 216 case BuiltinType::UShort: 217 case BuiltinType::UInt: 218 case BuiltinType::ULong: 219 case BuiltinType::ULongLong: 220 case BuiltinType::UInt128: 221 case BuiltinType::SChar: 222 case BuiltinType::Short: 223 case BuiltinType::Int: 224 case BuiltinType::Long: 225 case BuiltinType::LongLong: 226 case BuiltinType::Int128: 227 case BuiltinType::Half: 228 case BuiltinType::Float: 229 case BuiltinType::Double: 230 case BuiltinType::LongDouble: 231 llvm_unreachable("Builtin type needs extra local data!"); 232 // Fall through, if the impossible happens. 233 234 case BuiltinType::NullPtr: 235 case BuiltinType::Overload: 236 case BuiltinType::Dependent: 237 case BuiltinType::BoundMember: 238 case BuiltinType::UnknownAny: 239 case BuiltinType::ARCUnbridgedCast: 240 case BuiltinType::PseudoObject: 241 case BuiltinType::ObjCId: 242 case BuiltinType::ObjCClass: 243 case BuiltinType::ObjCSel: 244 case BuiltinType::BuiltinFn: 245 return TST_unspecified; 246 } 247 248 llvm_unreachable("Invalid BuiltinType Kind!"); 249} 250 251TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { 252 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) 253 TL = PTL->getInnerLoc(); 254 return TL; 255} 256 257void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 258 SourceLocation Loc) { 259 setElaboratedKeywordLoc(Loc); 260 NestedNameSpecifierLocBuilder Builder; 261 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 262 setQualifierLoc(Builder.getWithLocInContext(Context)); 263} 264 265void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 266 SourceLocation Loc) { 267 setElaboratedKeywordLoc(Loc); 268 NestedNameSpecifierLocBuilder Builder; 269 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 270 setQualifierLoc(Builder.getWithLocInContext(Context)); 271 setNameLoc(Loc); 272} 273 274void 275DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, 276 SourceLocation Loc) { 277 setElaboratedKeywordLoc(Loc); 278 if (getTypePtr()->getQualifier()) { 279 NestedNameSpecifierLocBuilder Builder; 280 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); 281 setQualifierLoc(Builder.getWithLocInContext(Context)); 282 } else { 283 setQualifierLoc(NestedNameSpecifierLoc()); 284 } 285 setTemplateKeywordLoc(Loc); 286 setTemplateNameLoc(Loc); 287 setLAngleLoc(Loc); 288 setRAngleLoc(Loc); 289 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), 290 getTypePtr()->getArgs(), 291 getArgInfos(), Loc); 292} 293 294void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 295 unsigned NumArgs, 296 const TemplateArgument *Args, 297 TemplateArgumentLocInfo *ArgInfos, 298 SourceLocation Loc) { 299 for (unsigned i = 0, e = NumArgs; i != e; ++i) { 300 switch (Args[i].getKind()) { 301 case TemplateArgument::Null: 302 case TemplateArgument::Declaration: 303 case TemplateArgument::Integral: 304 case TemplateArgument::Pack: 305 case TemplateArgument::Expression: 306 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); 307 break; 308 309 case TemplateArgument::Type: 310 ArgInfos[i] = TemplateArgumentLocInfo( 311 Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 312 Loc)); 313 break; 314 315 case TemplateArgument::Template: 316 case TemplateArgument::TemplateExpansion: { 317 NestedNameSpecifierLocBuilder Builder; 318 TemplateName Template = Args[i].getAsTemplate(); 319 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) 320 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); 321 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) 322 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); 323 324 ArgInfos[i] = TemplateArgumentLocInfo( 325 Builder.getWithLocInContext(Context), 326 Loc, 327 Args[i].getKind() == TemplateArgument::Template 328 ? SourceLocation() 329 : Loc); 330 break; 331 } 332 } 333 } 334} 335