Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 0 additions & 124 deletions libcudacxx/include/cuda/__argument/argument.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,130 +129,6 @@ struct __constant_sequence
}
};

// =====================================================================
// __assert_in_range
// =====================================================================

template <class _To, class _From>
_CCCL_API constexpr void __assert_in_range([[maybe_unused]] _From __val) noexcept
{
if constexpr (::cuda::std::__cccl_is_cv_integer_v<_To> && ::cuda::std::__cccl_is_cv_integer_v<_From>)
{
_CCCL_ASSERT(::cuda::std::in_range<::cuda::std::remove_cv_t<_To>>(__val),
"runtime bound value overflows the element type");
}
}

template <class _To, class _From>
[[nodiscard]] _CCCL_API constexpr _To __runtime_bound_cast(_From __val) noexcept
{
__assert_in_range<_To>(__val);
return static_cast<_To>(__val);
}

template <class _To, auto _Value>
_CCCL_API constexpr bool __static_bound_in_range() noexcept
{
using _RawTo = ::cuda::std::remove_cv_t<_To>;
using _RawFrom = ::cuda::std::remove_cv_t<decltype(_Value)>;

if constexpr (::cuda::std::__cccl_is_integer_v<_RawTo> && ::cuda::std::__cccl_is_integer_v<_RawFrom>)
{
return ::cuda::std::in_range<_RawTo>(_Value);
}
else if constexpr (::cuda::std::is_arithmetic_v<_RawTo> && ::cuda::std::is_arithmetic_v<_RawFrom>)
{
return static_cast<_RawFrom>(static_cast<_RawTo>(_Value)) == _Value;
}
else
{
return true;
}
}

template <class _ElementType, class _StaticBounds>
inline constexpr bool __valid_static_bounds_v = true;

