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