llvm/llvm/include/llvm/Support/PointerLikeTypeTraits.h

//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- 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 PointerLikeTypeTraits class.  This allows data
// structures to reason about pointers and other things that are pointer sized.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H

#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <type_traits>

namespace llvm {

/// A traits type that is used to handle pointer types and things that are just
/// wrappers for pointers as a uniform entity.
template <typename T> struct PointerLikeTypeTraits;

namespace detail {
/// A tiny meta function to compute the log2 of a compile time constant.
template <size_t N>
struct ConstantLog2
    : std::integral_constant<size_t, ConstantLog2<N / 2>::value + 1> {};
template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {};

// Provide a trait to check if T is pointer-like.
template <typename T, typename U = void> struct HasPointerLikeTypeTraits {};

// sizeof(T) is valid only for a complete T.
HasPointerLikeTypeTraits<T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)) , void())>;

template <typename T> struct IsPointerLike {};

IsPointerLike<T *>;
} // namespace detail

// Provide PointerLikeTypeTraits for non-cvr pointers.
PointerLikeTypeTraits<T *>;

template <> struct PointerLikeTypeTraits<void *> {};

// Provide PointerLikeTypeTraits for const things.
PointerLikeTypeTraits<const T>;

// Provide PointerLikeTypeTraits for const pointers.
PointerLikeTypeTraits<const T *>;

// Provide PointerLikeTypeTraits for uintptr_t.
template <> struct PointerLikeTypeTraits<uintptr_t> {};

/// Provide suitable custom traits struct for function pointers.
///
/// Function pointers can't be directly given these traits as functions can't
/// have their alignment computed with `alignof` and we need different casting.
///
/// To rely on higher alignment for a specialized use, you can provide a
/// customized form of this template explicitly with higher alignment, and
/// potentially use alignment attributes on functions to satisfy that.
template <int Alignment, typename FunctionPointerT>
struct FunctionPointerLikeTypeTraits {};

/// Provide a default specialization for function pointers that assumes 4-byte
/// alignment.
///
/// We assume here that functions used with this are always at least 4-byte
/// aligned. This means that, for example, thumb functions won't work or systems
/// with weird unaligned function pointers won't work. But all practical systems
/// we support satisfy this requirement.
PointerLikeTypeTraits<ReturnT (*)(ParamTs...)>;

} // end namespace llvm

#endif