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