1327952Sdim//===- CanonicalType.h - C Language Family Type Representation --*- C++ -*-===//
2198092Srdivacky//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6198092Srdivacky//
7198092Srdivacky//===----------------------------------------------------------------------===//
8198092Srdivacky//
9198092Srdivacky//  This file defines the CanQual class template, which provides access to
10198092Srdivacky//  canonical types.
11198092Srdivacky//
12198092Srdivacky//===----------------------------------------------------------------------===//
13198092Srdivacky
14280031Sdim#ifndef LLVM_CLANG_AST_CANONICALTYPE_H
15280031Sdim#define LLVM_CLANG_AST_CANONICALTYPE_H
16198092Srdivacky
17198092Srdivacky#include "clang/AST/Type.h"
18327952Sdim#include "clang/Basic/Diagnostic.h"
19327952Sdim#include "clang/Basic/SourceLocation.h"
20327952Sdim#include "llvm/ADT/ArrayRef.h"
21327952Sdim#include "llvm/ADT/FoldingSet.h"
22288943Sdim#include "llvm/ADT/iterator.h"
23198092Srdivacky#include "llvm/Support/Casting.h"
24327952Sdim#include "llvm/Support/PointerLikeTypeTraits.h"
25327952Sdim#include <cassert>
26327952Sdim#include <iterator>
27327952Sdim#include <type_traits>
28198092Srdivacky
29198092Srdivackynamespace clang {
30198092Srdivacky
31198092Srdivackytemplate<typename T> class CanProxy;
32198092Srdivackytemplate<typename T> struct CanProxyAdaptor;
33327952Sdimclass CXXRecordDecl;
34327952Sdimclass EnumDecl;
35327952Sdimclass Expr;
36327952Sdimclass IdentifierInfo;
37327952Sdimclass ObjCInterfaceDecl;
38327952Sdimclass RecordDecl;
39327952Sdimclass TagDecl;
40327952Sdimclass TemplateTypeParmDecl;
41198092Srdivacky
42198092Srdivacky//----------------------------------------------------------------------------//
43198092Srdivacky// Canonical, qualified type template
44198092Srdivacky//----------------------------------------------------------------------------//
45198092Srdivacky
46341825Sdim/// Represents a canonical, potentially-qualified type.
47198092Srdivacky///
48198092Srdivacky/// The CanQual template is a lightweight smart pointer that provides access
49198092Srdivacky/// to the canonical representation of a type, where all typedefs and other
50198092Srdivacky/// syntactic sugar has been eliminated. A CanQualType may also have various
51198092Srdivacky/// qualifiers (const, volatile, restrict) attached to it.
52198092Srdivacky///
53198092Srdivacky/// The template type parameter @p T is one of the Type classes (PointerType,
54198092Srdivacky/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that
55198092Srdivacky/// type (or some subclass of that type). The typedef @c CanQualType is just
56198092Srdivacky/// a shorthand for @c CanQual<Type>.
57198092Srdivacky///
58198092Srdivacky/// An instance of @c CanQual<T> can be implicitly converted to a
59198092Srdivacky/// @c CanQual<U> when T is derived from U, which essentially provides an
60198092Srdivacky/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be
61198092Srdivacky/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
62198092Srdivacky/// be implicitly converted to a QualType, but the reverse operation requires
63198092Srdivacky/// a call to ASTContext::getCanonicalType().
64198092Srdivackytemplate<typename T = Type>
65198092Srdivackyclass CanQual {
66341825Sdim  /// The actual, canonical type.
67198092Srdivacky  QualType Stored;
68198092Srdivacky
69198092Srdivackypublic:
70341825Sdim  /// Constructs a NULL canonical type.
71327952Sdim  CanQual() = default;
72198092Srdivacky
73341825Sdim  /// Converting constructor that permits implicit upcasting of
74198092Srdivacky  /// canonical type pointers.
75276479Sdim  template <typename U>
76276479Sdim  CanQual(const CanQual<U> &Other,
77276479Sdim          typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0);
78198092Srdivacky
79341825Sdim  /// Retrieve the underlying type pointer, which refers to a
80198092Srdivacky  /// canonical type.
81218893Sdim  ///
82327952Sdim  /// The underlying pointer must not be nullptr.
83218893Sdim  const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
84198092Srdivacky
85341825Sdim  /// Retrieve the underlying type pointer, which refers to a
86327952Sdim  /// canonical type, or nullptr.
87341825Sdim  const T *getTypePtrOrNull() const {
88341825Sdim    return cast_or_null<T>(Stored.getTypePtrOrNull());
89218893Sdim  }
90218893Sdim
91341825Sdim  /// Implicit conversion to a qualified type.
92198092Srdivacky  operator QualType() const { return Stored; }
93198092Srdivacky
94341825Sdim  /// Implicit conversion to bool.
95288943Sdim  explicit operator bool() const { return !isNull(); }
96341825Sdim
97198893Srdivacky  bool isNull() const {
98198893Srdivacky    return Stored.isNull();
99198893Srdivacky  }
100198893Srdivacky
101218893Sdim  SplitQualType split() const { return Stored.split(); }
102218893Sdim
103341825Sdim  /// Retrieve a canonical type pointer with a different static type,
104198092Srdivacky  /// upcasting or downcasting as needed.
105198092Srdivacky  ///
106198092Srdivacky  /// The getAs() function is typically used to try to downcast to a
107198092Srdivacky  /// more specific (canonical) type in the type system. For example:
108198092Srdivacky  ///
109198092Srdivacky  /// @code
110198092Srdivacky  /// void f(CanQual<Type> T) {
111198092Srdivacky  ///   if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) {
112198092Srdivacky  ///     // look at Ptr's pointee type
113198092Srdivacky  ///   }
114198092Srdivacky  /// }
115198092Srdivacky  /// @endcode
116198092Srdivacky  ///
117198092Srdivacky  /// \returns A proxy pointer to the same type, but with the specified
118198092Srdivacky  /// static type (@p U). If the dynamic type is not the specified static type
119198092Srdivacky  /// or a derived class thereof, a NULL canonical type.
120198092Srdivacky  template<typename U> CanProxy<U> getAs() const;
121198092Srdivacky
122234353Sdim  template<typename U> CanProxy<U> castAs() const;
123234353Sdim
124341825Sdim  /// Overloaded arrow operator that produces a canonical type
125198092Srdivacky  /// proxy.
126198092Srdivacky  CanProxy<T> operator->() const;
127198092Srdivacky
128341825Sdim  /// Retrieve all qualifiers.
129199482Srdivacky  Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
130198092Srdivacky
131341825Sdim  /// Retrieve the const/volatile/restrict qualifiers.
132199482Srdivacky  unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
133198092Srdivacky
134341825Sdim  /// Determines whether this type has any qualifiers
135199482Srdivacky  bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
136198092Srdivacky
137198092Srdivacky  bool isConstQualified() const {
138199482Srdivacky    return Stored.isLocalConstQualified();
139198092Srdivacky  }
140327952Sdim
141198092Srdivacky  bool isVolatileQualified() const {
142199482Srdivacky    return Stored.isLocalVolatileQualified();
143198092Srdivacky  }
144327952Sdim
145198092Srdivacky  bool isRestrictQualified() const {
146199482Srdivacky    return Stored.isLocalRestrictQualified();
147198092Srdivacky  }
148198092Srdivacky
149341825Sdim  /// Determines if this canonical type is furthermore
150204643Srdivacky  /// canonical as a parameter.  The parameter-canonicalization
151204643Srdivacky  /// process decays arrays to pointers and drops top-level qualifiers.
152204643Srdivacky  bool isCanonicalAsParam() const {
153204643Srdivacky    return Stored.isCanonicalAsParam();
154204643Srdivacky  }
155204643Srdivacky
156341825Sdim  /// Retrieve the unqualified form of this type.
157198092Srdivacky  CanQual<T> getUnqualifiedType() const;
158198092Srdivacky
159341825Sdim  /// Retrieves a version of this type with const applied.
160198893Srdivacky  /// Note that this does not always yield a canonical type.
161198893Srdivacky  QualType withConst() const {
162198893Srdivacky    return Stored.withConst();
163198092Srdivacky  }
164198092Srdivacky
165341825Sdim  /// Determines whether this canonical type is more qualified than
166198092Srdivacky  /// the @p Other canonical type.
167198092Srdivacky  bool isMoreQualifiedThan(CanQual<T> Other) const {
168198092Srdivacky    return Stored.isMoreQualifiedThan(Other.Stored);
169198092Srdivacky  }
170198092Srdivacky
171341825Sdim  /// Determines whether this canonical type is at least as qualified as
172198092Srdivacky  /// the @p Other canonical type.
173198092Srdivacky  bool isAtLeastAsQualifiedAs(CanQual<T> Other) const {
174198092Srdivacky    return Stored.isAtLeastAsQualifiedAs(Other.Stored);
175198092Srdivacky  }
176198092Srdivacky
177341825Sdim  /// If the canonical type is a reference type, returns the type that
178198092Srdivacky  /// it refers to; otherwise, returns the type itself.
179198092Srdivacky  CanQual<Type> getNonReferenceType() const;
180198092Srdivacky
181341825Sdim  /// Retrieve the internal representation of this canonical type.
182198092Srdivacky  void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
183198092Srdivacky
184341825Sdim  /// Construct a canonical type from its internal representation.
185198092Srdivacky  static CanQual<T> getFromOpaquePtr(void *Ptr);
186198092Srdivacky
187341825Sdim  /// Builds a canonical type from a QualType.
188198092Srdivacky  ///
189198092Srdivacky  /// This routine is inherently unsafe, because it requires the user to
190198092Srdivacky  /// ensure that the given type is a canonical type with the correct
191198092Srdivacky  // (dynamic) type.
192198092Srdivacky  static CanQual<T> CreateUnsafe(QualType Other);
193204643Srdivacky
194206084Srdivacky  void dump() const { Stored.dump(); }
195206084Srdivacky
196204643Srdivacky  void Profile(llvm::FoldingSetNodeID &ID) const {
197204643Srdivacky    ID.AddPointer(getAsOpaquePtr());
198204643Srdivacky  }
199198092Srdivacky};
200198092Srdivacky
201198092Srdivackytemplate<typename T, typename U>
202198092Srdivackyinline bool operator==(CanQual<T> x, CanQual<U> y) {
203198092Srdivacky  return x.getAsOpaquePtr() == y.getAsOpaquePtr();
204198092Srdivacky}
205198092Srdivacky
206198092Srdivackytemplate<typename T, typename U>
207198092Srdivackyinline bool operator!=(CanQual<T> x, CanQual<U> y) {
208198092Srdivacky  return x.getAsOpaquePtr() != y.getAsOpaquePtr();
209198092Srdivacky}
210198092Srdivacky
211341825Sdim/// Represents a canonical, potentially-qualified type.
212327952Sdimusing CanQualType = CanQual<Type>;
213198092Srdivacky
214204643Srdivackyinline CanQualType Type::getCanonicalTypeUnqualified() const {
215204643Srdivacky  return CanQualType::CreateUnsafe(getCanonicalTypeInternal());
216204643Srdivacky}
217204643Srdivacky
218200583Srdivackyinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
219200583Srdivacky                                           CanQualType T) {
220200583Srdivacky  DB << static_cast<QualType>(T);
221200583Srdivacky  return DB;
222200583Srdivacky}
223200583Srdivacky
224198092Srdivacky//----------------------------------------------------------------------------//
225198092Srdivacky// Internal proxy classes used by canonical types
226198092Srdivacky//----------------------------------------------------------------------------//
227198092Srdivacky
228198092Srdivacky#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor)                    \
229198092SrdivackyCanQualType Accessor() const {                                           \
230198092Srdivackyreturn CanQualType::CreateUnsafe(this->getTypePtr()->Accessor());      \
231198092Srdivacky}
232198092Srdivacky
233198092Srdivacky#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor)             \
234198092SrdivackyType Accessor() const { return this->getTypePtr()->Accessor(); }
235198092Srdivacky
236341825Sdim/// Base class of all canonical proxy types, which is responsible for
237198092Srdivacky/// storing the underlying canonical type and providing basic conversions.
238198092Srdivackytemplate<typename T>
239198092Srdivackyclass CanProxyBase {
240198092Srdivackyprotected:
241198092Srdivacky  CanQual<T> Stored;
242198092Srdivacky
243198092Srdivackypublic:
244341825Sdim  /// Retrieve the pointer to the underlying Type
245218893Sdim  const T *getTypePtr() const { return Stored.getTypePtr(); }
246198092Srdivacky
247341825Sdim  /// Implicit conversion to the underlying pointer.
248198092Srdivacky  ///
249198092Srdivacky  /// Also provides the ability to use canonical type proxies in a Boolean
250198092Srdivacky  // context,e.g.,
251198092Srdivacky  /// @code
252198092Srdivacky  ///   if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
253198092Srdivacky  /// @endcode
254218893Sdim  operator const T*() const { return this->Stored.getTypePtrOrNull(); }
255198092Srdivacky
256341825Sdim  /// Try to convert the given canonical type to a specific structural
257198092Srdivacky  /// type.
258198092Srdivacky  template<typename U> CanProxy<U> getAs() const {
259198092Srdivacky    return this->Stored.template getAs<U>();
260198092Srdivacky  }
261198092Srdivacky
262198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass)
263198092Srdivacky
264198092Srdivacky  // Type predicates
265198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
266198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
267198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
268198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
269198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
270198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
271198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType)
272198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType)
273198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType)
274198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType)
275210299Sed  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType)
276198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType)
277198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType)
278198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType)
279198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType)
280198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType)
281198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType)
282198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType)
283198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType)
284198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType)
285198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType)
286198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType)
287198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType)
288198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType)
289198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
290198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
291198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
292243830Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType)
293207619Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType)
294198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
295198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
296198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType)
297198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
298198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
299210299Sed  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
300198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
301198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
302212904Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
303212904Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
304212904Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
305210299Sed  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
306198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
307198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
308198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
309223017Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType)
310223017Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType)
311198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
312198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
313224145Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl)
314198092Srdivacky
315341825Sdim  /// Retrieve the proxy-adaptor type.
316198092Srdivacky  ///
317198092Srdivacky  /// This arrow operator is used when CanProxyAdaptor has been specialized
318198092Srdivacky  /// for the given type T. In that case, we reference members of the
319198092Srdivacky  /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden
320198092Srdivacky  /// by the arrow operator in the primary CanProxyAdaptor template.
321198092Srdivacky  const CanProxyAdaptor<T> *operator->() const {
322198092Srdivacky    return static_cast<const CanProxyAdaptor<T> *>(this);
323198092Srdivacky  }
324198092Srdivacky};
325198092Srdivacky
326341825Sdim/// Replaceable canonical proxy adaptor class that provides the link
327198092Srdivacky/// between a canonical type and the accessors of the type.
328198092Srdivacky///
329198092Srdivacky/// The CanProxyAdaptor is a replaceable class template that is instantiated
330198092Srdivacky/// as part of each canonical proxy type. The primary template merely provides
331198092Srdivacky/// redirection to the underlying type (T), e.g., @c PointerType. One can
332198092Srdivacky/// provide specializations of this class template for each underlying type
333198092Srdivacky/// that provide accessors returning canonical types (@c CanQualType) rather
334198092Srdivacky/// than the more typical @c QualType, to propagate the notion of "canonical"
335198092Srdivacky/// through the system.
336198092Srdivackytemplate<typename T>
337327952Sdimstruct CanProxyAdaptor : CanProxyBase<T> {};
338198092Srdivacky
339341825Sdim/// Canonical proxy type returned when retrieving the members of a
340198092Srdivacky/// canonical type or as the result of the @c CanQual<T>::getAs member
341198092Srdivacky/// function.
342198092Srdivacky///
343198092Srdivacky/// The CanProxy type mainly exists as a proxy through which operator-> will
344198092Srdivacky/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy
345198092Srdivacky/// type that provides canonical-type access to the fields of the type.
346198092Srdivackytemplate<typename T>
347198092Srdivackyclass CanProxy : public CanProxyAdaptor<T> {
348198092Srdivackypublic:
349341825Sdim  /// Build a NULL proxy.
350327952Sdim  CanProxy() = default;
351198092Srdivacky
352341825Sdim  /// Build a proxy to the given canonical type.
353198092Srdivacky  CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
354198092Srdivacky
355341825Sdim  /// Implicit conversion to the stored canonical type.
356198092Srdivacky  operator CanQual<T>() const { return this->Stored; }
357198092Srdivacky};
358198092Srdivacky
359327952Sdim} // namespace clang
360198092Srdivacky
361198092Srdivackynamespace llvm {
362198092Srdivacky
363198092Srdivacky/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from
364198092Srdivacky/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
365198092Srdivacky/// to return smart pointer (proxies?).
366198092Srdivackytemplate<typename T>
367327952Sdimstruct simplify_type< ::clang::CanQual<T>> {
368327952Sdim  using SimpleType = const T *;
369327952Sdim
370249423Sdim  static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) {
371198092Srdivacky    return Val.getTypePtr();
372198092Srdivacky  }
373198092Srdivacky};
374198092Srdivacky
375198092Srdivacky// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
376198092Srdivackytemplate<typename T>
377327952Sdimstruct PointerLikeTypeTraits<clang::CanQual<T>> {
378327952Sdim  static void *getAsVoidPointer(clang::CanQual<T> P) {
379198092Srdivacky    return P.getAsOpaquePtr();
380198092Srdivacky  }
381327952Sdim
382327952Sdim  static clang::CanQual<T> getFromVoidPointer(void *P) {
383198092Srdivacky    return clang::CanQual<T>::getFromOpaquePtr(P);
384198092Srdivacky  }
385327952Sdim
386198092Srdivacky  // qualifier information is encoded in the low bits.
387198092Srdivacky  enum { NumLowBitsAvailable = 0 };
388198092Srdivacky};
389198092Srdivacky
390327952Sdim} // namespace llvm
391198092Srdivacky
392198092Srdivackynamespace clang {
393198092Srdivacky
394198092Srdivacky//----------------------------------------------------------------------------//
395198092Srdivacky// Canonical proxy adaptors for canonical type nodes.
396198092Srdivacky//----------------------------------------------------------------------------//
397198092Srdivacky
398341825Sdim/// Iterator adaptor that turns an iterator over canonical QualTypes
399198092Srdivacky/// into an iterator over CanQualTypes.
400288943Sdimtemplate <typename InputIterator>
401288943Sdimstruct CanTypeIterator
402288943Sdim    : llvm::iterator_adaptor_base<
403288943Sdim          CanTypeIterator<InputIterator>, InputIterator,
404288943Sdim          typename std::iterator_traits<InputIterator>::iterator_category,
405288943Sdim          CanQualType,
406288943Sdim          typename std::iterator_traits<InputIterator>::difference_type,
407288943Sdim          CanProxy<Type>, CanQualType> {
408327952Sdim  CanTypeIterator() = default;
409288943Sdim  explicit CanTypeIterator(InputIterator Iter)
410288943Sdim      : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {}
411198092Srdivacky
412288943Sdim  CanQualType operator*() const { return CanQualType::CreateUnsafe(*this->I); }
413288943Sdim  CanProxy<Type> operator->() const;
414198092Srdivacky};
415198092Srdivacky
416198092Srdivackytemplate<>
417198092Srdivackystruct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
418198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
419198092Srdivacky};
420198092Srdivacky
421198092Srdivackytemplate<>
422198092Srdivackystruct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {
423198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
424198092Srdivacky};
425198092Srdivacky
426198092Srdivackytemplate<>
427198092Srdivackystruct CanProxyAdaptor<BlockPointerType>
428198092Srdivacky  : public CanProxyBase<BlockPointerType> {
429198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
430198092Srdivacky};
431198092Srdivacky
432198092Srdivackytemplate<>
433198092Srdivackystruct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {
434198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
435198092Srdivacky};
436198092Srdivacky
437198092Srdivackytemplate<>
438198092Srdivackystruct CanProxyAdaptor<LValueReferenceType>
439198092Srdivacky  : public CanProxyBase<LValueReferenceType> {
440198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
441198092Srdivacky};
442198092Srdivacky
443198092Srdivackytemplate<>
444198092Srdivackystruct CanProxyAdaptor<RValueReferenceType>
445198092Srdivacky  : public CanProxyBase<RValueReferenceType> {
446198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
447198092Srdivacky};
448198092Srdivacky
449198092Srdivackytemplate<>
450198092Srdivackystruct CanProxyAdaptor<MemberPointerType>
451198092Srdivacky  : public CanProxyBase<MemberPointerType> {
452198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
453198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
454198092Srdivacky};
455198092Srdivacky
456249423Sdim// CanProxyAdaptors for arrays are intentionally unimplemented because
457249423Sdim// they are not safe.
458249423Sdimtemplate<> struct CanProxyAdaptor<ArrayType>;
459249423Sdimtemplate<> struct CanProxyAdaptor<ConstantArrayType>;
460249423Sdimtemplate<> struct CanProxyAdaptor<IncompleteArrayType>;
461249423Sdimtemplate<> struct CanProxyAdaptor<VariableArrayType>;
462249423Sdimtemplate<> struct CanProxyAdaptor<DependentSizedArrayType>;
463198092Srdivacky
464198092Srdivackytemplate<>
465198092Srdivackystruct CanProxyAdaptor<DependentSizedExtVectorType>
466198092Srdivacky  : public CanProxyBase<DependentSizedExtVectorType> {
467198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
468198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr)
469198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc)
470198092Srdivacky};
471198092Srdivacky
472198092Srdivackytemplate<>
473198092Srdivackystruct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {
474198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
475198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
476198092Srdivacky};
477198092Srdivacky
478198092Srdivackytemplate<>
479198092Srdivackystruct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
480198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
481198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
482198092Srdivacky};
483198092Srdivacky
484198092Srdivackytemplate<>
485198092Srdivackystruct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
486276479Sdim  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
487206084Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
488198092Srdivacky};
489198092Srdivacky
490198092Srdivackytemplate<>
491198092Srdivackystruct CanProxyAdaptor<FunctionNoProtoType>
492198092Srdivacky  : public CanProxyBase<FunctionNoProtoType> {
493276479Sdim  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
494206084Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
495198092Srdivacky};
496198092Srdivacky
497198092Srdivackytemplate<>
498198092Srdivackystruct CanProxyAdaptor<FunctionProtoType>
499198092Srdivacky  : public CanProxyBase<FunctionProtoType> {
500276479Sdim  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
501206084Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
502276479Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams)
503309124Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos)
504309124Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(
505309124Sdim            ArrayRef<FunctionProtoType::ExtParameterInfo>, getExtParameterInfos)
506327952Sdim
507276479Sdim  CanQualType getParamType(unsigned i) const {
508276479Sdim    return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i));
509198092Srdivacky  }
510198092Srdivacky
511198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
512353358Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getMethodQuals)
513198092Srdivacky
514327952Sdim  using param_type_iterator =
515327952Sdim      CanTypeIterator<FunctionProtoType::param_type_iterator>;
516198092Srdivacky
517276479Sdim  param_type_iterator param_type_begin() const {
518276479Sdim    return param_type_iterator(this->getTypePtr()->param_type_begin());
519198092Srdivacky  }
520198092Srdivacky
521276479Sdim  param_type_iterator param_type_end() const {
522276479Sdim    return param_type_iterator(this->getTypePtr()->param_type_end());
523198092Srdivacky  }
524198092Srdivacky
525198092Srdivacky  // Note: canonical function types never have exception specifications
526198092Srdivacky};
527198092Srdivacky
528198092Srdivackytemplate<>
529198092Srdivackystruct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
530198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
531198092Srdivacky};
532198092Srdivacky
533198092Srdivackytemplate<>
534198092Srdivackystruct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
535198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr)
536198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
537198092Srdivacky};
538198092Srdivacky
539223017Sdimtemplate <>
540223017Sdimstruct CanProxyAdaptor<UnaryTransformType>
541223017Sdim    : public CanProxyBase<UnaryTransformType> {
542223017Sdim  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
543223017Sdim  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
544223017Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind)
545223017Sdim};
546223017Sdim
547198092Srdivackytemplate<>
548198092Srdivackystruct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
549198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
550198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
551198092Srdivacky};
552198092Srdivacky
553198092Srdivackytemplate<>
554198092Srdivackystruct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
555198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
556198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
557198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
558198092Srdivacky};
559198092Srdivacky
560198092Srdivackytemplate<>
561198092Srdivackystruct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {
562198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl)
563198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
564198092Srdivacky};
565198092Srdivacky
566198092Srdivackytemplate<>
567198092Srdivackystruct CanProxyAdaptor<TemplateTypeParmType>
568198092Srdivacky  : public CanProxyBase<TemplateTypeParmType> {
569198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth)
570198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex)
571198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack)
572221345Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl)
573221345Sdim  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier)
574198092Srdivacky};
575198092Srdivacky
576198092Srdivackytemplate<>
577208600Srdivackystruct CanProxyAdaptor<ObjCObjectType>
578208600Srdivacky  : public CanProxyBase<ObjCObjectType> {
579208600Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
580208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *,
581208600Srdivacky                                      getInterface)
582208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId)
583208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass)
584208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId)
585208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass)
586208600Srdivacky
587327952Sdim  using qual_iterator = ObjCObjectPointerType::qual_iterator;
588327952Sdim
589208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
590208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
591208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
592208600Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
593208600Srdivacky};
594208600Srdivacky
595208600Srdivackytemplate<>
596198092Srdivackystruct CanProxyAdaptor<ObjCObjectPointerType>
597198092Srdivacky  : public CanProxyBase<ObjCObjectPointerType> {
598198092Srdivacky  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
599198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *,
600198092Srdivacky                                      getInterfaceType)
601198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType)
602198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType)
603198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
604198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
605198092Srdivacky
606327952Sdim  using qual_iterator = ObjCObjectPointerType::qual_iterator;
607327952Sdim
608198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
609198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
610198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
611198092Srdivacky  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
612198092Srdivacky};
613198092Srdivacky
614198092Srdivacky//----------------------------------------------------------------------------//
615198092Srdivacky// Method and function definitions
616198092Srdivacky//----------------------------------------------------------------------------//
617198092Srdivackytemplate<typename T>
618198092Srdivackyinline CanQual<T> CanQual<T>::getUnqualifiedType() const {
619199482Srdivacky  return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType());
620198092Srdivacky}
621198092Srdivacky
622198092Srdivackytemplate<typename T>
623198092Srdivackyinline CanQual<Type> CanQual<T>::getNonReferenceType() const {
624198092Srdivacky  if (CanQual<ReferenceType> RefType = getAs<ReferenceType>())
625198092Srdivacky    return RefType->getPointeeType();
626198092Srdivacky  else
627198092Srdivacky    return *this;
628198092Srdivacky}
629198092Srdivacky
630198092Srdivackytemplate<typename T>
631198092SrdivackyCanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
632198092Srdivacky  CanQual<T> Result;
633212904Sdim  Result.Stored = QualType::getFromOpaquePtr(Ptr);
634212904Sdim  assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
635212904Sdim          Result.Stored.isCanonical()) && "Type is not canonical!");
636198092Srdivacky  return Result;
637198092Srdivacky}
638198092Srdivacky
639198092Srdivackytemplate<typename T>
640198092SrdivackyCanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
641198398Srdivacky  assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!");
642198092Srdivacky  assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
643198092Srdivacky         "Dynamic type does not meet the static type's requires");
644198092Srdivacky  CanQual<T> Result;
645198092Srdivacky  Result.Stored = Other;
646198092Srdivacky  return Result;
647198092Srdivacky}
648198092Srdivacky
649198092Srdivackytemplate<typename T>
650198092Srdivackytemplate<typename U>
651198092SrdivackyCanProxy<U> CanQual<T>::getAs() const {
652314564Sdim  static_assert(!TypeIsArrayType<T>::value,
653314564Sdim                "ArrayType cannot be used with getAs!");
654249423Sdim
655198092Srdivacky  if (Stored.isNull())
656198092Srdivacky    return CanProxy<U>();
657198092Srdivacky
658198092Srdivacky  if (isa<U>(Stored.getTypePtr()))
659198092Srdivacky    return CanQual<U>::CreateUnsafe(Stored);
660198092Srdivacky
661198092Srdivacky  return CanProxy<U>();
662198092Srdivacky}
663198092Srdivacky
664198092Srdivackytemplate<typename T>
665234353Sdimtemplate<typename U>
666234353SdimCanProxy<U> CanQual<T>::castAs() const {
667314564Sdim  static_assert(!TypeIsArrayType<U>::value,
668314564Sdim                "ArrayType cannot be used with castAs!");
669249423Sdim
670234353Sdim  assert(!Stored.isNull() && isa<U>(Stored.getTypePtr()));
671234353Sdim  return CanQual<U>::CreateUnsafe(Stored);
672234353Sdim}
673234353Sdim
674234353Sdimtemplate<typename T>
675198092SrdivackyCanProxy<T> CanQual<T>::operator->() const {
676198092Srdivacky  return CanProxy<T>(*this);
677198092Srdivacky}
678198092Srdivacky
679288943Sdimtemplate <typename InputIterator>
680288943SdimCanProxy<Type> CanTypeIterator<InputIterator>::operator->() const {
681198092Srdivacky  return CanProxy<Type>(*this);
682198092Srdivacky}
683198092Srdivacky
684327952Sdim} // namespace clang
685198092Srdivacky
686327952Sdim#endif // LLVM_CLANG_AST_CANONICALTYPE_H
687