TypeLoc.cpp revision 55fc873017f10f6f566b182b70f6fc22aefa3464
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::BuiltinFn:
266    return TST_unspecified;
267  }
268
269  llvm_unreachable("Invalid BuiltinType Kind!");
270}
271
272TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
273  while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
274    TL = PTL->getInnerLoc();
275  return TL;
276}
277
278void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
279                                        SourceLocation Loc) {
280  setElaboratedKeywordLoc(Loc);
281  NestedNameSpecifierLocBuilder Builder;
282  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
283  setQualifierLoc(Builder.getWithLocInContext(Context));
284}
285
286void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
287                                           SourceLocation Loc) {
288  setElaboratedKeywordLoc(Loc);
289  NestedNameSpecifierLocBuilder Builder;
290  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
291  setQualifierLoc(Builder.getWithLocInContext(Context));
292  setNameLoc(Loc);
293}
294
295void
296DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
297                                                        SourceLocation Loc) {
298  setElaboratedKeywordLoc(Loc);
299  if (getTypePtr()->getQualifier()) {
300    NestedNameSpecifierLocBuilder Builder;
301    Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
302    setQualifierLoc(Builder.getWithLocInContext(Context));
303  } else {
304    setQualifierLoc(NestedNameSpecifierLoc());
305  }
306  setTemplateKeywordLoc(Loc);
307  setTemplateNameLoc(Loc);
308  setLAngleLoc(Loc);
309  setRAngleLoc(Loc);
310  TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
311                                                   getTypePtr()->getArgs(),
312                                                   getArgInfos(), Loc);
313}
314
315void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
316                                                      unsigned NumArgs,
317                                                  const TemplateArgument *Args,
318                                              TemplateArgumentLocInfo *ArgInfos,
319                                                      SourceLocation Loc) {
320  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
321    switch (Args[i].getKind()) {
322    case TemplateArgument::Null:
323    case TemplateArgument::Declaration:
324    case TemplateArgument::Integral:
325    case TemplateArgument::NullPtr:
326      llvm_unreachable("Impossible TemplateArgument");
327
328    case TemplateArgument::Expression:
329      ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
330      break;
331
332    case TemplateArgument::Type:
333      ArgInfos[i] = TemplateArgumentLocInfo(
334                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
335                                                           Loc));
336      break;
337
338    case TemplateArgument::Template:
339    case TemplateArgument::TemplateExpansion: {
340      NestedNameSpecifierLocBuilder Builder;
341      TemplateName Template = Args[i].getAsTemplate();
342      if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
343        Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
344      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
345        Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
346
347      ArgInfos[i] = TemplateArgumentLocInfo(
348                                           Builder.getWithLocInContext(Context),
349                                            Loc,
350                                Args[i].getKind() == TemplateArgument::Template
351                                            ? SourceLocation()
352                                            : Loc);
353      break;
354    }
355
356    case TemplateArgument::Pack:
357      ArgInfos[i] = TemplateArgumentLocInfo();
358      break;
359    }
360  }
361}
362