TypeLoc.cpp revision b13621d08e20ac7aa550e05896de8a57ee99c1e8
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 = cast<CLASS##TypeLoc>(TL); \
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 (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) {
110        LeftMost = Cur;
111        break;
112      }
113      /* Fall through */
114    case FunctionNoProto:
115    case ConstantArray:
116    case DependentSizedArray:
117    case IncompleteArray:
118    case VariableArray:
119      // FIXME: Currently QualifiedTypeLoc does not have a source range
120    case Qualified:
121      Cur = Cur.getNextTypeLoc();
122      continue;
123    default:
124      if (!Cur.getLocalSourceRange().getBegin().isInvalid())
125        LeftMost = Cur;
126      Cur = Cur.getNextTypeLoc();
127      if (Cur.isNull())
128        break;
129      continue;
130    } // switch
131    break;
132  } // while
133  return LeftMost.getLocalSourceRange().getBegin();
134}
135
136SourceLocation TypeLoc::getEndLoc() const {
137  TypeLoc Cur = *this;
138  TypeLoc Last;
139  while (true) {
140    switch (Cur.getTypeLocClass()) {
141    default:
142      if (!Last)
143	Last = Cur;
144      return Last.getLocalSourceRange().getEnd();
145    case Paren:
146    case ConstantArray:
147    case DependentSizedArray:
148    case IncompleteArray:
149    case VariableArray:
150    case FunctionNoProto:
151      Last = Cur;
152      break;
153    case FunctionProto:
154      if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn())
155        Last = TypeLoc();
156      else
157        Last = Cur;
158      break;
159    case Pointer:
160    case BlockPointer:
161    case MemberPointer:
162    case LValueReference:
163    case RValueReference:
164    case PackExpansion:
165      if (!Last)
166	Last = Cur;
167      break;
168    case Qualified:
169    case Elaborated:
170      break;
171    }
172    Cur = Cur.getNextTypeLoc();
173  }
174}
175
176
177namespace {
178  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
179    // Overload resolution does the real work for us.
180    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
181    static bool isTypeSpec(TypeLoc _) { return false; }
182
183#define ABSTRACT_TYPELOC(CLASS, PARENT)
184#define TYPELOC(CLASS, PARENT) \
185    bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
186      return isTypeSpec(TyLoc); \
187    }
188#include "clang/AST/TypeLocNodes.def"
189  };
190}
191
192
193/// \brief Determines if the given type loc corresponds to a
194/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
195/// the type hierarchy, this is made somewhat complicated.
196///
197/// There are a lot of types that currently use TypeSpecTypeLoc
198/// because it's a convenient base class.  Ideally we would not accept
199/// those here, but ideally we would have better implementations for
200/// them.
201bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
202  if (TL->getType().hasLocalQualifiers()) return false;
203  return TSTChecker().Visit(*TL);
204}
205
206// Reimplemented to account for GNU/C++ extension
207//     typeof unary-expression
208// where there are no parentheses.
209SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
210  if (getRParenLoc().isValid())
211    return SourceRange(getTypeofLoc(), getRParenLoc());
212  else
213    return SourceRange(getTypeofLoc(),
214                       getUnderlyingExpr()->getSourceRange().getEnd());
215}
216
217
218TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
219  if (needsExtraLocalData())
220    return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
221  switch (getTypePtr()->getKind()) {
222  case BuiltinType::Void:
223    return TST_void;
224  case BuiltinType::Bool:
225    return TST_bool;
226  case BuiltinType::Char_U:
227  case BuiltinType::Char_S:
228    return TST_char;
229  case BuiltinType::Char16:
230    return TST_char16;
231  case BuiltinType::Char32:
232    return TST_char32;
233  case BuiltinType::WChar_S:
234  case BuiltinType::WChar_U:
235    return TST_wchar;
236  case BuiltinType::UChar:
237  case BuiltinType::UShort:
238  case BuiltinType::UInt:
239  case BuiltinType::ULong:
240  case BuiltinType::ULongLong:
241  case BuiltinType::UInt128:
242  case BuiltinType::SChar:
243  case BuiltinType::Short:
244  case BuiltinType::Int:
245  case BuiltinType::Long:
246  case BuiltinType::LongLong:
247  case BuiltinType::Int128:
248  case BuiltinType::Half:
249  case BuiltinType::Float:
250  case BuiltinType::Double:
251  case BuiltinType::LongDouble:
252    llvm_unreachable("Builtin type needs extra local data!");
253    // Fall through, if the impossible happens.
254
255  case BuiltinType::NullPtr:
256  case BuiltinType::Overload:
257  case BuiltinType::Dependent:
258  case BuiltinType::BoundMember:
259  case BuiltinType::UnknownAny:
260  case BuiltinType::ARCUnbridgedCast:
261  case BuiltinType::PseudoObject:
262  case BuiltinType::ObjCId:
263  case BuiltinType::ObjCClass:
264  case BuiltinType::ObjCSel:
265  case BuiltinType::OCLImage1d:
266  case BuiltinType::OCLImage1dArray:
267  case BuiltinType::OCLImage1dBuffer:
268  case BuiltinType::OCLImage2d:
269  case BuiltinType::OCLImage2dArray:
270  case BuiltinType::OCLImage3d:
271  case BuiltinType::BuiltinFn:
272    return TST_unspecified;
273  }
274
275  llvm_unreachable("Invalid BuiltinType Kind!");
276}
277
278TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
279  while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
280    TL = PTL->getInnerLoc();
281  return TL;
282}
283
284void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
285                                        SourceLocation Loc) {
286  setElaboratedKeywordLoc(Loc);
287  NestedNameSpecifierLocBuilder Builder;
288  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
289  setQualifierLoc(Builder.getWithLocInContext(Context));
290}
291
292void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
293                                           SourceLocation Loc) {
294  setElaboratedKeywordLoc(Loc);
295  NestedNameSpecifierLocBuilder Builder;
296  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
297  setQualifierLoc(Builder.getWithLocInContext(Context));
298  setNameLoc(Loc);
299}
300
301void
302DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
303                                                        SourceLocation Loc) {
304  setElaboratedKeywordLoc(Loc);
305  if (getTypePtr()->getQualifier()) {
306    NestedNameSpecifierLocBuilder Builder;
307    Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
308    setQualifierLoc(Builder.getWithLocInContext(Context));
309  } else {
310    setQualifierLoc(NestedNameSpecifierLoc());
311  }
312  setTemplateKeywordLoc(Loc);
313  setTemplateNameLoc(Loc);
314  setLAngleLoc(Loc);
315  setRAngleLoc(Loc);
316  TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
317                                                   getTypePtr()->getArgs(),
318                                                   getArgInfos(), Loc);
319}
320
321void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
322                                                      unsigned NumArgs,
323                                                  const TemplateArgument *Args,
324                                              TemplateArgumentLocInfo *ArgInfos,
325                                                      SourceLocation Loc) {
326  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
327    switch (Args[i].getKind()) {
328    case TemplateArgument::Null:
329    case TemplateArgument::Declaration:
330    case TemplateArgument::Integral:
331    case TemplateArgument::NullPtr:
332      llvm_unreachable("Impossible TemplateArgument");
333
334    case TemplateArgument::Expression:
335      ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
336      break;
337
338    case TemplateArgument::Type:
339      ArgInfos[i] = TemplateArgumentLocInfo(
340                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
341                                                           Loc));
342      break;
343
344    case TemplateArgument::Template:
345    case TemplateArgument::TemplateExpansion: {
346      NestedNameSpecifierLocBuilder Builder;
347      TemplateName Template = Args[i].getAsTemplate();
348      if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
349        Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
350      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
351        Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
352
353      ArgInfos[i] = TemplateArgumentLocInfo(
354                                           Builder.getWithLocInContext(Context),
355                                            Loc,
356                                Args[i].getKind() == TemplateArgument::Template
357                                            ? SourceLocation()
358                                            : Loc);
359      break;
360    }
361
362    case TemplateArgument::Pack:
363      ArgInfos[i] = TemplateArgumentLocInfo();
364      break;
365    }
366  }
367}
368