TypeLoc.cpp 10 KB

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