TypeLoc.cpp revision ea285162342df160e7860e26528bc7110bc6c0cd
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.getSourceRange(); \ 31 } 32#include "clang/AST/TypeLocNodes.def" 33 }; 34} 35 36SourceRange TypeLoc::getSourceRangeImpl(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 77namespace { 78 struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> { 79 SourceLocation Loc; 80 TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {} 81 82#define ABSTRACT_TYPELOC(CLASS, PARENT) 83#define TYPELOC(CLASS, PARENT) \ 84 void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 85 TyLoc.initializeLocal(Loc); \ 86 } 87#include "clang/AST/TypeLocNodes.def" 88 }; 89} 90 91/// \brief Initializes a type location, and all of its children 92/// recursively, as if the entire tree had been written in the 93/// given location. 94void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) { 95 do { 96 TypeLocInitializer(Loc).Visit(TL); 97 } while ((TL = TL.getNextTypeLoc())); 98} 99 100namespace { 101 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { 102 // Overload resolution does the real work for us. 103 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } 104 static bool isTypeSpec(TypeLoc _) { return false; } 105 106#define ABSTRACT_TYPELOC(CLASS, PARENT) 107#define TYPELOC(CLASS, PARENT) \ 108 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ 109 return isTypeSpec(TyLoc); \ 110 } 111#include "clang/AST/TypeLocNodes.def" 112 }; 113} 114 115 116/// \brief Determines if the given type loc corresponds to a 117/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in 118/// the type hierarchy, this is made somewhat complicated. 119/// 120/// There are a lot of types that currently use TypeSpecTypeLoc 121/// because it's a convenient base class. Ideally we would not accept 122/// those here, but ideally we would have better implementations for 123/// them. 124bool TypeSpecTypeLoc::classof(const TypeLoc *TL) { 125 if (TL->getType().hasLocalQualifiers()) return false; 126 return TSTChecker().Visit(*TL); 127} 128 129// Reimplemented to account for GNU/C++ extension 130// typeof unary-expression 131// where there are no parentheses. 132SourceRange TypeOfExprTypeLoc::getSourceRange() const { 133 if (getRParenLoc().isValid()) 134 return SourceRange(getTypeofLoc(), getRParenLoc()); 135 else 136 return SourceRange(getTypeofLoc(), 137 getUnderlyingExpr()->getSourceRange().getEnd()); 138} 139 140 141TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { 142 if (needsExtraLocalData()) 143 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); 144 else { 145 switch (getTypePtr()->getKind()) { 146 case BuiltinType::Void: 147 return TST_void; 148 case BuiltinType::Bool: 149 return TST_bool; 150 case BuiltinType::Char_U: 151 case BuiltinType::Char_S: 152 return TST_char; 153 case BuiltinType::Char16: 154 return TST_char16; 155 case BuiltinType::Char32: 156 return TST_char32; 157 case BuiltinType::WChar: 158 return TST_wchar; 159 case BuiltinType::UndeducedAuto: 160 return TST_auto; 161 162 case BuiltinType::UChar: 163 case BuiltinType::UShort: 164 case BuiltinType::UInt: 165 case BuiltinType::ULong: 166 case BuiltinType::ULongLong: 167 case BuiltinType::UInt128: 168 case BuiltinType::SChar: 169 case BuiltinType::Short: 170 case BuiltinType::Int: 171 case BuiltinType::Long: 172 case BuiltinType::LongLong: 173 case BuiltinType::Int128: 174 case BuiltinType::Float: 175 case BuiltinType::Double: 176 case BuiltinType::LongDouble: 177 llvm_unreachable("Builtin type needs extra local data!"); 178 // Fall through, if the impossible happens. 179 180 case BuiltinType::NullPtr: 181 case BuiltinType::Overload: 182 case BuiltinType::Dependent: 183 case BuiltinType::ObjCId: 184 case BuiltinType::ObjCClass: 185 case BuiltinType::ObjCSel: 186 return TST_unspecified; 187 } 188 } 189 190 return TST_unspecified; 191} 192