xref: /llvm-project/libcxx/include/__utility/is_pointer_in_range.h (revision 33af68a476fee9e3380f0831c8a69265ace61b74)
17949ee0dSNikolas Klauser //===----------------------------------------------------------------------===//
27949ee0dSNikolas Klauser //
37949ee0dSNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47949ee0dSNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
57949ee0dSNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67949ee0dSNikolas Klauser //
77949ee0dSNikolas Klauser //===----------------------------------------------------------------------===//
87949ee0dSNikolas Klauser 
97949ee0dSNikolas Klauser #ifndef _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H
107949ee0dSNikolas Klauser #define _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H
117949ee0dSNikolas Klauser 
127949ee0dSNikolas Klauser #include <__algorithm/comp.h>
137949ee0dSNikolas Klauser #include <__assert>
147949ee0dSNikolas Klauser #include <__config>
157949ee0dSNikolas Klauser #include <__type_traits/enable_if.h>
167949ee0dSNikolas Klauser #include <__type_traits/integral_constant.h>
177949ee0dSNikolas Klauser #include <__type_traits/is_constant_evaluated.h>
187949ee0dSNikolas Klauser #include <__type_traits/void_t.h>
197949ee0dSNikolas Klauser #include <__utility/declval.h>
20a06073f9SLouis Dionne #include <__utility/is_valid_range.h>
217949ee0dSNikolas Klauser 
227949ee0dSNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
237949ee0dSNikolas Klauser #  pragma GCC system_header
247949ee0dSNikolas Klauser #endif
257949ee0dSNikolas Klauser 
267949ee0dSNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD
277949ee0dSNikolas Klauser 
28c4e98722SNikolas Klauser template <class _Tp, class _Up, class = void>
29c4e98722SNikolas Klauser struct __is_less_than_comparable : false_type {};
30c4e98722SNikolas Klauser 
317949ee0dSNikolas Klauser template <class _Tp, class _Up>
32c4e98722SNikolas Klauser struct __is_less_than_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>() < std::declval<_Up>())> > : true_type {
33c4e98722SNikolas Klauser };
34c4e98722SNikolas Klauser 
35c4e98722SNikolas Klauser template <class _Tp, class _Up, __enable_if_t<__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0>
36e2c2ffbeSLouis Dionne _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool
37e2c2ffbeSLouis Dionne __is_pointer_in_range(const _Tp* __begin, const _Tp* __end, const _Up* __ptr) {
38a06073f9SLouis Dionne   _LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__begin, __end), "[__begin, __end) is not a valid range");
397949ee0dSNikolas Klauser 
40a06073f9SLouis Dionne   if (__libcpp_is_constant_evaluated()) {
417949ee0dSNikolas Klauser     // If this is not a constant during constant evaluation we know that __ptr is not part of the allocation where
427949ee0dSNikolas Klauser     // [__begin, __end) is.
437949ee0dSNikolas Klauser     if (!__builtin_constant_p(__begin <= __ptr && __ptr < __end))
447949ee0dSNikolas Klauser       return false;
457949ee0dSNikolas Klauser   }
467949ee0dSNikolas Klauser 
477949ee0dSNikolas Klauser   return !__less<>()(__ptr, __begin) && __less<>()(__ptr, __end);
487949ee0dSNikolas Klauser }
497949ee0dSNikolas Klauser 
50c4e98722SNikolas Klauser template <class _Tp, class _Up, __enable_if_t<!__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0>
51e2c2ffbeSLouis Dionne _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool
52e2c2ffbeSLouis Dionne __is_pointer_in_range(const _Tp* __begin, const _Tp* __end, const _Up* __ptr) {
53c4e98722SNikolas Klauser   if (__libcpp_is_constant_evaluated())
54c4e98722SNikolas Klauser     return false;
55c4e98722SNikolas Klauser 
56c4e98722SNikolas Klauser   return reinterpret_cast<const char*>(__begin) <= reinterpret_cast<const char*>(__ptr) &&
57c4e98722SNikolas Klauser          reinterpret_cast<const char*>(__ptr) < reinterpret_cast<const char*>(__end);
58c4e98722SNikolas Klauser }
59c4e98722SNikolas Klauser 
60*33af68a4SNikolas Klauser template <class _Tp, class _Up>
61*33af68a4SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
62*33af68a4SNikolas Klauser __is_overlapping_range(const _Tp* __begin, const _Tp* __end, const _Up* __begin2) {
63*33af68a4SNikolas Klauser   auto __size = __end - __begin;
64*33af68a4SNikolas Klauser   auto __end2 = __begin2 + __size;
65*33af68a4SNikolas Klauser   return std::__is_pointer_in_range(__begin, __end, __begin2) || std::__is_pointer_in_range(__begin2, __end2, __begin);
66*33af68a4SNikolas Klauser }
67*33af68a4SNikolas Klauser 
687949ee0dSNikolas Klauser _LIBCPP_END_NAMESPACE_STD
697949ee0dSNikolas Klauser 
707949ee0dSNikolas Klauser #endif // _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H
71