TypeLoc.cpp revision 218893
1198092Srdivacky//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
2198092Srdivacky//
3198092Srdivacky//                     The LLVM Compiler Infrastructure
4198092Srdivacky//
5198092Srdivacky// This file is distributed under the University of Illinois Open Source
6198092Srdivacky// License. See LICENSE.TXT for details.
7198092Srdivacky//
8198092Srdivacky//===----------------------------------------------------------------------===//
9198092Srdivacky//
10198092Srdivacky//  This file defines the TypeLoc subclasses implementations.
11198092Srdivacky//
12198092Srdivacky//===----------------------------------------------------------------------===//
13198092Srdivacky
14198112Srdivacky#include "llvm/Support/raw_ostream.h"
15198092Srdivacky#include "clang/AST/TypeLocVisitor.h"
16202379Srdivacky#include "clang/AST/Expr.h"
17202879Srdivacky#include "llvm/Support/ErrorHandling.h"
18198092Srdivackyusing namespace clang;
19198092Srdivacky
20198092Srdivacky//===----------------------------------------------------------------------===//
21198092Srdivacky// TypeLoc Implementation
22198092Srdivacky//===----------------------------------------------------------------------===//
23198092Srdivacky
24198092Srdivackynamespace {
25198398Srdivacky  class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
26198398Srdivacky  public:
27198398Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT)
28198112Srdivacky#define TYPELOC(CLASS, PARENT) \
29198398Srdivacky    SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
30208600Srdivacky      return TyLoc.getLocalSourceRange(); \
31198398Srdivacky    }
32198092Srdivacky#include "clang/AST/TypeLocNodes.def"
33198398Srdivacky  };
34198092Srdivacky}
35198092Srdivacky
36208600SrdivackySourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
37198398Srdivacky  if (TL.isNull()) return SourceRange();
38198398Srdivacky  return TypeLocRanger().Visit(TL);
39198092Srdivacky}
40198092Srdivacky
41198092Srdivackynamespace {
42198398Srdivacky  class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
43198398Srdivacky  public:
44198398Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT)
45198112Srdivacky#define TYPELOC(CLASS, PARENT) \
46198398Srdivacky    unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
47198398Srdivacky      return TyLoc.getFullDataSize(); \
48198398Srdivacky    }
49198092Srdivacky#include "clang/AST/TypeLocNodes.def"
50198398Srdivacky  };
51198092Srdivacky}
52198092Srdivacky
53198092Srdivacky/// \brief Returns the size of the type source info data block.
54198112Srdivackyunsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
55198112Srdivacky  if (Ty.isNull()) return 0;
56198112Srdivacky  return TypeSizer().Visit(TypeLoc(Ty, 0));
57198092Srdivacky}
58198092Srdivacky
59198092Srdivackynamespace {
60198398Srdivacky  class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
61198398Srdivacky  public:
62198398Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT)
63198398Srdivacky#define TYPELOC(CLASS, PARENT) \
64198398Srdivacky    TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
65198398Srdivacky      return TyLoc.getNextTypeLoc(); \
66198398Srdivacky    }
67198092Srdivacky#include "clang/AST/TypeLocNodes.def"
68198398Srdivacky  };
69198092Srdivacky}
70198092Srdivacky
71198092Srdivacky/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
72198092Srdivacky/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
73198398SrdivackyTypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
74198398Srdivacky  return NextLoc().Visit(TL);
75198092Srdivacky}
76198092Srdivacky
77198398Srdivacky/// \brief Initializes a type location, and all of its children
78198398Srdivacky/// recursively, as if the entire tree had been written in the
79198398Srdivacky/// given location.
80218893Sdimvoid TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
81218893Sdim                             SourceLocation Loc) {
82208600Srdivacky  while (true) {
83208600Srdivacky    switch (TL.getTypeLocClass()) {
84208600Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT)
85208600Srdivacky#define TYPELOC(CLASS, PARENT)        \
86208600Srdivacky    case CLASS: {                     \
87208600Srdivacky      CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
88218893Sdim      TLCasted.initializeLocal(Context, Loc);  \
89208600Srdivacky      TL = TLCasted.getNextTypeLoc(); \
90208600Srdivacky      if (!TL) return;                \
91208600Srdivacky      continue;                       \
92208600Srdivacky    }
93208600Srdivacky#include "clang/AST/TypeLocNodes.def"
94208600Srdivacky    }
95208600Srdivacky  }
96198092Srdivacky}
97200583Srdivacky
98208600SrdivackySourceLocation TypeLoc::getBeginLoc() const {
99208600Srdivacky  TypeLoc Cur = *this;
100208600Srdivacky  while (true) {
101208600Srdivacky    switch (Cur.getTypeLocClass()) {
102208600Srdivacky    // FIXME: Currently QualifiedTypeLoc does not have a source range
103208600Srdivacky    // case Qualified:
104208600Srdivacky    case Elaborated:
105208600Srdivacky      break;
106208600Srdivacky    default:
107208600Srdivacky      TypeLoc Next = Cur.getNextTypeLoc();
108208600Srdivacky      if (Next.isNull()) break;
109208600Srdivacky      Cur = Next;
110208600Srdivacky      continue;
111208600Srdivacky    }
112208600Srdivacky    break;
113208600Srdivacky  }
114208600Srdivacky  return Cur.getLocalSourceRange().getBegin();
115208600Srdivacky}
116208600Srdivacky
117208600SrdivackySourceLocation TypeLoc::getEndLoc() const {
118208600Srdivacky  TypeLoc Cur = *this;
119208600Srdivacky  while (true) {
120208600Srdivacky    switch (Cur.getTypeLocClass()) {
121208600Srdivacky    default:
122208600Srdivacky      break;
123208600Srdivacky    case Qualified:
124208600Srdivacky    case Elaborated:
125208600Srdivacky      Cur = Cur.getNextTypeLoc();
126208600Srdivacky      continue;
127208600Srdivacky    }
128208600Srdivacky    break;
129208600Srdivacky  }
130208600Srdivacky  return Cur.getLocalSourceRange().getEnd();
131208600Srdivacky}
132208600Srdivacky
133208600Srdivacky
134200583Srdivackynamespace {
135200583Srdivacky  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
136200583Srdivacky    // Overload resolution does the real work for us.
137200583Srdivacky    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
138200583Srdivacky    static bool isTypeSpec(TypeLoc _) { return false; }
139200583Srdivacky
140200583Srdivacky#define ABSTRACT_TYPELOC(CLASS, PARENT)
141200583Srdivacky#define TYPELOC(CLASS, PARENT) \
142200583Srdivacky    bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
143200583Srdivacky      return isTypeSpec(TyLoc); \
144200583Srdivacky    }
145200583Srdivacky#include "clang/AST/TypeLocNodes.def"
146200583Srdivacky  };
147200583Srdivacky}
148200583Srdivacky
149200583Srdivacky
150200583Srdivacky/// \brief Determines if the given type loc corresponds to a
151200583Srdivacky/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
152200583Srdivacky/// the type hierarchy, this is made somewhat complicated.
153200583Srdivacky///
154200583Srdivacky/// There are a lot of types that currently use TypeSpecTypeLoc
155200583Srdivacky/// because it's a convenient base class.  Ideally we would not accept
156200583Srdivacky/// those here, but ideally we would have better implementations for
157200583Srdivacky/// them.
158200583Srdivackybool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
159200583Srdivacky  if (TL->getType().hasLocalQualifiers()) return false;
160200583Srdivacky  return TSTChecker().Visit(*TL);
161200583Srdivacky}
162202379Srdivacky
163202379Srdivacky// Reimplemented to account for GNU/C++ extension
164202379Srdivacky//     typeof unary-expression
165202379Srdivacky// where there are no parentheses.
166208600SrdivackySourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
167202379Srdivacky  if (getRParenLoc().isValid())
168202379Srdivacky    return SourceRange(getTypeofLoc(), getRParenLoc());
169202379Srdivacky  else
170202379Srdivacky    return SourceRange(getTypeofLoc(),
171202379Srdivacky                       getUnderlyingExpr()->getSourceRange().getEnd());
172202379Srdivacky}
173202879Srdivacky
174202879Srdivacky
175202879SrdivackyTypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
176202879Srdivacky  if (needsExtraLocalData())
177202879Srdivacky    return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
178202879Srdivacky  else {
179202879Srdivacky    switch (getTypePtr()->getKind()) {
180202879Srdivacky    case BuiltinType::Void:
181202879Srdivacky      return TST_void;
182202879Srdivacky    case BuiltinType::Bool:
183202879Srdivacky      return TST_bool;
184202879Srdivacky    case BuiltinType::Char_U:
185202879Srdivacky    case BuiltinType::Char_S:
186202879Srdivacky      return TST_char;
187202879Srdivacky    case BuiltinType::Char16:
188202879Srdivacky      return TST_char16;
189202879Srdivacky    case BuiltinType::Char32:
190202879Srdivacky      return TST_char32;
191218893Sdim    case BuiltinType::WChar_S:
192218893Sdim    case BuiltinType::WChar_U:
193202879Srdivacky      return TST_wchar;
194218893Sdim
195202879Srdivacky    case BuiltinType::UChar:
196202879Srdivacky    case BuiltinType::UShort:
197202879Srdivacky    case BuiltinType::UInt:
198202879Srdivacky    case BuiltinType::ULong:
199202879Srdivacky    case BuiltinType::ULongLong:
200202879Srdivacky    case BuiltinType::UInt128:
201202879Srdivacky    case BuiltinType::SChar:
202202879Srdivacky    case BuiltinType::Short:
203202879Srdivacky    case BuiltinType::Int:
204202879Srdivacky    case BuiltinType::Long:
205202879Srdivacky    case BuiltinType::LongLong:
206202879Srdivacky    case BuiltinType::Int128:
207202879Srdivacky    case BuiltinType::Float:
208202879Srdivacky    case BuiltinType::Double:
209202879Srdivacky    case BuiltinType::LongDouble:
210202879Srdivacky      llvm_unreachable("Builtin type needs extra local data!");
211202879Srdivacky      // Fall through, if the impossible happens.
212202879Srdivacky
213202879Srdivacky    case BuiltinType::NullPtr:
214202879Srdivacky    case BuiltinType::Overload:
215202879Srdivacky    case BuiltinType::Dependent:
216202879Srdivacky    case BuiltinType::ObjCId:
217202879Srdivacky    case BuiltinType::ObjCClass:
218202879Srdivacky    case BuiltinType::ObjCSel:
219202879Srdivacky      return TST_unspecified;
220202879Srdivacky    }
221202879Srdivacky  }
222202879Srdivacky
223202879Srdivacky  return TST_unspecified;
224202879Srdivacky}
225218893Sdim
226218893SdimTypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
227218893Sdim  while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
228218893Sdim    TL = PTL->getInnerLoc();
229218893Sdim  return TL;
230218893Sdim}
231218893Sdim
232218893Sdimvoid TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
233218893Sdim                                                      unsigned NumArgs,
234218893Sdim                                                  const TemplateArgument *Args,
235218893Sdim                                              TemplateArgumentLocInfo *ArgInfos,
236218893Sdim                                                      SourceLocation Loc) {
237218893Sdim  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
238218893Sdim    switch (Args[i].getKind()) {
239218893Sdim    case TemplateArgument::Null:
240218893Sdim    case TemplateArgument::Declaration:
241218893Sdim    case TemplateArgument::Integral:
242218893Sdim    case TemplateArgument::Pack:
243218893Sdim    case TemplateArgument::Expression:
244218893Sdim      // FIXME: Can we do better for declarations and integral values?
245218893Sdim      ArgInfos[i] = TemplateArgumentLocInfo();
246218893Sdim      break;
247218893Sdim
248218893Sdim    case TemplateArgument::Type:
249218893Sdim      ArgInfos[i] = TemplateArgumentLocInfo(
250218893Sdim                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
251218893Sdim                                                           Loc));
252218893Sdim      break;
253218893Sdim
254218893Sdim    case TemplateArgument::Template:
255218893Sdim      ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc,
256218893Sdim                                            SourceLocation());
257218893Sdim      break;
258218893Sdim
259218893Sdim    case TemplateArgument::TemplateExpansion:
260218893Sdim      ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc);
261218893Sdim      break;
262218893Sdim    }
263218893Sdim  }
264218893Sdim}
265218893Sdim
266