CanonicalType.h revision b7efff4bae117604f442bb6859c844f90b15f3ff
1//===-- CanonicalType.h - C Language Family Type Representation -*- 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 CanQual class template, which provides access to
11//  canonical types.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H
16#define LLVM_CLANG_AST_CANONICAL_TYPE_H
17
18#include "clang/AST/Type.h"
19#include "llvm/Support/Casting.h"
20#include "llvm/Support/type_traits.h"
21#include <iterator>
22
23namespace clang {
24
25template<typename T> class CanProxy;
26template<typename T> struct CanProxyAdaptor;
27
28//----------------------------------------------------------------------------//
29// Canonical, qualified type template
30//----------------------------------------------------------------------------//
31
32/// \brief Represents a canonical, potentially-qualified type.
33///
34/// The CanQual template is a lightweight smart pointer that provides access
35/// to the canonical representation of a type, where all typedefs and other
36/// syntactic sugar has been eliminated. A CanQualType may also have various
37/// qualifiers (const, volatile, restrict) attached to it.
38///
39/// The template type parameter @p T is one of the Type classes (PointerType,
40/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that
41/// type (or some subclass of that type). The typedef @c CanQualType is just
42/// a shorthand for @c CanQual<Type>.
43///
44/// An instance of @c CanQual<T> can be implicitly converted to a
45/// @c CanQual<U> when T is derived from U, which essentially provides an
46/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be
47/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
48/// be implicitly converted to a QualType, but the reverse operation requires
49/// a call to ASTContext::getCanonicalType().
50///
51///
52template<typename T = Type>
53class CanQual {
54  /// \brief The actual, canonical type.
55  QualType Stored;
56
57public:
58  /// \brief Constructs a NULL canonical type.
59  CanQual() : Stored() { }
60
61  /// \brief Converting constructor that permits implicit upcasting of
62  /// canonical type pointers.
63  template<typename U>
64  CanQual(const CanQual<U>& Other,
65          typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
66
67  /// \brief Retrieve the underlying type pointer, which refers to a
68  /// canonical type.
69  ///
70  /// The underlying pointer must not be NULL.
71  const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
72
73  /// \brief Retrieve the underlying type pointer, which refers to a
74  /// canonical type, or NULL.
75  ///
76  const T *getTypePtrOrNull() const {
77    return cast_or_null<T>(Stored.getTypePtrOrNull());
78  }
79
80  /// \brief Implicit conversion to a qualified type.
81  operator QualType() const { return Stored; }
82
83  /// \brief Implicit conversion to bool.
84  operator bool() const { return !isNull(); }
85
86  bool isNull() const {
87    return Stored.isNull();
88  }
89
90  SplitQualType split() const { return Stored.split(); }
91
92  /// \brief Retrieve a canonical type pointer with a different static type,
93  /// upcasting or downcasting as needed.
94  ///
95  /// The getAs() function is typically used to try to downcast to a
96  /// more specific (canonical) type in the type system. For example:
97  ///
98  /// @code
99  /// void f(CanQual<Type> T) {
100  ///   if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) {
101  ///     // look at Ptr's pointee type
102  ///   }
103  /// }
104  /// @endcode
105  ///
106  /// \returns A proxy pointer to the same type, but with the specified
107  /// static type (@p U). If the dynamic type is not the specified static type
108  /// or a derived class thereof, a NULL canonical type.
109  template<typename U> CanProxy<U> getAs() const;
110
111  /// \brief Overloaded arrow operator that produces a canonical type
112  /// proxy.
113  CanProxy<T> operator->() const;
114
115  /// \brief Retrieve all qualifiers.
116  Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
117
118  /// \brief Retrieve the const/volatile/restrict qualifiers.
119  unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
120
121  /// \brief Determines whether this type has any qualifiers
122  bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
123
124  bool isConstQualified() const {
125    return Stored.isLocalConstQualified();
126  }
127  bool isVolatileQualified() const {
128    return Stored.isLocalVolatileQualified();
129  }
130  bool isRestrictQualified() const {
131    return Stored.isLocalRestrictQualified();
132  }
133
134  /// \brief Determines if this canonical type is furthermore
135  /// canonical as a parameter.  The parameter-canonicalization
136  /// process decays arrays to pointers and drops top-level qualifiers.
137  bool isCanonicalAsParam() const {
138    return Stored.isCanonicalAsParam();
139  }
140
141  /// \brief Retrieve the unqualified form of this type.
142  CanQual<T> getUnqualifiedType() const;
143
144  /// \brief Retrieves a version of this type with const applied.
145  /// Note that this does not always yield a canonical type.
146  QualType withConst() const {
147    return Stored.withConst();
148  }
149
150  /// \brief Determines whether this canonical type is more qualified than
151  /// the @p Other canonical type.
152  bool isMoreQualifiedThan(CanQual<T> Other) const {
153    return Stored.isMoreQualifiedThan(Other.Stored);
154  }
155
156  /// \brief Determines whether this canonical type is at least as qualified as
157  /// the @p Other canonical type.
158  bool isAtLeastAsQualifiedAs(CanQual<T> Other) const {
159    return Stored.isAtLeastAsQualifiedAs(Other.Stored);
160  }
161
162  /// \brief If the canonical type is a reference type, returns the type that
163  /// it refers to; otherwise, returns the type itself.
164  CanQual<Type> getNonReferenceType() const;
165
166  /// \brief Retrieve the internal representation of this canonical type.
167  void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
168
169  /// \brief Construct a canonical type from its internal representation.
170  static CanQual<T> getFromOpaquePtr(void *Ptr);
171
172  /// \brief Builds a canonical type from a QualType.
173  ///
174  /// This routine is inherently unsafe, because it requires the user to
175  /// ensure that the given type is a canonical type with the correct
176  // (dynamic) type.
177  static CanQual<T> CreateUnsafe(QualType Other);
178
179  void dump() const { Stored.dump(); }
180
181  void Profile(llvm::FoldingSetNodeID &ID) const {
182    ID.AddPointer(getAsOpaquePtr());
183  }
184};
185
186template<typename T, typename U>
187inline bool operator==(CanQual<T> x, CanQual<U> y) {
188  return x.getAsOpaquePtr() == y.getAsOpaquePtr();
189}
190
191template<typename T, typename U>
192inline bool operator!=(CanQual<T> x, CanQual<U> y) {
193  return x.getAsOpaquePtr() != y.getAsOpaquePtr();
194}
195
196/// \brief Represents a canonical, potentially-qualified type.
197typedef CanQual<Type> CanQualType;
198
199inline CanQualType Type::getCanonicalTypeUnqualified() const {
200  return CanQualType::CreateUnsafe(getCanonicalTypeInternal());
201}
202
203inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
204                                           CanQualType T) {
205  DB << static_cast<QualType>(T);
206  return DB;
207}
208
209//----------------------------------------------------------------------------//
210// Internal proxy classes used by canonical types
211//----------------------------------------------------------------------------//
212
213#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor)                    \
214CanQualType Accessor() const {                                           \
215return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor());      \
216}
217
218#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor)             \
219Type Accessor() const { return this->getTypePtr()->Accessor(); }
220
221/// \brief Base class of all canonical proxy types, which is responsible for
222/// storing the underlying canonical type and providing basic conversions.
223template<typename T>
224class CanProxyBase {
225protected:
226  CanQual<T> Stored;
227
228public:
229  /// \brief Retrieve the pointer to the underlying Type
230  const T *getTypePtr() const { return Stored.getTypePtr(); }
231
232  /// \brief Implicit conversion to the underlying pointer.
233  ///
234  /// Also provides the ability to use canonical type proxies in a Boolean
235  // context,e.g.,
236  /// @code
237  ///   if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
238  /// @endcode
239  operator const T*() const { return this->Stored.getTypePtrOrNull(); }
240
241  /// \brief Try to convert the given canonical type to a specific structural
242  /// type.
243  template<typename U> CanProxy<U> getAs() const {
244    return this->Stored.template getAs<U>();
245  }
246
247  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass)
248
249  // Type predicates
250  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
251  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
252  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
253  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType)
254  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
255  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
256  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
257  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType)
258  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType)
259  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType)
260  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType)
261  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType)
262  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType)
263  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType)
264  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType)
265  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType)
266  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType)
267  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType)
268  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType)
269  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType)
270  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType)
271  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType)
272  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType)
273  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType)
274  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType)
275  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
276  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
277  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
278  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType)
279  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
280  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
281  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType)
282  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
283  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
284  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
285  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
286  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
287  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
288  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
289  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
290  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
291  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
292  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
293  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
294  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
295  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
296
297  /// \brief Retrieve the proxy-adaptor type.
298  ///
299  /// This arrow operator is used when CanProxyAdaptor has been specialized
300  /// for the given type T. In that case, we reference members of the
301  /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden
302  /// by the arrow operator in the primary CanProxyAdaptor template.
303  const CanProxyAdaptor<T> *operator->() const {
304    return static_cast<const CanProxyAdaptor<T> *>(this);
305  }
306};
307
308/// \brief Replacable canonical proxy adaptor class that provides the link
309/// between a canonical type and the accessors of the type.
310///
311/// The CanProxyAdaptor is a replaceable class template that is instantiated
312/// as part of each canonical proxy type. The primary template merely provides
313/// redirection to the underlying type (T), e.g., @c PointerType. One can
314/// provide specializations of this class template for each underlying type
315/// that provide accessors returning canonical types (@c CanQualType) rather
316/// than the more typical @c QualType, to propagate the notion of "canonical"
317/// through the system.
318template<typename T>
319struct CanProxyAdaptor : CanProxyBase<T> { };
320
321/// \brief Canonical proxy type returned when retrieving the members of a
322/// canonical type or as the result of the @c CanQual<T>::getAs member
323/// function.
324///
325/// The CanProxy type mainly exists as a proxy through which operator-> will
326/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy
327/// type that provides canonical-type access to the fields of the type.
328template<typename T>
329class CanProxy : public CanProxyAdaptor<T> {
330public:
331  /// \brief Build a NULL proxy.
332  CanProxy() { }
333
334  /// \brief Build a proxy to the given canonical type.
335  CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
336
337  /// \brief Implicit conversion to the stored canonical type.
338  operator CanQual<T>() const { return this->Stored; }
339};
340
341} // end namespace clang
342
343namespace llvm {
344
345/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from
346/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
347/// to return smart pointer (proxies?).
348template<typename T>
349struct simplify_type<const ::clang::CanQual<T> > {
350  typedef const T *SimpleType;
351  static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
352    return Val.getTypePtr();
353  }
354};
355template<typename T>
356struct simplify_type< ::clang::CanQual<T> >
357: public simplify_type<const ::clang::CanQual<T> > {};
358
359// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
360template<typename T>
361class PointerLikeTypeTraits<clang::CanQual<T> > {
362public:
363  static inline void *getAsVoidPointer(clang::CanQual<T> P) {
364    return P.getAsOpaquePtr();
365  }
366  static inline clang::CanQual<T> getFromVoidPointer(void *P) {
367    return clang::CanQual<T>::getFromOpaquePtr(P);
368  }
369  // qualifier information is encoded in the low bits.
370  enum { NumLowBitsAvailable = 0 };
371};
372
373} // end namespace llvm
374
375namespace clang {
376
377//----------------------------------------------------------------------------//
378// Canonical proxy adaptors for canonical type nodes.
379//----------------------------------------------------------------------------//
380
381/// \brief Iterator adaptor that turns an iterator over canonical QualTypes
382/// into an iterator over CanQualTypes.
383template<typename InputIterator>
384class CanTypeIterator {
385  InputIterator Iter;
386
387public:
388  typedef CanQualType    value_type;
389  typedef value_type     reference;
390  typedef CanProxy<Type> pointer;
391  typedef typename std::iterator_traits<InputIterator>::difference_type
392    difference_type;
393  typedef typename std::iterator_traits<InputIterator>::iterator_category
394    iterator_category;
395
396  CanTypeIterator() : Iter() { }
397  explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { }
398
399  // Input iterator
400  reference operator*() const {
401    return CanQualType::CreateUnsafe(*Iter);
402  }
403
404  pointer operator->() const;
405
406  CanTypeIterator &operator++() {
407    ++Iter;
408    return *this;
409  }
410
411  CanTypeIterator operator++(int) {
412    CanTypeIterator Tmp(*this);
413    ++Iter;
414    return Tmp;
415  }
416
417  friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) {
418    return X.Iter == Y.Iter;
419  }
420  friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) {
421    return X.Iter != Y.Iter;
422  }
423
424  // Bidirectional iterator
425  CanTypeIterator &operator--() {
426    --Iter;
427    return *this;
428  }
429
430  CanTypeIterator operator--(int) {
431    CanTypeIterator Tmp(*this);
432    --Iter;
433    return Tmp;
434  }
435
436  // Random access iterator
437  reference operator[](difference_type n) const {
438    return CanQualType::CreateUnsafe(Iter[n]);
439  }
440
441  CanTypeIterator &operator+=(difference_type n) {
442    Iter += n;
443    return *this;
444  }
445
446  CanTypeIterator &operator-=(difference_type n) {
447    Iter -= n;
448    return *this;
449  }
450
451  friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) {
452    X += n;
453    return X;
454  }
455
456  friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) {
457    X += n;
458    return X;
459  }
460
461  friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) {
462    X -= n;
463    return X;
464  }
465
466  friend difference_type operator-(const CanTypeIterator &X,
467                                   const CanTypeIterator &Y) {
468    return X - Y;
469  }
470};
471
472template<>
473struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
474  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
475};
476
477template<>
478struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {
479  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
480};
481
482template<>
483struct CanProxyAdaptor<BlockPointerType>
484  : public CanProxyBase<BlockPointerType> {
485  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
486};
487
488template<>
489struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {
490  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
491};
492
493template<>
494struct CanProxyAdaptor<LValueReferenceType>
495  : public CanProxyBase<LValueReferenceType> {
496  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
497};
498
499template<>
500struct CanProxyAdaptor<RValueReferenceType>
501  : public CanProxyBase<RValueReferenceType> {
502  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
503};
504
505template<>
506struct CanProxyAdaptor<MemberPointerType>
507  : public CanProxyBase<MemberPointerType> {
508  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
509  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
510};
511
512template<>
513struct CanProxyAdaptor<ArrayType> : public CanProxyBase<ArrayType> {
514  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
515  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
516                                      getSizeModifier)
517  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
518};
519
520template<>
521struct CanProxyAdaptor<ConstantArrayType>
522  : public CanProxyBase<ConstantArrayType> {
523  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
524  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
525                                      getSizeModifier)
526  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
527  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
528};
529
530template<>
531struct CanProxyAdaptor<IncompleteArrayType>
532  : public CanProxyBase<IncompleteArrayType> {
533  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
534  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
535                                      getSizeModifier)
536  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
537};
538
539template<>
540struct CanProxyAdaptor<VariableArrayType>
541  : public CanProxyBase<VariableArrayType> {
542  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
543  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
544                                      getSizeModifier)
545  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
546  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
547  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
548  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
549  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
550};
551
552template<>
553struct CanProxyAdaptor<DependentSizedArrayType>
554  : public CanProxyBase<DependentSizedArrayType> {
555  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
556  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
557  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
558  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
559  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
560};
561
562template<>
563struct CanProxyAdaptor<DependentSizedExtVectorType>
564  : public CanProxyBase<DependentSizedExtVectorType> {
565  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
566  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr)
567  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc)
568};
569
570template<>
571struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {
572  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
573  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
574};
575
576template<>
577struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
578  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
579  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
580};
581
582template<>
583struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
584  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
585  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
586};
587
588template<>
589struct CanProxyAdaptor<FunctionNoProtoType>
590  : public CanProxyBase<FunctionNoProtoType> {
591  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
592  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
593};
594
595template<>
596struct CanProxyAdaptor<FunctionProtoType>
597  : public CanProxyBase<FunctionProtoType> {
598  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
599  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
600  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)
601  CanQualType getArgType(unsigned i) const {
602    return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
603  }
604
605  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
606  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
607
608  typedef CanTypeIterator<FunctionProtoType::arg_type_iterator>
609    arg_type_iterator;
610
611  arg_type_iterator arg_type_begin() const {
612    return arg_type_iterator(this->getTypePtr()->arg_type_begin());
613  }
614
615  arg_type_iterator arg_type_end() const {
616    return arg_type_iterator(this->getTypePtr()->arg_type_end());
617  }
618
619  // Note: canonical function types never have exception specifications
620};
621
622template<>
623struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
624  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
625};
626
627template<>
628struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
629  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr)
630  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
631};
632
633template<>
634struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
635  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
636  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
637};
638
639template<>
640struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
641  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
642  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
643  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
644};
645
646template<>
647struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {
648  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl)
649  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
650};
651
652template<>
653struct CanProxyAdaptor<TemplateTypeParmType>
654  : public CanProxyBase<TemplateTypeParmType> {
655  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth)
656  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex)
657  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack)
658  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl)
659  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier)
660};
661
662template<>
663struct CanProxyAdaptor<ObjCObjectType>
664  : public CanProxyBase<ObjCObjectType> {
665  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
666  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *,
667                                      getInterface)
668  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId)
669  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass)
670  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId)
671  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass)
672
673  typedef ObjCObjectPointerType::qual_iterator qual_iterator;
674  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
675  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
676  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
677  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
678};
679
680template<>
681struct CanProxyAdaptor<ObjCObjectPointerType>
682  : public CanProxyBase<ObjCObjectPointerType> {
683  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
684  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *,
685                                      getInterfaceType)
686  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType)
687  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType)
688  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
689  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
690
691  typedef ObjCObjectPointerType::qual_iterator qual_iterator;
692  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
693  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
694  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
695  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
696};
697
698//----------------------------------------------------------------------------//
699// Method and function definitions
700//----------------------------------------------------------------------------//
701template<typename T>
702inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
703  return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType());
704}
705
706template<typename T>
707inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
708  if (CanQual<ReferenceType> RefType = getAs<ReferenceType>())
709    return RefType->getPointeeType();
710  else
711    return *this;
712}
713
714template<typename T>
715CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
716  CanQual<T> Result;
717  Result.Stored = QualType::getFromOpaquePtr(Ptr);
718  assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
719          Result.Stored.isCanonical()) && "Type is not canonical!");
720  return Result;
721}
722
723template<typename T>
724CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
725  assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!");
726  assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
727         "Dynamic type does not meet the static type's requires");
728  CanQual<T> Result;
729  Result.Stored = Other;
730  return Result;
731}
732
733template<typename T>
734template<typename U>
735CanProxy<U> CanQual<T>::getAs() const {
736  if (Stored.isNull())
737    return CanProxy<U>();
738
739  if (isa<U>(Stored.getTypePtr()))
740    return CanQual<U>::CreateUnsafe(Stored);
741
742  return CanProxy<U>();
743}
744
745template<typename T>
746CanProxy<T> CanQual<T>::operator->() const {
747  return CanProxy<T>(*this);
748}
749
750template<typename InputIterator>
751typename CanTypeIterator<InputIterator>::pointer
752CanTypeIterator<InputIterator>::operator->() const {
753  return CanProxy<Type>(*this);
754}
755
756}
757
758
759#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H
760