| //===- CanonicalType.h - C Language Family Type Representation --*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the CanQual class template, which provides access to |
| // canonical types. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_AST_CANONICALTYPE_H |
| #define LLVM_CLANG_AST_CANONICALTYPE_H |
| |
| #include "clang/AST/Type.h" |
| #include "clang/Basic/Diagnostic.h" |
| #include "clang/Basic/SourceLocation.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/FoldingSet.h" |
| #include "llvm/ADT/iterator.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/PointerLikeTypeTraits.h" |
| #include <cassert> |
| #include <iterator> |
| #include <type_traits> |
| |
| namespace clang { |
| |
| template<typename T> class CanProxy; |
| template<typename T> struct CanProxyAdaptor; |
| class CXXRecordDecl; |
| class EnumDecl; |
| class Expr; |
| class IdentifierInfo; |
| class ObjCInterfaceDecl; |
| class RecordDecl; |
| class TagDecl; |
| class TemplateTypeParmDecl; |
| |
| //----------------------------------------------------------------------------// |
| // Canonical, qualified type template |
| //----------------------------------------------------------------------------// |
| |
| /// Represents a canonical, potentially-qualified type. |
| /// |
| /// The CanQual template is a lightweight smart pointer that provides access |
| /// to the canonical representation of a type, where all typedefs and other |
| /// syntactic sugar has been eliminated. A CanQualType may also have various |
| /// qualifiers (const, volatile, restrict) attached to it. |
| /// |
| /// The template type parameter @p T is one of the Type classes (PointerType, |
| /// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that |
| /// type (or some subclass of that type). The typedef @c CanQualType is just |
| /// a shorthand for @c CanQual<Type>. |
| /// |
| /// An instance of @c CanQual<T> can be implicitly converted to a |
| /// @c CanQual<U> when T is derived from U, which essentially provides an |
| /// implicit upcast. For example, @c CanQual<LValueReferenceType> can be |
| /// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can |
| /// be implicitly converted to a QualType, but the reverse operation requires |
| /// a call to ASTContext::getCanonicalType(). |
| template<typename T = Type> |
| class CanQual { |
| /// The actual, canonical type. |
| QualType Stored; |
| |
| public: |
| /// Constructs a NULL canonical type. |
| CanQual() = default; |
| |
| /// Converting constructor that permits implicit upcasting of |
| /// canonical type pointers. |
| template <typename U> |
| CanQual(const CanQual<U> &Other, |
| typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0); |
| |
| /// Retrieve the underlying type pointer, which refers to a |
| /// canonical type. |
| /// |
| /// The underlying pointer must not be nullptr. |
| const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); } |
| |
| /// Retrieve the underlying type pointer, which refers to a |
| /// canonical type, or nullptr. |
| const T *getTypePtrOrNull() const { |
| return cast_or_null<T>(Stored.getTypePtrOrNull()); |
| } |
| |
| /// Implicit conversion to a qualified type. |
| operator QualType() const { return Stored; } |
| |
| /// Implicit conversion to bool. |
| explicit operator bool() const { return !isNull(); } |
| |
| bool isNull() const { |
| return Stored.isNull(); |
| } |
| |
| SplitQualType split() const { return Stored.split(); } |
| |
| /// Retrieve a canonical type pointer with a different static type, |
| /// upcasting or downcasting as needed. |
| /// |
| /// The getAs() function is typically used to try to downcast to a |
| /// more specific (canonical) type in the type system. For example: |
| /// |
| /// @code |
| /// void f(CanQual<Type> T) { |
| /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { |
| /// // look at Ptr's pointee type |
| /// } |
| /// } |
| /// @endcode |
| /// |
| /// \returns A proxy pointer to the same type, but with the specified |
| /// static type (@p U). If the dynamic type is not the specified static type |
| /// or a derived class thereof, a NULL canonical type. |
| template<typename U> CanProxy<U> getAs() const; |
| |
| template<typename U> CanProxy<U> castAs() const; |
| |
| /// Overloaded arrow operator that produces a canonical type |
| /// proxy. |
| CanProxy<T> operator->() const; |
| |
| /// Retrieve all qualifiers. |
| Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); } |
| |
| /// Retrieve the const/volatile/restrict qualifiers. |
| unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); } |
| |
| /// Determines whether this type has any qualifiers |
| bool hasQualifiers() const { return Stored.hasLocalQualifiers(); } |
| |
| bool isConstQualified() const { |
| return Stored.isLocalConstQualified(); |
| } |
| |
| bool isVolatileQualified() const { |
| return Stored.isLocalVolatileQualified(); |
| } |
| |
| bool isRestrictQualified() const { |
| return Stored.isLocalRestrictQualified(); |
| } |
| |
| /// Determines if this canonical type is furthermore |
| /// canonical as a parameter. The parameter-canonicalization |
| /// process decays arrays to pointers and drops top-level qualifiers. |
| bool isCanonicalAsParam() const { |
| return Stored.isCanonicalAsParam(); |
| } |
| |
| /// Retrieve the unqualified form of this type. |
| CanQual<T> getUnqualifiedType() const; |
| |
| /// Retrieves a version of this type with const applied. |
| /// Note that this does not always yield a canonical type. |
| QualType withConst() const { |
| return Stored.withConst(); |
| } |
| |
| /// Determines whether this canonical type is more qualified than |
| /// the @p Other canonical type. |
| bool isMoreQualifiedThan(CanQual<T> Other) const { |
| return Stored.isMoreQualifiedThan(Other.Stored); |
| } |
| |
| /// Determines whether this canonical type is at least as qualified as |
| /// the @p Other canonical type. |
| bool isAtLeastAsQualifiedAs(CanQual<T> Other) const { |
| return Stored.isAtLeastAsQualifiedAs(Other.Stored); |
| } |
| |
| /// If the canonical type is a reference type, returns the type that |
| /// it refers to; otherwise, returns the type itself. |
| CanQual<Type> getNonReferenceType() const; |
| |
| /// Retrieve the internal representation of this canonical type. |
| void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); } |
| |
| /// Construct a canonical type from its internal representation. |
| static CanQual<T> getFromOpaquePtr(void *Ptr); |
| |
| /// Builds a canonical type from a QualType. |
| /// |
| /// This routine is inherently unsafe, because it requires the user to |
| /// ensure that the given type is a canonical type with the correct |
| // (dynamic) type. |
| static CanQual<T> CreateUnsafe(QualType Other); |
| |
| void dump() const { Stored.dump(); } |
| |
| void Profile(llvm::FoldingSetNodeID &ID) const { |
| ID.AddPointer(getAsOpaquePtr()); |
| } |
| }; |
| |
| template<typename T, typename U> |
| inline bool operator==(CanQual<T> x, CanQual<U> y) { |
| return x.getAsOpaquePtr() == y.getAsOpaquePtr(); |
| } |
| |
| template<typename T, typename U> |
| inline bool operator!=(CanQual<T> x, CanQual<U> y) { |
| return x.getAsOpaquePtr() != y.getAsOpaquePtr(); |
| } |
| |
| /// Represents a canonical, potentially-qualified type. |
| using CanQualType = CanQual<Type>; |
| |
| inline CanQualType Type::getCanonicalTypeUnqualified() const { |
| return CanQualType::CreateUnsafe(getCanonicalTypeInternal()); |
| } |
| |
| inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
| CanQualType T) { |
| DB << static_cast<QualType>(T); |
| return DB; |
| } |
| |
| //----------------------------------------------------------------------------// |
| // Internal proxy classes used by canonical types |
| //----------------------------------------------------------------------------// |
| |
| #define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \ |
| CanQualType Accessor() const { \ |
| return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \ |
| } |
| |
| #define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \ |
| Type Accessor() const { return this->getTypePtr()->Accessor(); } |
| |
| /// Base class of all canonical proxy types, which is responsible for |
| /// storing the underlying canonical type and providing basic conversions. |
| template<typename T> |
| class CanProxyBase { |
| protected: |
| CanQual<T> Stored; |
| |
| public: |
| /// Retrieve the pointer to the underlying Type |
| const T *getTypePtr() const { return Stored.getTypePtr(); } |
| |
| /// Implicit conversion to the underlying pointer. |
| /// |
| /// Also provides the ability to use canonical type proxies in a Boolean |
| // context,e.g., |
| /// @code |
| /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } |
| /// @endcode |
| operator const T*() const { return this->Stored.getTypePtrOrNull(); } |
| |
| /// Try to convert the given canonical type to a specific structural |
| /// type. |
| template<typename U> CanProxy<U> getAs() const { |
| return this->Stored.template getAs<U>(); |
| } |
| |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass) |
| |
| // Type predicates |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl) |
| |
| /// Retrieve the proxy-adaptor type. |
| /// |
| /// This arrow operator is used when CanProxyAdaptor has been specialized |
| /// for the given type T. In that case, we reference members of the |
| /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden |
| /// by the arrow operator in the primary CanProxyAdaptor template. |
| const CanProxyAdaptor<T> *operator->() const { |
| return static_cast<const CanProxyAdaptor<T> *>(this); |
| } |
| }; |
| |
| /// Replaceable canonical proxy adaptor class that provides the link |
| /// between a canonical type and the accessors of the type. |
| /// |
| /// The CanProxyAdaptor is a replaceable class template that is instantiated |
| /// as part of each canonical proxy type. The primary template merely provides |
| /// redirection to the underlying type (T), e.g., @c PointerType. One can |
| /// provide specializations of this class template for each underlying type |
| /// that provide accessors returning canonical types (@c CanQualType) rather |
| /// than the more typical @c QualType, to propagate the notion of "canonical" |
| /// through the system. |
| template<typename T> |
| struct CanProxyAdaptor : CanProxyBase<T> {}; |
| |
| /// Canonical proxy type returned when retrieving the members of a |
| /// canonical type or as the result of the @c CanQual<T>::getAs member |
| /// function. |
| /// |
| /// The CanProxy type mainly exists as a proxy through which operator-> will |
| /// look to either map down to a raw T* (e.g., PointerType*) or to a proxy |
| /// type that provides canonical-type access to the fields of the type. |
| template<typename T> |
| class CanProxy : public CanProxyAdaptor<T> { |
| public: |
| /// Build a NULL proxy. |
| CanProxy() = default; |
| |
| /// Build a proxy to the given canonical type. |
| CanProxy(CanQual<T> Stored) { this->Stored = Stored; } |
| |
| /// Implicit conversion to the stored canonical type. |
| operator CanQual<T>() const { return this->Stored; } |
| }; |
| |
| } // namespace clang |
| |
| namespace llvm { |
| |
| /// Implement simplify_type for CanQual<T>, so that we can dyn_cast from |
| /// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. |
| /// to return smart pointer (proxies?). |
| template<typename T> |
| struct simplify_type< ::clang::CanQual<T>> { |
| using SimpleType = const T *; |
| |
| static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) { |
| return Val.getTypePtr(); |
| } |
| }; |
| |
| // Teach SmallPtrSet that CanQual<T> is "basically a pointer". |
| template<typename T> |
| struct PointerLikeTypeTraits<clang::CanQual<T>> { |
| static void *getAsVoidPointer(clang::CanQual<T> P) { |
| return P.getAsOpaquePtr(); |
| } |
| |
| static clang::CanQual<T> getFromVoidPointer(void *P) { |
| return clang::CanQual<T>::getFromOpaquePtr(P); |
| } |
| |
| // qualifier information is encoded in the low bits. |
| enum { NumLowBitsAvailable = 0 }; |
| }; |
| |
| } // namespace llvm |
| |
| namespace clang { |
| |
| //----------------------------------------------------------------------------// |
| // Canonical proxy adaptors for canonical type nodes. |
| //----------------------------------------------------------------------------// |
| |
| /// Iterator adaptor that turns an iterator over canonical QualTypes |
| /// into an iterator over CanQualTypes. |
| template <typename InputIterator> |
| struct CanTypeIterator |
| : llvm::iterator_adaptor_base< |
| CanTypeIterator<InputIterator>, InputIterator, |
| typename std::iterator_traits<InputIterator>::iterator_category, |
| CanQualType, |
| typename std::iterator_traits<InputIterator>::difference_type, |
| CanProxy<Type>, CanQualType> { |
| CanTypeIterator() = default; |
| explicit CanTypeIterator(InputIterator Iter) |
| : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {} |
| |
| CanQualType operator*() const { return CanQualType::CreateUnsafe(*this->I); } |
| CanProxy<Type> operator->() const; |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<BlockPointerType> |
| : public CanProxyBase<BlockPointerType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<LValueReferenceType> |
| : public CanProxyBase<LValueReferenceType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<RValueReferenceType> |
| : public CanProxyBase<RValueReferenceType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<MemberPointerType> |
| : public CanProxyBase<MemberPointerType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) |
| }; |
| |
| // CanProxyAdaptors for arrays are intentionally unimplemented because |
| // they are not safe. |
| template<> struct CanProxyAdaptor<ArrayType>; |
| template<> struct CanProxyAdaptor<ConstantArrayType>; |
| template<> struct CanProxyAdaptor<IncompleteArrayType>; |
| template<> struct CanProxyAdaptor<VariableArrayType>; |
| template<> struct CanProxyAdaptor<DependentSizedArrayType>; |
| |
| template<> |
| struct CanProxyAdaptor<DependentSizedExtVectorType> |
| : public CanProxyBase<DependentSizedExtVectorType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<FunctionNoProtoType> |
| : public CanProxyBase<FunctionNoProtoType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<FunctionProtoType> |
| : public CanProxyBase<FunctionProtoType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR( |
| ArrayRef<FunctionProtoType::ExtParameterInfo>, getExtParameterInfos) |
| |
| CanQualType getParamType(unsigned i) const { |
| return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i)); |
| } |
| |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getMethodQuals) |
| |
| using param_type_iterator = |
| CanTypeIterator<FunctionProtoType::param_type_iterator>; |
| |
| param_type_iterator param_type_begin() const { |
| return param_type_iterator(this->getTypePtr()->param_type_begin()); |
| } |
| |
| param_type_iterator param_type_end() const { |
| return param_type_iterator(this->getTypePtr()->param_type_end()); |
| } |
| |
| // Note: canonical function types never have exception specifications |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> { |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr) |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) |
| }; |
| |
| template <> |
| struct CanProxyAdaptor<UnaryTransformType> |
| : public CanProxyBase<UnaryTransformType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> { |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> { |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> { |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<TemplateTypeParmType> |
| : public CanProxyBase<TemplateTypeParmType> { |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<ObjCObjectType> |
| : public CanProxyBase<ObjCObjectType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, |
| getInterface) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) |
| |
| using qual_iterator = ObjCObjectPointerType::qual_iterator; |
| |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) |
| }; |
| |
| template<> |
| struct CanProxyAdaptor<ObjCObjectPointerType> |
| : public CanProxyBase<ObjCObjectPointerType> { |
| LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *, |
| getInterfaceType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType) |
| |
| using qual_iterator = ObjCObjectPointerType::qual_iterator; |
| |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) |
| LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) |
| }; |
| |
| //----------------------------------------------------------------------------// |
| // Method and function definitions |
| //----------------------------------------------------------------------------// |
| template<typename T> |
| inline CanQual<T> CanQual<T>::getUnqualifiedType() const { |
| return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType()); |
| } |
| |
| template<typename T> |
| inline CanQual<Type> CanQual<T>::getNonReferenceType() const { |
| if (CanQual<ReferenceType> RefType = getAs<ReferenceType>()) |
| return RefType->getPointeeType(); |
| else |
| return *this; |
| } |
| |
| template<typename T> |
| CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { |
| CanQual<T> Result; |
| Result.Stored = QualType::getFromOpaquePtr(Ptr); |
| assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 || |
| Result.Stored.isCanonical()) && "Type is not canonical!"); |
| return Result; |
| } |
| |
| template<typename T> |
| CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { |
| assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!"); |
| assert((Other.isNull() || isa<T>(Other.getTypePtr())) && |
| "Dynamic type does not meet the static type's requires"); |
| CanQual<T> Result; |
| Result.Stored = Other; |
| return Result; |
| } |
| |
| template<typename T> |
| template<typename U> |
| CanProxy<U> CanQual<T>::getAs() const { |
| static_assert(!TypeIsArrayType<T>::value, |
| "ArrayType cannot be used with getAs!"); |
| |
| if (Stored.isNull()) |
| return CanProxy<U>(); |
| |
| if (isa<U>(Stored.getTypePtr())) |
| return CanQual<U>::CreateUnsafe(Stored); |
| |
| return CanProxy<U>(); |
| } |
| |
| template<typename T> |
| template<typename U> |
| CanProxy<U> CanQual<T>::castAs() const { |
| static_assert(!TypeIsArrayType<U>::value, |
| "ArrayType cannot be used with castAs!"); |
| |
| assert(!Stored.isNull() && isa<U>(Stored.getTypePtr())); |
| return CanQual<U>::CreateUnsafe(Stored); |
| } |
| |
| template<typename T> |
| CanProxy<T> CanQual<T>::operator->() const { |
| return CanProxy<T>(*this); |
| } |
| |
| template <typename InputIterator> |
| CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const { |
| return CanProxy<Type>(*this); |
| } |
| |
| } // namespace clang |
| |
| #endif // LLVM_CLANG_AST_CANONICALTYPE_H |