llvm/clang/include/clang/AST/CanonicalType.h

//===- 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 {};

template<typename T, typename U>
inline bool operator==(CanQual<T> x, CanQual<U> y) {}

template<typename T, typename U>
inline bool operator!=(CanQual<T> x, CanQual<U> y) {}

/// Represents a canonical, potentially-qualified type.
CanQualType;

inline CanQualType Type::getCanonicalTypeUnqualified() const {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             CanQualType T) {}

//----------------------------------------------------------------------------//
// Internal proxy classes used by canonical types
//----------------------------------------------------------------------------//

#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor)

#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, 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 {}};

/// 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> {};

} // 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?).
simplify_type< ::clang::CanQual<T>>;

// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
PointerLikeTypeTraits<clang::CanQual<T>>;

} // 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> {};

template<>
struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {};

template<>
struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {};

template<>
struct CanProxyAdaptor<BlockPointerType>
  : public CanProxyBase<BlockPointerType> {};

template<>
struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {};

template<>
struct CanProxyAdaptor<LValueReferenceType>
  : public CanProxyBase<LValueReferenceType> {};

template<>
struct CanProxyAdaptor<RValueReferenceType>
  : public CanProxyBase<RValueReferenceType> {};

template<>
struct CanProxyAdaptor<MemberPointerType>
  : public CanProxyBase<MemberPointerType> {};

// 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> {};

template<>
struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {};

template<>
struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {};

template<>
struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {};

template<>
struct CanProxyAdaptor<FunctionNoProtoType>
  : public CanProxyBase<FunctionNoProtoType> {};

template<>
struct CanProxyAdaptor<FunctionProtoType>
  : public CanProxyBase<FunctionProtoType> {};

template<>
struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {};

template<>
struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {};

template <>
struct CanProxyAdaptor<UnaryTransformType>
    : public CanProxyBase<UnaryTransformType> {};

template<>
struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {};

template<>
struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {};

template<>
struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {};

template<>
struct CanProxyAdaptor<TemplateTypeParmType>
  : public CanProxyBase<TemplateTypeParmType> {};

template<>
struct CanProxyAdaptor<ObjCObjectType>
  : public CanProxyBase<ObjCObjectType> {};

template<>
struct CanProxyAdaptor<ObjCObjectPointerType>
  : public CanProxyBase<ObjCObjectPointerType> {};

//----------------------------------------------------------------------------//
// Method and function definitions
//----------------------------------------------------------------------------//
template<typename T>
inline CanQual<T> CanQual<T>::getUnqualifiedType() const {}

template<typename T>
inline CanQual<Type> CanQual<T>::getNonReferenceType() const {}

template<typename T>
CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {}

template<typename T>
CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {}

template<typename T>
template<typename U>
CanProxy<U> CanQual<T>::getAs() const {}

template<typename T>
template<typename U>
CanProxy<U> CanQual<T>::castAs() const {}

template<typename T>
CanProxy<T> CanQual<T>::operator->() const {}

template <typename InputIterator>
CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const {}

} // namespace clang

#endif // LLVM_CLANG_AST_CANONICALTYPE_H