diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-02 21:17:18 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-01-07 17:46:17 +0000 |
| commit | fe013be447cd855ccaf6094a1d06aea570450629 (patch) | |
| tree | 9adc1e0a5d25b6280995832bb29d592fb80554a6 /contrib/llvm-project/libcxx/include/__utility/is_pointer_in_range.h | |
| parent | 2f3b605b2e159522ecab77fd518e8139aaf581e9 (diff) | |
Diffstat (limited to 'contrib/llvm-project/libcxx/include/__utility/is_pointer_in_range.h')
| -rw-r--r-- | contrib/llvm-project/libcxx/include/__utility/is_pointer_in_range.h | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/contrib/llvm-project/libcxx/include/__utility/is_pointer_in_range.h b/contrib/llvm-project/libcxx/include/__utility/is_pointer_in_range.h new file mode 100644 index 000000000000..e859562e7457 --- /dev/null +++ b/contrib/llvm-project/libcxx/include/__utility/is_pointer_in_range.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H +#define _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H + +#include <__algorithm/comp.h> +#include <__assert> +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, class _Up, class = void> +struct __is_less_than_comparable : false_type {}; + +template <class _Tp, class _Up> +struct __is_less_than_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>() < std::declval<_Up>())> > : true_type { +}; + +template <class _Tp, class _Up, __enable_if_t<__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool __is_pointer_in_range( + const _Tp* __begin, const _Tp* __end, const _Up* __ptr) { + if (__libcpp_is_constant_evaluated()) { + _LIBCPP_ASSERT_UNCATEGORIZED(__builtin_constant_p(__begin <= __end), "__begin and __end do not form a range"); + + // If this is not a constant during constant evaluation we know that __ptr is not part of the allocation where + // [__begin, __end) is. + if (!__builtin_constant_p(__begin <= __ptr && __ptr < __end)) + return false; + } + + // Checking this for unrelated pointers is technically UB, but no compiler optimizes based on it (currently). + return !__less<>()(__ptr, __begin) && __less<>()(__ptr, __end); +} + +template <class _Tp, class _Up, __enable_if_t<!__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool __is_pointer_in_range( + const _Tp* __begin, const _Tp* __end, const _Up* __ptr) { + if (__libcpp_is_constant_evaluated()) + return false; + + return reinterpret_cast<const char*>(__begin) <= reinterpret_cast<const char*>(__ptr) && + reinterpret_cast<const char*>(__ptr) < reinterpret_cast<const char*>(__end); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H |
