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