TypeLoc.cpp revision b6744efecba58792cce20d2d7b9ee39927c5422e
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  while (true) {
122    switch (Cur.getTypeLocClass()) {
123    default:
124      break;
125    case Qualified:
126    case Elaborated:
127      Cur = Cur.getNextTypeLoc();
128      continue;
129    }
130    break;
131  }
132  return Cur.getLocalSourceRange().getEnd();
133}
134
135
136namespace {
137  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
138    // Overload resolution does the real work for us.
139    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
140    static bool isTypeSpec(TypeLoc _) { return false; }
141
142#define ABSTRACT_TYPELOC(CLASS, PARENT)
143#define TYPELOC(CLASS, PARENT) \
144    bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
145      return isTypeSpec(TyLoc); \
146    }
147#include "clang/AST/TypeLocNodes.def"
148  };
149}
150
151
152/// \brief Determines if the given type loc corresponds to a
153/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
154/// the type hierarchy, this is made somewhat complicated.
155///
156/// There are a lot of types that currently use TypeSpecTypeLoc
157/// because it's a convenient base class.  Ideally we would not accept
158/// those here, but ideally we would have better implementations for
159/// them.
160bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
161  if (TL->getType().hasLocalQualifiers()) return false;
162  return TSTChecker().Visit(*TL);
163}
164
165// Reimplemented to account for GNU/C++ extension
166//     typeof unary-expression
167// where there are no parentheses.
168SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
169  if (getRParenLoc().isValid())
170    return SourceRange(getTypeofLoc(), getRParenLoc());
171  else
172    return SourceRange(getTypeofLoc(),
173                       getUnderlyingExpr()->getSourceRange().getEnd());
174}
175
176
177TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
178  if (needsExtraLocalData())
179    return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
180  else {
181    switch (getTypePtr()->getKind()) {
182    case BuiltinType::Void:
183      return TST_void;
184    case BuiltinType::Bool:
185      return TST_bool;
186    case BuiltinType::Char_U:
187    case BuiltinType::Char_S:
188      return TST_char;
189    case BuiltinType::Char16:
190      return TST_char16;
191    case BuiltinType::Char32:
192      return TST_char32;
193    case BuiltinType::WChar_S:
194    case BuiltinType::WChar_U:
195      return TST_wchar;
196
197    case BuiltinType::UChar:
198    case BuiltinType::UShort:
199    case BuiltinType::UInt:
200    case BuiltinType::ULong:
201    case BuiltinType::ULongLong:
202    case BuiltinType::UInt128:
203    case BuiltinType::SChar:
204    case BuiltinType::Short:
205    case BuiltinType::Int:
206    case BuiltinType::Long:
207    case BuiltinType::LongLong:
208    case BuiltinType::Int128:
209    case BuiltinType::Float:
210    case BuiltinType::Double:
211    case BuiltinType::LongDouble:
212      llvm_unreachable("Builtin type needs extra local data!");
213      // Fall through, if the impossible happens.
214
215    case BuiltinType::NullPtr:
216    case BuiltinType::Overload:
217    case BuiltinType::Dependent:
218    case BuiltinType::ObjCId:
219    case BuiltinType::ObjCClass:
220    case BuiltinType::ObjCSel:
221      return TST_unspecified;
222    }
223  }
224
225  return TST_unspecified;
226}
227
228TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
229  while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
230    TL = PTL->getInnerLoc();
231  return TL;
232}
233
234void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
235                                        SourceLocation Loc) {
236  setKeywordLoc(Loc);
237  NestedNameSpecifierLocBuilder Builder;
238  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
239  setQualifierLoc(Builder.getWithLocInContext(Context));
240}
241
242void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
243                                           SourceLocation Loc) {
244  setKeywordLoc(Loc);
245  NestedNameSpecifierLocBuilder Builder;
246  Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
247  setQualifierLoc(Builder.getWithLocInContext(Context));
248  setNameLoc(Loc);
249}
250
251void
252DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
253                                                        SourceLocation Loc) {
254  setKeywordLoc(Loc);
255  if (getTypePtr()->getQualifier()) {
256    NestedNameSpecifierLocBuilder Builder;
257    Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
258    setQualifierLoc(Builder.getWithLocInContext(Context));
259  } else {
260    setQualifierLoc(NestedNameSpecifierLoc());
261  }
262
263  setNameLoc(Loc);
264  setLAngleLoc(Loc);
265  setRAngleLoc(Loc);
266  TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
267                                                   getTypePtr()->getArgs(),
268                                                   getArgInfos(), Loc);
269}
270
271void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
272                                                      unsigned NumArgs,
273                                                  const TemplateArgument *Args,
274                                              TemplateArgumentLocInfo *ArgInfos,
275                                                      SourceLocation Loc) {
276  for (unsigned i = 0, e = NumArgs; i != e; ++i) {
277    switch (Args[i].getKind()) {
278    case TemplateArgument::Null:
279    case TemplateArgument::Declaration:
280    case TemplateArgument::Integral:
281    case TemplateArgument::Pack:
282    case TemplateArgument::Expression:
283      // FIXME: Can we do better for declarations and integral values?
284      ArgInfos[i] = TemplateArgumentLocInfo();
285      break;
286
287    case TemplateArgument::Type:
288      ArgInfos[i] = TemplateArgumentLocInfo(
289                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
290                                                           Loc));
291      break;
292
293    case TemplateArgument::Template:
294    case TemplateArgument::TemplateExpansion: {
295      NestedNameSpecifierLocBuilder Builder;
296      TemplateName Template = Args[i].getAsTemplate();
297      if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
298        Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
299      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
300        Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
301
302      ArgInfos[i] = TemplateArgumentLocInfo(
303                                           Builder.getWithLocInContext(Context),
304                                            Loc,
305                                Args[i].getKind() == TemplateArgument::Template
306                                            ? SourceLocation()
307                                            : Loc);
308      break;
309    }
310    }
311  }
312}
313
314