aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/libcxx/include/__utility/is_pointer_in_range.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-09-02 21:17:18 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-01-07 17:46:17 +0000
commitfe013be447cd855ccaf6094a1d06aea570450629 (patch)
tree9adc1e0a5d25b6280995832bb29d592fb80554a6 /contrib/llvm-project/libcxx/include/__utility/is_pointer_in_range.h
parent2f3b605b2e159522ecab77fd518e8139aaf581e9 (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.h62
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