template <class _ElementType, auto _Lowest, auto _Highest>
inline constexpr bool __valid_static_bounds_v<_ElementType, __static_bounds<_Lowest, _Highest>> =
__static_bound_in_range<_ElementType, _Lowest>() && __static_bound_in_range<_ElementType, _Highest>();

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __wrapper_static_lowest() noexcept
{
if constexpr (::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
return ::cuda::std::numeric_limits<_ElementType>::lowest();
}
else
{
return static_cast<_ElementType>(_StaticBounds::lower());
}
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __wrapper_static_highest() noexcept
{
if constexpr (::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
return (::cuda::std::numeric_limits<_ElementType>::max)();
}
else
{
return static_cast<_ElementType>(_StaticBounds::upper());
}
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __effective_lowest(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
auto __static_lowest = __wrapper_static_lowest<_ElementType, _StaticBounds>();
return __static_lowest > __runtime_bounds.lower() ? __static_lowest : __runtime_bounds.lower();
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __effective_highest(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
auto __static_highest = __wrapper_static_highest<_ElementType, _StaticBounds>();
return __static_highest < __runtime_bounds.upper() ? __static_highest : __runtime_bounds.upper();
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr bool __has_bounds_intersection(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
return __effective_lowest<_ElementType, _StaticBounds>(__runtime_bounds)
<= __effective_highest<_ElementType, _StaticBounds>(__runtime_bounds);
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr void __validate_bounds_intersection(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
static_assert(__valid_static_bounds_v<_ElementType, _StaticBounds>,
"static argument bounds cannot be represented by the element type");
_CCCL_VERIFY((__has_bounds_intersection<_ElementType, _StaticBounds>(__runtime_bounds)),
"static and runtime argument bounds do not intersect");
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr void __validate_static_element_bounds([[maybe_unused]] const _ElementType& __val) noexcept
{
if constexpr (!::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
_CCCL_ASSERT((__val >= __wrapper_static_lowest<_ElementType, _StaticBounds>()),
"immediate argument value is below static lowest bound");
_CCCL_ASSERT((__val <= __wrapper_static_highest<_ElementType, _StaticBounds>()),
"immediate argument value is above static highest bound");
}
}

template <class _ElementType>
_CCCL_API constexpr void __validate_runtime_element_bounds(
[[maybe_unused]] const _ElementType& __val, [[maybe_unused]] __runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
_CCCL_ASSERT((__val >= __runtime_bounds.lower()), "immediate argument value is below runtime lower bound");
_CCCL_ASSERT((__val <= __runtime_bounds.upper()), "immediate argument value is above runtime upper bound");
}

// =====================================================================
// __immediate
// =====================================================================
Expand Down
130 changes: 128 additions & 2 deletions libcudacxx/include/cuda/__argument/argument_bounds.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
#endif // no system header

#include <cuda/std/__cccl/assert.h>
#include <cuda/std/__type_traits/is_extended_arithmetic.h>
#include <cuda/std/__type_traits/is_same.h>
#include <cuda/std/__type_traits/remove_cv.h>
#include <cuda/std/__type_traits/remove_cvref.h>
#include <cuda/std/__utility/cmp.h>
#include <cuda/std/limits>

#include <cuda/std/__cccl/prologue.h>
Expand Down Expand Up @@ -136,12 +139,135 @@ template <class _Tp>
}

template <class _Tp>
inline constexpr bool __is_static_bounds_cv_v = __is_static_bounds_v<::cuda::std::remove_cv_t<_Tp>>;
inline constexpr bool __is_static_bounds_cv_v = __is_static_bounds_v<::cuda::std::remove_cvref_t<_Tp>>;
template <class _Tp>
inline constexpr bool __is_runtime_bounds_cv_v = __is_runtime_bounds_v<::cuda::std::remove_cv_t<_Tp>>;
inline constexpr bool __is_runtime_bounds_cv_v = __is_runtime_bounds_v<::cuda::std::remove_cvref_t<_Tp>>;
template <class _Tp>
inline constexpr bool __is_bounds_v = __is_static_bounds_cv_v<_Tp> || __is_runtime_bounds_cv_v<_Tp>;

// =====================================================================
// __assert_in_range
// =====================================================================

template <class _To, class _From>
_CCCL_API constexpr void __assert_in_range([[maybe_unused]] _From __val) noexcept
{
if constexpr (::cuda::std::__cccl_is_integer_v<_To> && ::cuda::std::__cccl_is_integer_v<_From>)
{
_CCCL_ASSERT(::cuda::std::in_range<_To>(__val), "runtime bound value overflows the element type");
}
}

template <class _To, class _From>
[[nodiscard]] _CCCL_API constexpr _To __runtime_bound_cast(_From __val) noexcept
{
__assert_in_range<_To>(__val);
return static_cast<_To>(__val);
Comment on lines +152 to +165

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

important: Runtime bounds still narrow silently for non-integer sources.

__runtime_bound_cast only guards integer-to-integer conversions, but __immediate_sequence uses it to store user-supplied runtime bounds as __element_type. A mixed-type case like floating runtime bounds into an integral element type gets truncated before __validate_bounds_intersection runs, so validation happens on different endpoints than the caller passed. Please reject any arithmetic runtime bound that is not exactly representable in _To, not just integer/integer pairs.

}

template <class _To, auto _Value>
_CCCL_API constexpr bool __static_bound_in_range() noexcept
{
using _From = decltype(_Value);

if constexpr (::cuda::std::__cccl_is_integer_v<_To> && ::cuda::std::__cccl_is_integer_v<_From>)
{
return ::cuda::std::in_range<_To>(_Value);
}
else if constexpr (::cuda::std::is_arithmetic_v<_To> && ::cuda::std::is_arithmetic_v<_From>)
{
return static_cast<_From>(static_cast<_To>(_Value)) == _Value;
}
else
{
return true;
}
}

template <class _ElementType, class _StaticBounds>
inline constexpr bool __valid_static_bounds_v = true;

template <class _ElementType, auto _Lowest, auto _Highest>
inline constexpr bool __valid_static_bounds_v<_ElementType, __static_bounds<_Lowest, _Highest>> =
::cuda::__argument::__static_bound_in_range<_ElementType, _Lowest>()
&& ::cuda::__argument::__static_bound_in_range<_ElementType, _Highest>();

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __wrapper_static_lowest() noexcept
{
if constexpr (::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
return ::cuda::std::numeric_limits<_ElementType>::lowest();
}
else
{
return static_cast<_ElementType>(_StaticBounds::lower());
}
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __wrapper_static_highest() noexcept
{
if constexpr (::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
return (::cuda::std::numeric_limits<_ElementType>::max)();
}
else
{
return static_cast<_ElementType>(_StaticBounds::upper());
}
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __effective_lowest(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
auto __static_lowest = ::cuda::__argument::__wrapper_static_lowest<_ElementType, _StaticBounds>();
return __static_lowest > __runtime_bounds.lower() ? __static_lowest : __runtime_bounds.lower();
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __effective_highest(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
auto __static_highest = ::cuda::__argument::__wrapper_static_highest<_ElementType, _StaticBounds>();
return __static_highest < __runtime_bounds.upper() ? __static_highest : __runtime_bounds.upper();
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr bool __valid_argument_bounds(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
return ::cuda::__argument::__effective_lowest<_ElementType, _StaticBounds>(__runtime_bounds)
<= ::cuda::__argument::__effective_highest<_ElementType, _StaticBounds>(__runtime_bounds);
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr void __validate_bounds_intersection(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
static_assert(__valid_static_bounds_v<_ElementType, _StaticBounds>,
"static argument bounds cannot be represented by the element type");
_CCCL_VERIFY((::cuda::__argument::__valid_argument_bounds<_ElementType, _StaticBounds>(__runtime_bounds)),
"static and runtime argument bounds do not intersect");
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr void __validate_static_element_bounds([[maybe_unused]] const _ElementType& __val) noexcept
{
if constexpr (!::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
_CCCL_ASSERT((__val >= ::cuda::__argument::__wrapper_static_lowest<_ElementType, _StaticBounds>()),
"immediate argument value is below static lowest bound");
_CCCL_ASSERT((__val <= ::cuda::__argument::__wrapper_static_highest<_ElementType, _StaticBounds>()),
"immediate argument value is above static highest bound");
}
}

template <class _ElementType>
_CCCL_API constexpr void __validate_runtime_element_bounds(
[[maybe_unused]] const _ElementType& __val, [[maybe_unused]] __runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
_CCCL_ASSERT((__val >= __runtime_bounds.lower()), "immediate argument value is below runtime lower bound");
_CCCL_ASSERT((__val <= __runtime_bounds.upper()), "immediate argument value is above runtime upper bound");
}

_CCCL_END_NAMESPACE_CUDA_ARGUMENT

#include <cuda/std/__cccl/epilogue.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ TEST_FUNC constexpr bool test()

// Static and runtime bounds intersection
{
static_assert(cuda::__argument::__has_bounds_intersection<int, cuda::__argument::__static_bounds<1, 100>>(
static_assert(cuda::__argument::__valid_argument_bounds<int, cuda::__argument::__static_bounds<1, 100>>(
cuda::__argument::__runtime_bounds<int>{50, 200}));
static_assert(!cuda::__argument::__has_bounds_intersection<int, cuda::__argument::__static_bounds<100, 200>>(
static_assert(!cuda::__argument::__valid_argument_bounds<int, cuda::__argument::__static_bounds<100, 200>>(
cuda::__argument::__runtime_bounds<int>{0, 50}));
}

Expand Down
Loading