diff --git a/libcudacxx/include/cuda/std/__expected/bad_expected_access.h b/libcudacxx/include/cuda/std/__expected/bad_expected_access.h index 5600402e429..0f10f546be6 100644 --- a/libcudacxx/include/cuda/std/__expected/bad_expected_access.h +++ b/libcudacxx/include/cuda/std/__expected/bad_expected_access.h @@ -51,14 +51,6 @@ class bad_expected_access; template <> class bad_expected_access : public ::std::exception { -protected: - _CCCL_HIDE_FROM_ABI bad_expected_access() noexcept = default; - _CCCL_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) = default; - _CCCL_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default; - _CCCL_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default; - _CCCL_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default; - ~bad_expected_access() noexcept override = default; - public: // The way this has been designed (by using a class template below) means that we'll already // have a profusion of these vtables in TUs, and the dynamic linker will already have a bunch @@ -74,10 +66,21 @@ template class bad_expected_access : public bad_expected_access { public: - explicit bad_expected_access(_Err __e) +# if _CCCL_CUDA_COMPILER(CLANG) // Clang needs this or it breaks with device only types + _CCCL_HOST_DEVICE +# endif // _CCCL_CUDA_COMPILER(CLANG) + _CCCL_HIDE_FROM_ABI explicit bad_expected_access(_Err __e) : __unex_(_CUDA_VSTD::move(__e)) {} +# if _CCCL_CUDA_COMPILER(CLANG) // Clang needs this or it breaks with device only types + _CCCL_HOST_DEVICE +# endif // _CCCL_CUDA_COMPILER(CLANG) + _CCCL_HIDE_FROM_ABI ~bad_expected_access() noexcept + { + __unex_.~_Err(); + } + _LIBCUDACXX_HIDE_FROM_ABI _Err& error() & noexcept { return __unex_; diff --git a/libcudacxx/include/cuda/std/__expected/expected.h b/libcudacxx/include/cuda/std/__expected/expected.h index cc5ddfc03f0..f618ff57c92 100644 --- a/libcudacxx/include/cuda/std/__expected/expected.h +++ b/libcudacxx/include/cuda/std/__expected/expected.h @@ -1070,6 +1070,7 @@ class expected : private __expected_move_assign<_Tp, _Err> } // [expected.object.eq], equality operators + _CCCL_EXEC_CHECK_DISABLE friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const expected& __x, const expected& __y) { if (__x.__has_val_ != __y.has_value()) @@ -1090,12 +1091,14 @@ class expected : private __expected_move_assign<_Tp, _Err> } # if _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const expected& __x, const expected& __y) { return !(__x == __y); } # endif // _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T2, class _E2) _CCCL_REQUIRES((!_CCCL_TRAIT(is_void, _T2))) friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) @@ -1118,6 +1121,7 @@ class expected : private __expected_move_assign<_Tp, _Err> } # if _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T2, class _E2) _CCCL_REQUIRES((!_CCCL_TRAIT(is_void, _T2))) friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const expected& __x, const expected<_T2, _E2>& __y) @@ -1126,6 +1130,7 @@ class expected : private __expected_move_assign<_Tp, _Err> } # endif // _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T2) _CCCL_REQUIRES((!__expected::__is_expected_nonvoid<_T2>) ) friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const expected& __x, const _T2& __v) @@ -1133,18 +1138,21 @@ class expected : private __expected_move_assign<_Tp, _Err> return __x.__has_val_ && static_cast(__x.__union_.__val_ == __v); } # if _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T2) _CCCL_REQUIRES((!__expected::__is_expected_nonvoid<_T2>) ) friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const _T2& __v, const expected& __x) { return __x.__has_val_ && static_cast(__x.__union_.__val_ == __v); } + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T2) _CCCL_REQUIRES((!__expected::__is_expected_nonvoid<_T2>) ) friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const expected& __x, const _T2& __v) { return !__x.__has_val_ || static_cast(__x.__union_.__val_ != __v); } + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T2) _CCCL_REQUIRES((!__expected::__is_expected_nonvoid<_T2>) ) friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const _T2& __v, const expected& __x) @@ -1153,22 +1161,26 @@ class expected : private __expected_move_assign<_Tp, _Err> } # endif // _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE template friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { return !__x.__has_val_ && static_cast(__x.__union_.__unex_ == __e.error()); } # if _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE template friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const unexpected<_E2>& __e, const expected& __x) { return !__x.__has_val_ && static_cast(__x.__union_.__unex_ == __e.error()); } + _CCCL_EXEC_CHECK_DISABLE template friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const expected& __x, const unexpected<_E2>& __e) { return __x.__has_val_ || static_cast(__x.__union_.__unex_ != __e.error()); } + _CCCL_EXEC_CHECK_DISABLE template friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const unexpected<_E2>& __e, const expected& __x) { @@ -1906,6 +1918,7 @@ class expected : private __expected_move_assign } // [expected.void.eq], equality operators + _CCCL_EXEC_CHECK_DISABLE friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const expected& __x, const expected& __y) noexcept { if (__x.__has_val_ != __y.has_value()) @@ -1918,12 +1931,14 @@ class expected : private __expected_move_assign } } # if _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const expected& __x, const expected& __y) noexcept { return !(__x == __y); } # endif + _CCCL_EXEC_CHECK_DISABLE template friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const expected& __x, const expected& __y) noexcept @@ -1938,6 +1953,7 @@ class expected : private __expected_move_assign } } # if _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE template friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const expected& __x, const expected& __y) noexcept @@ -1946,22 +1962,26 @@ class expected : private __expected_move_assign } # endif + _CCCL_EXEC_CHECK_DISABLE template friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) noexcept { return !__x.__has_val_ && static_cast(__x.__union_.__unex_ == __y.error()); } # if _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE template friend _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const unexpected<_E2>& __y, const expected& __x) noexcept { return !__x.__has_val_ && static_cast(__x.__union_.__unex_ == __y.error()); } + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI friend constexpr bool operator!=(const expected& __x, const unexpected<_E2>& __y) noexcept { return __x.__has_val_ || static_cast(__x.__union_.__unex_ != __y.error()); } + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI friend constexpr bool operator!=(const unexpected<_E2>& __y, const expected& __x) noexcept { diff --git a/libcudacxx/include/cuda/std/__expected/expected_base.h b/libcudacxx/include/cuda/std/__expected/expected_base.h index 31de97e3f50..0de6cc29158 100644 --- a/libcudacxx/include/cuda/std/__expected/expected_base.h +++ b/libcudacxx/include/cuda/std/__expected/expected_base.h @@ -71,30 +71,35 @@ union __expected_union_t struct __empty_t {}; + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Tp2 = _Tp) _CCCL_REQUIRES(_CCCL_TRAIT(is_default_constructible, _Tp2)) _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t() noexcept(_CCCL_TRAIT(is_nothrow_default_constructible, _Tp2)) : __val_() {} + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Tp2 = _Tp) _CCCL_REQUIRES((!_CCCL_TRAIT(is_default_constructible, _Tp2))) _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t() noexcept : __empty_() {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t(in_place_t, _Args&&... __args) noexcept( _CCCL_TRAIT(is_nothrow_constructible, _Tp, _Args...)) : __val_(_CUDA_VSTD::forward<_Args>(__args)...) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t(unexpect_t, _Args&&... __args) noexcept( _CCCL_TRAIT(is_nothrow_constructible, _Err, _Args...)) : __unex_(_CUDA_VSTD::forward<_Args>(__args)...) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t( __expected_construct_from_invoke_tag, @@ -104,6 +109,7 @@ union __expected_union_t : __val_(_CUDA_VSTD::invoke(_CUDA_VSTD::forward<_Fun>(__fun), _CUDA_VSTD::forward<_Args>(__args)...)) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t( __expected_construct_from_invoke_tag, @@ -128,18 +134,21 @@ union __expected_union_t<_Tp, _Err, true> struct __empty_t {}; + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Tp2 = _Tp) _CCCL_REQUIRES(_CCCL_TRAIT(is_default_constructible, _Tp2)) _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t() noexcept(_CCCL_TRAIT(is_nothrow_default_constructible, _Tp2)) : __val_() {} + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Tp2 = _Tp) _CCCL_REQUIRES((!_CCCL_TRAIT(is_default_constructible, _Tp2))) _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t() noexcept : __empty_() {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t(in_place_t, _Args&&... __args) noexcept( _CCCL_TRAIT(is_nothrow_constructible, _Tp, _Args...)) @@ -152,6 +161,7 @@ union __expected_union_t<_Tp, _Err, true> : __unex_(_CUDA_VSTD::forward<_Args>(__args)...) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t( __expected_construct_from_invoke_tag, @@ -161,6 +171,7 @@ union __expected_union_t<_Tp, _Err, true> : __val_(_CUDA_VSTD::invoke(_CUDA_VSTD::forward<_Fun>(__fun), _CUDA_VSTD::forward<_Args>(__args)...)) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __expected_union_t( __expected_construct_from_invoke_tag, @@ -436,6 +447,7 @@ struct __expected_storage : __expected_destruct<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_storage, __expected_destruct, _Tp, _Err); + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T1, class _T2, class... _Args) _CCCL_REQUIRES(_CCCL_TRAIT(is_nothrow_constructible, _T1, _Args...)) static _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX20 void @@ -445,6 +457,7 @@ struct __expected_storage : __expected_destruct<_Tp, _Err> _LIBCUDACXX_CONSTRUCT_AT(__newval, _CUDA_VSTD::forward<_Args>(__args)...); } + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T1, class _T2, class... _Args) _CCCL_REQUIRES( (!_CCCL_TRAIT(is_nothrow_constructible, _T1, _Args...)) _CCCL_AND _CCCL_TRAIT(is_nothrow_move_constructible, _T1)) @@ -456,6 +469,7 @@ struct __expected_storage : __expected_destruct<_Tp, _Err> _LIBCUDACXX_CONSTRUCT_AT(__newval, _CUDA_VSTD::move(__tmp)); } + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _T1, class _T2, class... _Args) _CCCL_REQUIRES( (!_CCCL_TRAIT(is_nothrow_constructible, _T1, _Args...)) _CCCL_AND(!_CCCL_TRAIT(is_nothrow_move_constructible, _T1))) @@ -475,6 +489,7 @@ struct __expected_storage : __expected_destruct<_Tp, _Err> __trans.__complete(); } + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Err2 = _Err) _CCCL_REQUIRES(_CCCL_TRAIT(is_nothrow_move_constructible, _Err2)) static _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX20 void @@ -493,6 +508,7 @@ struct __expected_storage : __expected_destruct<_Tp, _Err> __with_err.__has_val_ = true; } + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Err2 = _Err) _CCCL_REQUIRES((!_CCCL_TRAIT(is_nothrow_move_constructible, _Err2))) static _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX20 void @@ -653,6 +669,7 @@ struct __expected_copy_assign<_Tp, _Err, __smf_availability::__available> : __ex _CCCL_HIDE_FROM_ABI __expected_copy_assign(const __expected_copy_assign&) = default; _CCCL_HIDE_FROM_ABI __expected_copy_assign(__expected_copy_assign&&) = default; + _CCCL_EXEC_CHECK_DISABLE _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX20 __expected_copy_assign& operator=(const __expected_copy_assign& __other) noexcept( _CCCL_TRAIT(is_nothrow_copy_assignable, _Tp) && _CCCL_TRAIT(is_nothrow_copy_constructible, _Tp) @@ -917,6 +934,7 @@ struct __expected_storage : __expected_destruct { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_storage, __expected_destruct, void, _Err); + _CCCL_EXEC_CHECK_DISABLE static _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX20 void __swap_val_unex_impl( __expected_storage& __with_val, __expected_storage& __with_err) noexcept(_CCCL_TRAIT(is_nothrow_move_constructible, _Err)) diff --git a/libcudacxx/include/cuda/std/__expected/unexpected.h b/libcudacxx/include/cuda/std/__expected/unexpected.h index 0f8f3784374..0da94402a85 100644 --- a/libcudacxx/include/cuda/std/__expected/unexpected.h +++ b/libcudacxx/include/cuda/std/__expected/unexpected.h @@ -73,6 +73,7 @@ class unexpected _CCCL_HIDE_FROM_ABI unexpected(const unexpected&) = default; _CCCL_HIDE_FROM_ABI unexpected(unexpected&&) = default; + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Error = _Err) _CCCL_REQUIRES((!_CCCL_TRAIT(is_same, remove_cvref_t<_Error>, unexpected) && !_CCCL_TRAIT(is_same, remove_cvref_t<_Error>, in_place_t) @@ -82,6 +83,7 @@ class unexpected : __unex_(_CUDA_VSTD::forward<_Error>(__error)) {} + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class... _Args) _CCCL_REQUIRES(_CCCL_TRAIT(is_constructible, _Err, _Args...)) _LIBCUDACXX_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, _Args&&... __args) noexcept( @@ -89,6 +91,7 @@ class unexpected : __unex_(_CUDA_VSTD::forward<_Args>(__args)...) {} + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Up, class... _Args) _CCCL_REQUIRES(_CCCL_TRAIT(is_constructible, _Err, initializer_list<_Up>&, _Args...)) _LIBCUDACXX_HIDE_FROM_ABI constexpr explicit unexpected( @@ -123,6 +126,7 @@ class unexpected } // [expected.un.swap] + _CCCL_EXEC_CHECK_DISABLE _LIBCUDACXX_HIDE_FROM_ABI constexpr void swap(unexpected& __other) noexcept(_CCCL_TRAIT(is_nothrow_swappable, _Err)) { static_assert(_CCCL_TRAIT(is_swappable, _Err), "E must be swappable"); @@ -130,6 +134,7 @@ class unexpected swap(__unex_, __other.__unex_); } + _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _Err2 = _Err) _CCCL_REQUIRES(_CCCL_TRAIT(is_swappable, _Err2)) friend _LIBCUDACXX_HIDE_FROM_ABI constexpr void @@ -140,6 +145,7 @@ class unexpected } // [expected.un.eq] + _CCCL_EXEC_CHECK_DISABLE template _CCCL_NODISCARD_FRIEND _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator==(const unexpected& __lhs, @@ -148,6 +154,7 @@ class unexpected return __lhs.error() == __rhs.error(); } # if _CCCL_STD_VER < 2020 + _CCCL_EXEC_CHECK_DISABLE template _CCCL_NODISCARD_FRIEND _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator!=(const unexpected& __lhs, diff --git a/libcudacxx/include/cuda/std/__memory/construct_at.h b/libcudacxx/include/cuda/std/__memory/construct_at.h index bc231cd27d7..a78314c6479 100644 --- a/libcudacxx/include/cuda/std/__memory/construct_at.h +++ b/libcudacxx/include/cuda/std/__memory/construct_at.h @@ -50,6 +50,7 @@ # ifndef __cpp_lib_constexpr_dynamic_alloc namespace std { +_CCCL_EXEC_CHECK_DISABLE template ()) _Tp(_CUDA_VSTD::declval<_Args>()...))> diff --git a/libcudacxx/include/cuda/std/__utility/pair.h b/libcudacxx/include/cuda/std/__utility/pair.h index e725cf4b001..e8678f58767 100644 --- a/libcudacxx/include/cuda/std/__utility/pair.h +++ b/libcudacxx/include/cuda/std/__utility/pair.h @@ -124,6 +124,7 @@ struct __pair_base _T1 first; _T2 second; + _CCCL_EXEC_CHECK_DISABLE template , enable_if_t<_Constraints::__explicit_default_constructible, int> = 0> _LIBCUDACXX_HIDE_FROM_ABI explicit constexpr __pair_base() noexcept( @@ -132,6 +133,7 @@ struct __pair_base , second() {} + _CCCL_EXEC_CHECK_DISABLE template , enable_if_t<_Constraints::__implicit_default_constructible, int> = 0> _LIBCUDACXX_HIDE_FROM_ABI constexpr __pair_base() noexcept( @@ -140,6 +142,7 @@ struct __pair_base , second() {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __pair_base(_U1&& __t1, _U2&& __t2) noexcept( _CCCL_TRAIT(is_nothrow_constructible, _T1, _U1) && _CCCL_TRAIT(is_nothrow_constructible, _T2, _U2)) @@ -163,6 +166,7 @@ struct __pair_base<_T1, _T2, true> _T1 first; _T2 second; + _CCCL_EXEC_CHECK_DISABLE template , enable_if_t<_Constraints::__explicit_default_constructible, int> = 0> _LIBCUDACXX_HIDE_FROM_ABI explicit constexpr __pair_base() noexcept( @@ -171,6 +175,7 @@ struct __pair_base<_T1, _T2, true> , second() {} + _CCCL_EXEC_CHECK_DISABLE template , enable_if_t<_Constraints::__implicit_default_constructible, int> = 0> _LIBCUDACXX_HIDE_FROM_ABI constexpr __pair_base() noexcept( @@ -179,10 +184,13 @@ struct __pair_base<_T1, _T2, true> , second() {} + _CCCL_EXEC_CHECK_DISABLE _CCCL_HIDE_FROM_ABI constexpr __pair_base(const __pair_base&) = default; - _CCCL_HIDE_FROM_ABI constexpr __pair_base(__pair_base&&) = default; + _CCCL_EXEC_CHECK_DISABLE + _CCCL_HIDE_FROM_ABI constexpr __pair_base(__pair_base&&) = default; // We need to ensure that a reference type, which would inhibit the implicit copy assignment still works + _CCCL_EXEC_CHECK_DISABLE _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 __pair_base& operator=( conditional_t<_CCCL_TRAIT(is_copy_assignable, _T1) && _CCCL_TRAIT(is_copy_assignable, _T2), __pair_base, __nat> const& __p) noexcept(_CCCL_TRAIT(is_nothrow_copy_assignable, _T1) && _CCCL_TRAIT(is_nothrow_copy_assignable, _T2)) @@ -193,6 +201,7 @@ struct __pair_base<_T1, _T2, true> } // We need to ensure that a reference type, which would inhibit the implicit move assignment still works + _CCCL_EXEC_CHECK_DISABLE _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 __pair_base& operator=( conditional_t<_CCCL_TRAIT(is_move_assignable, _T1) && _CCCL_TRAIT(is_move_assignable, _T2), __pair_base, __nat>&& __p) noexcept(_CCCL_TRAIT(is_nothrow_move_assignable, _T1) && _CCCL_TRAIT(is_nothrow_move_assignable, _T2)) @@ -202,6 +211,7 @@ struct __pair_base<_T1, _T2, true> return *this; } + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __pair_base(_U1&& __t1, _U2&& __t2) noexcept( _CCCL_TRAIT(is_nothrow_constructible, _T1, _U1) && _CCCL_TRAIT(is_nothrow_constructible, _T2, _U2)) @@ -532,6 +542,7 @@ _CCCL_HOST_DEVICE pair(_T1, _T2) -> pair<_T1, _T2>; // [pairs.spec], specialized algorithms +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { @@ -540,6 +551,7 @@ _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator==(const pair<_T1, #ifndef _LIBCUDACXX_HAS_NO_SPACESHIP_OPERATOR +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr common_comparison_category_t<__synth_three_way_result<_T1>, __synth_three_way_result<_T2>> @@ -554,30 +566,35 @@ operator<=>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) #else // _LIBCUDACXX_HAS_NO_SPACESHIP_OPERATOR +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { return !(__x == __y); } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second); } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { return __y < __x; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { return !(__x < __y); } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/optional b/libcudacxx/include/cuda/std/detail/libcxx/include/optional index 04f056c91d3..d61ce254f4d 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/optional +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/optional @@ -296,12 +296,14 @@ struct __optional_destruct_base<_Tp, false> , __engaged_(false) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) : __val_(_CUDA_VSTD::forward<_Args>(__args)...) , __engaged_(true) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __optional_destruct_base( __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) @@ -338,12 +340,14 @@ struct __optional_destruct_base<_Tp, true> , __engaged_(false) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) : __val_(_CUDA_VSTD::forward<_Args>(__args)...) , __engaged_(true) {} + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr __optional_destruct_base( __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) @@ -389,6 +393,7 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> return _CUDA_VSTD::move(this->__val_); } + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX20 void __construct(_Args&&... __args) { @@ -410,6 +415,7 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> } } + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr void __assign_from(_That&& __opt) { @@ -811,6 +817,7 @@ public: return this->__get(); } + _CCCL_EXEC_CHECK_DISABLE _LIBCUDACXX_HIDE_FROM_ABI constexpr void swap(optional& __opt) noexcept( _CCCL_TRAIT(is_nothrow_move_constructible, value_type) && _CCCL_TRAIT(is_nothrow_swappable, value_type)) { @@ -1088,6 +1095,7 @@ _CCCL_HOST_DEVICE optional(_Tp) -> optional<_Tp>; # endif // _CCCL_NO_DEDUCTION_GUIDES // Comparisons between optionals +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() == declval()), bool), @@ -1105,6 +1113,7 @@ operator==(const optional<_Tp>& __x, const optional<_Up>& __y) return *__x == *__y; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() != declval()), bool), @@ -1122,6 +1131,7 @@ operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) return *__x != *__y; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() < declval()), bool), @@ -1139,6 +1149,7 @@ operator<(const optional<_Tp>& __x, const optional<_Up>& __y) return *__x < *__y; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() > declval()), bool), @@ -1156,6 +1167,7 @@ operator>(const optional<_Tp>& __x, const optional<_Up>& __y) return *__x > *__y; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() <= declval()), bool), @@ -1173,6 +1185,7 @@ operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) return *__x <= *__y; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() >= declval()), bool), @@ -1264,6 +1277,7 @@ _LIBCUDACXX_HIDE_FROM_ABI constexpr bool operator>=(nullopt_t, const optional<_T } // Comparisons with T +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() == declval()), bool), @@ -1273,6 +1287,7 @@ operator==(const optional<_Tp>& __x, const _Up& __v) return static_cast(__x) ? *__x == __v : false; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() == declval()), bool), @@ -1282,6 +1297,7 @@ operator==(const _Tp& __v, const optional<_Up>& __x) return static_cast(__x) ? __v == *__x : false; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() != declval()), bool), @@ -1291,6 +1307,7 @@ operator!=(const optional<_Tp>& __x, const _Up& __v) return static_cast(__x) ? *__x != __v : true; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() != declval()), bool), @@ -1300,6 +1317,7 @@ operator!=(const _Tp& __v, const optional<_Up>& __x) return static_cast(__x) ? __v != *__x : true; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() < declval()), bool), @@ -1309,6 +1327,7 @@ operator<(const optional<_Tp>& __x, const _Up& __v) return static_cast(__x) ? *__x < __v : true; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() < declval()), bool), @@ -1318,6 +1337,7 @@ operator<(const _Tp& __v, const optional<_Up>& __x) return static_cast(__x) ? __v < *__x : false; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() <= declval()), bool), @@ -1327,6 +1347,7 @@ operator<=(const optional<_Tp>& __x, const _Up& __v) return static_cast(__x) ? *__x <= __v : true; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() <= declval()), bool), @@ -1336,6 +1357,7 @@ operator<=(const _Tp& __v, const optional<_Up>& __x) return static_cast(__x) ? __v <= *__x : false; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() > declval()), bool), @@ -1345,6 +1367,7 @@ operator>(const optional<_Tp>& __x, const _Up& __v) return static_cast(__x) ? *__x > __v : false; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() > declval()), bool), @@ -1354,6 +1377,7 @@ operator>(const _Tp& __v, const optional<_Up>& __x) return static_cast(__x) ? __v > *__x : true; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() >= declval()), bool), @@ -1363,6 +1387,7 @@ operator>=(const optional<_Tp>& __x, const _Up& __v) return static_cast(__x) ? *__x >= __v : false; } +_CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI constexpr enable_if_t< _CCCL_TRAIT(is_convertible, decltype(declval() >= declval()), bool), diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/tuple b/libcudacxx/include/cuda/std/detail/libcxx/include/tuple index aa2fdeaa368..6ff1039e61b 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/tuple +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/tuple @@ -1124,6 +1124,7 @@ _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 tuple<_Tp&&...> forward_as_tuple template struct __tuple_equal { + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator()(const _Tp& __x, const _Up& __y) { @@ -1157,6 +1158,7 @@ _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator!=(const tuple<_Tp. template struct __tuple_less { + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 bool operator()(const _Tp& __x, const _Up& __y) { diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/variant b/libcudacxx/include/cuda/std/detail/libcxx/include/variant index 0f6ec9d29fc..af1f7ba85ad 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/variant +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/variant @@ -255,6 +255,7 @@ C++20 #include #include #include +#include #include #include #include @@ -744,10 +745,22 @@ struct _CCCL_TYPE_VISIBILITY_DEFAULT __alt { using __value_type = _Tp; + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI explicit constexpr __alt(in_place_t, _Args&&... __args) : __value(_CUDA_VSTD::forward<_Args>(__args)...) {} + _CCCL_EXEC_CHECK_DISABLE + constexpr __alt(const __alt&) = default; + _CCCL_EXEC_CHECK_DISABLE + constexpr __alt(__alt&&) = default; + _CCCL_EXEC_CHECK_DISABLE + constexpr __alt& operator=(const __alt&) = default; + _CCCL_EXEC_CHECK_DISABLE + constexpr __alt& operator=(__alt&&) = default; + + _CCCL_EXEC_CHECK_DISABLE + ~__alt() = default; __value_type __value; }; @@ -906,6 +919,7 @@ class _CCCL_TYPE_VISIBILITY_DEFAULT __dtor<__traits<_Types...>, _Trait::_Availab { struct __visitor { + _CCCL_EXEC_CHECK_DISABLE template _LIBCUDACXX_HIDE_FROM_ABI void operator()(_Alt& __alt) const noexcept { @@ -1148,6 +1162,7 @@ public: } protected: + _CCCL_EXEC_CHECK_DISABLE template < size_t _Ip, class _Tp, @@ -1166,6 +1181,7 @@ protected: } } + _CCCL_EXEC_CHECK_DISABLE template < size_t _Ip, class _Tp, @@ -1896,7 +1912,11 @@ private: return __op(_CUDA_VSTD::get<0>(__lhs), _CUDA_VSTD::get<0>(__rhs)); } // We already checked that every variant has a value, so we should never reach this line +# if _CCCL_COMPILER(MSVC) // MSVC needs this to be wrapped in a function or it will error + _CUDA_VSTD::unreachable(); +# else // ^^^ _CCCL_COMPILER(MSVC) ^^^ / vvv !_CCCL_COMPILER(MSVC) vvv _CCCL_UNREACHABLE(); +# endif // !_CCCL_COMPILER(MSVC) } }; diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/expected/device_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/expected/device_only_types.pass.cpp new file mode 100644 index 00000000000..ba972e02d3a --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/expected/device_only_types.pass.cpp @@ -0,0 +1,201 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// We cannot suppress execution checks in cuda::std::construct_at +// XFAIL: c++20 && !nvrtc && nvcc && !msvc +// UNSUPPORTED: clang-14 + +#include +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +__device__ void test() +{ + using expected = cuda::std::expected; + { // default construction + expected default_constructed{}; + assert(default_constructed.has_value()); + assert(*default_constructed == 0); + } + + { // in_place zero initialization + expected in_place_zero_initialization{cuda::std::in_place}; + assert(in_place_zero_initialization.has_value()); + assert(*in_place_zero_initialization == 0); + } + + { // in_place initialization + expected in_place_initialization{cuda::std::in_place, 42}; + assert(in_place_initialization.has_value()); + assert(*in_place_initialization == 42); + } + + { // initializer_list initialization + expected init_list_initialization{cuda::std::in_place, cuda::std::initializer_list{}, 42}; + assert(init_list_initialization.has_value()); + assert(*init_list_initialization == 42); + } + + { // unexpect zero initialization + expected in_place_zero_initialization{cuda::std::unexpect}; + assert(!in_place_zero_initialization.has_value()); + assert(in_place_zero_initialization.error() == 0); + } + + { // unexpect initialization + expected in_place_initialization{cuda::std::unexpect, 42}; + assert(!in_place_initialization.has_value()); + assert(in_place_initialization.error() == 42); + } + + { // initializer_list initialization + expected init_list_initialization{cuda::std::unexpect, cuda::std::initializer_list{}, 42}; + assert(!init_list_initialization.has_value()); + assert(init_list_initialization.error() == 42); + } + + { // value initialization + expected value_initialization{42}; + assert(value_initialization.has_value()); + assert(*value_initialization == 42); + } + + { // copy construction + expected input{42}; + expected dest{input}; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // move construction + expected input{42}; + expected dest{cuda::std::move(input)}; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, value to value + expected input{42}; + expected dest{1337}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, value to empty + expected input{42}; + expected dest{}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, empty to value + expected input{}; + expected dest{1337}; + dest = input; + assert(dest.has_value()); + assert(*dest == 0); + } + + { // assignment, empty to empty + expected input{}; + expected dest{}; + dest = input; + assert(dest.has_value()); + assert(*dest == 0); + } + + { // assignment, error to value + expected input{cuda::std::unexpect, 42}; + expected dest{1337}; + dest = input; + assert(!dest.has_value()); + assert(dest.error() == 42); + } + + { // assignment, value to error + expected input{42}; + expected dest{cuda::std::unexpect, 1337}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, error to error + expected input{cuda::std::unexpect, 42}; + expected dest{cuda::std::unexpect, 1337}; + dest = input; + assert(!dest.has_value()); + assert(dest.error() == 42); + } + + { // comparison with expected with value + expected lhs{42}; + expected rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + } + + { // comparison with expected with error + expected lhs{cuda::std::unexpect, 42}; + expected rhs{cuda::std::unexpect, 1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + } + + { // comparison with type and value + expected expect{42}; + assert(expect == device_only_type{42}); + assert(device_only_type{42} == expect); + assert(expect != device_only_type{1337}); + assert(device_only_type{1337} != expect); + } + + { // comparison with type and error + expected expect{cuda::std::unexpect, 42}; + assert(expect == cuda::std::unexpected{42}); + assert(cuda::std::unexpected{42} == expect); + assert(expect != cuda::std::unexpected{1337}); + assert(cuda::std::unexpected{1337} != expect); + } + + { // swap + expected lhs{42}; + expected rhs{1337}; + lhs.swap(rhs); + assert(*lhs == 1337); + assert(*rhs == 42); + + swap(lhs, rhs); + assert(*lhs == 42); + assert(*rhs == 1337); + } + + { // swap cross error + expected lhs{42}; + expected rhs{cuda::std::unexpect, 1337}; + lhs.swap(rhs); + assert(lhs.error() == 1337); + assert(*rhs == 42); + + swap(lhs, rhs); + assert(*lhs == 42); + assert(rhs.error() == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_DEVICE, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/expected/host_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/expected/host_only_types.pass.cpp new file mode 100644 index 00000000000..282288b7be8 --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/expected/host_only_types.pass.cpp @@ -0,0 +1,199 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: nvrtc + +#include +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +void test() +{ + using expected = cuda::std::expected; + { // default construction + expected default_constructed{}; + assert(default_constructed.has_value()); + assert(*default_constructed == 0); + } + + { // in_place zero initialization + expected in_place_zero_initialization{cuda::std::in_place}; + assert(in_place_zero_initialization.has_value()); + assert(*in_place_zero_initialization == 0); + } + + { // in_place initialization + expected in_place_initialization{cuda::std::in_place, 42}; + assert(in_place_initialization.has_value()); + assert(*in_place_initialization == 42); + } + + { // initializer_list initialization + expected init_list_initialization{cuda::std::in_place, cuda::std::initializer_list{}, 42}; + assert(init_list_initialization.has_value()); + assert(*init_list_initialization == 42); + } + + { // unexpect zero initialization + expected in_place_zero_initialization{cuda::std::unexpect}; + assert(!in_place_zero_initialization.has_value()); + assert(in_place_zero_initialization.error() == 0); + } + + { // unexpect initialization + expected in_place_initialization{cuda::std::unexpect, 42}; + assert(!in_place_initialization.has_value()); + assert(in_place_initialization.error() == 42); + } + + { // initializer_list initialization + expected init_list_initialization{cuda::std::unexpect, cuda::std::initializer_list{}, 42}; + assert(!init_list_initialization.has_value()); + assert(init_list_initialization.error() == 42); + } + + { // value initialization + expected value_initialization{42}; + assert(value_initialization.has_value()); + assert(*value_initialization == 42); + } + + { // copy construction + expected input{42}; + expected dest{input}; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // move construction + expected input{42}; + expected dest{cuda::std::move(input)}; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, value to value + expected input{42}; + expected dest{1337}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, value to empty + expected input{42}; + expected dest{}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, empty to value + expected input{}; + expected dest{1337}; + dest = input; + assert(dest.has_value()); + assert(*dest == 0); + } + + { // assignment, empty to empty + expected input{}; + expected dest{}; + dest = input; + assert(dest.has_value()); + assert(*dest == 0); + } + + { // assignment, error to value + expected input{cuda::std::unexpect, 42}; + expected dest{1337}; + dest = input; + assert(!dest.has_value()); + assert(dest.error() == 42); + } + + { // assignment, value to error + expected input{42}; + expected dest{cuda::std::unexpect, 1337}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, error to error + expected input{cuda::std::unexpect, 42}; + expected dest{cuda::std::unexpect, 1337}; + dest = input; + assert(!dest.has_value()); + assert(dest.error() == 42); + } + + { // comparison with expected with value + expected lhs{42}; + expected rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + } + + { // comparison with expected with error + expected lhs{cuda::std::unexpect, 42}; + expected rhs{cuda::std::unexpect, 1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + } + + { // comparison with type and value + expected expect{42}; + assert(expect == host_only_type{42}); + assert(host_only_type{42} == expect); + assert(expect != host_only_type{1337}); + assert(host_only_type{1337} != expect); + } + + { // comparison with type and error + expected expect{cuda::std::unexpect, 42}; + assert(expect == cuda::std::unexpected{42}); + assert(cuda::std::unexpected{42} == expect); + assert(expect != cuda::std::unexpected{1337}); + assert(cuda::std::unexpected{1337} != expect); + } + + { // swap + expected lhs{42}; + expected rhs{1337}; + lhs.swap(rhs); + assert(*lhs == 1337); + assert(*rhs == 42); + + swap(lhs, rhs); + assert(*lhs == 42); + assert(*rhs == 1337); + } + + { // swap cross error + expected lhs{42}; + expected rhs{cuda::std::unexpect, 1337}; + lhs.swap(rhs); + assert(lhs.error() == 1337); + assert(*rhs == 42); + + swap(lhs, rhs); + assert(*lhs == 42); + assert(rhs.error() == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_HOST, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/optional/device_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/optional/device_only_types.pass.cpp new file mode 100644 index 00000000000..766b6ae821c --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/optional/device_only_types.pass.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// We cannot suppress execution checks in cuda::std::construct_at +// XFAIL: c++20 && !nvrtc && nvcc && !msvc +// UNSUPPORTED: clang-14 + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +__device__ void test() +{ + using optional = cuda::std::optional; + { // default construction + optional default_constructed{}; + assert(!default_constructed.has_value()); + } + + { // in_place zero initialization + optional in_place_zero_initialization{cuda::std::in_place}; + assert(in_place_zero_initialization.has_value()); + assert(*in_place_zero_initialization == 0); + } + + { // in_place initialization + optional in_place_initialization{cuda::std::in_place, 42}; + assert(in_place_initialization.has_value()); + assert(*in_place_initialization == 42); + } + + { // value initialization + optional value_initialization{42}; + assert(value_initialization.has_value()); + assert(*value_initialization == 42); + } + + { // copy construction + optional input{42}; + optional dest{input}; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // move construction + optional input{42}; + optional dest{cuda::std::move(input)}; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, value to value + optional input{42}; + optional dest{1337}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, value to empty + optional input{42}; + optional dest{}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, empty to value + optional input{}; + optional dest{1337}; + dest = input; + assert(!dest.has_value()); + } + + { // assignment, empty to empty + optional input{}; + optional dest{}; + dest = input; + assert(!dest.has_value()); + } + + { // comparison with optional + optional lhs{42}; + optional rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + assert(lhs < rhs); + assert(lhs <= rhs); + assert(!(lhs > rhs)); + assert(!(lhs >= rhs)); + } + + { // comparison with type + optional opt{42}; + assert(opt == device_only_type{42}); + assert(device_only_type{42} == opt); + assert(opt != device_only_type{1337}); + assert(device_only_type{1337} != opt); + + assert(opt < device_only_type{1337}); + assert(device_only_type{7} < opt); + assert(opt <= device_only_type{1337}); + assert(device_only_type{7} <= opt); + + assert(opt > device_only_type{7}); + assert(device_only_type{1337} > opt); + assert(opt >= device_only_type{7}); + assert(device_only_type{1337} >= opt); + } + + { // swap + optional lhs{42}; + optional rhs{1337}; + lhs.swap(rhs); + assert(*lhs == 1337); + assert(*rhs == 42); + + swap(lhs, rhs); + assert(*lhs == 42); + assert(*rhs == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_DEVICE, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/optional/host_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/optional/host_only_types.pass.cpp new file mode 100644 index 00000000000..3bf26d0fb2e --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/optional/host_only_types.pass.cpp @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: nvrtc + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +void test() +{ + using optional = cuda::std::optional; + { // default construction + optional default_constructed{}; + assert(!default_constructed.has_value()); + } + + { // in_place zero initialization + optional in_place_zero_initialization{cuda::std::in_place}; + assert(in_place_zero_initialization.has_value()); + assert(*in_place_zero_initialization == 0); + } + + { // in_place initialization + optional in_place_initialization{cuda::std::in_place, 42}; + assert(in_place_initialization.has_value()); + assert(*in_place_initialization == 42); + } + + { // value initialization + optional value_initialization{42}; + assert(value_initialization.has_value()); + assert(*value_initialization == 42); + } + + { // copy construction + optional input{42}; + optional dest{input}; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // move construction + optional input{42}; + optional dest{cuda::std::move(input)}; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, value to value + optional input{42}; + optional dest{1337}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, value to empty + optional input{42}; + optional dest{}; + dest = input; + assert(dest.has_value()); + assert(*dest == 42); + } + + { // assignment, empty to value + optional input{}; + optional dest{1337}; + dest = input; + assert(!dest.has_value()); + } + + { // assignment, empty to empty + optional input{}; + optional dest{}; + dest = input; + assert(!dest.has_value()); + } + + { // comparison with optional + optional lhs{42}; + optional rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + assert(lhs < rhs); + assert(lhs <= rhs); + assert(!(lhs > rhs)); + assert(!(lhs >= rhs)); + } + + { // comparison with type + optional opt{42}; + assert(opt == host_only_type{42}); + assert(host_only_type{42} == opt); + assert(opt != host_only_type{1337}); + assert(host_only_type{1337} != opt); + + assert(opt < host_only_type{1337}); + assert(host_only_type{7} < opt); + assert(opt <= host_only_type{1337}); + assert(host_only_type{7} <= opt); + + assert(opt > host_only_type{7}); + assert(host_only_type{1337} > opt); + assert(opt >= host_only_type{7}); + assert(host_only_type{1337} >= opt); + } + + { // swap + optional lhs{42}; + optional rhs{1337}; + lhs.swap(rhs); + assert(*lhs == 1337); + assert(*rhs == 42); + + swap(lhs, rhs); + assert(*lhs == 42); + assert(*rhs == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_HOST, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/tuple/device_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/device_only_types.pass.cpp new file mode 100644 index 00000000000..d8820409d10 --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/device_only_types.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +__device__ void test() +{ + using tuple = cuda::std::tuple; + { // default construction + tuple default_constructed{}; + assert(cuda::std::get<0>(default_constructed) == 0); + } + + { // value initialization + tuple value_initialization{device_only_type{42}}; + assert(cuda::std::get<0>(value_initialization) == 42); + } + + { // value initialization + tuple value_initialization{42}; + assert(cuda::std::get<0>(value_initialization) == 42); + } + + { // copy construction + tuple input{42}; + tuple dest{input}; + assert(cuda::std::get<0>(dest) == 42); + } + + { // move construction + tuple input{42}; + tuple dest{cuda::std::move(input)}; + assert(cuda::std::get<0>(dest) == 42); + } + + { // assignment, value to value + tuple input{42}; + tuple dest{1337}; + dest = input; + assert(cuda::std::get<0>(dest) == 42); + } + + { // comparison with tuple + tuple lhs{42}; + tuple rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + assert(lhs < rhs); + assert(lhs <= rhs); + assert(!(lhs > rhs)); + assert(!(lhs >= rhs)); + } + + { // swap + tuple lhs{42}; + tuple rhs{1337}; + lhs.swap(rhs); + assert(cuda::std::get<0>(lhs) == 1337); + assert(cuda::std::get<0>(rhs) == 42); + + swap(lhs, rhs); + assert(cuda::std::get<0>(lhs) == 42); + assert(cuda::std::get<0>(rhs) == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_DEVICE, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/tuple/forward_as_tuple_interop.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/forward_as_tuple_interop.pass.cpp similarity index 100% rename from libcudacxx/test/libcudacxx/cuda/tuple/forward_as_tuple_interop.pass.cpp rename to libcudacxx/test/libcudacxx/cuda/utilities/tuple/forward_as_tuple_interop.pass.cpp diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/tuple/host_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/host_only_types.pass.cpp new file mode 100644 index 00000000000..4942d051b1c --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/host_only_types.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: nvrtc + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +void test() +{ + using tuple = cuda::std::tuple; + { // default construction + tuple default_constructed{}; + assert(cuda::std::get<0>(default_constructed) == 0); + } + + { // value initialization + tuple value_initialization{host_only_type{42}}; + assert(cuda::std::get<0>(value_initialization) == 42); + } + + { // value initialization + tuple value_initialization{42}; + assert(cuda::std::get<0>(value_initialization) == 42); + } + + { // copy construction + tuple input{42}; + tuple dest{input}; + assert(cuda::std::get<0>(dest) == 42); + } + + { // move construction + tuple input{42}; + tuple dest{cuda::std::move(input)}; + assert(cuda::std::get<0>(dest) == 42); + } + + { // assignment, value to value + tuple input{42}; + tuple dest{1337}; + dest = input; + assert(cuda::std::get<0>(dest) == 42); + } + + { // assignment, value to empty + tuple input{42}; + tuple dest{}; + dest = input; + assert(cuda::std::get<0>(dest) == 42); + } + + { // comparison with tuple + tuple lhs{42}; + tuple rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + assert(lhs < rhs); + assert(lhs <= rhs); + assert(!(lhs > rhs)); + assert(!(lhs >= rhs)); + } + + { // swap + tuple lhs{42}; + tuple rhs{1337}; + lhs.swap(rhs); + assert(cuda::std::get<0>(lhs) == 1337); + assert(cuda::std::get<0>(rhs) == 42); + + swap(lhs, rhs); + assert(cuda::std::get<0>(lhs) == 42); + assert(cuda::std::get<0>(rhs) == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_HOST, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/tuple/vector_types_get.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/vector_types_get.pass.cpp similarity index 100% rename from libcudacxx/test/libcudacxx/cuda/tuple/vector_types_get.pass.cpp rename to libcudacxx/test/libcudacxx/cuda/utilities/tuple/vector_types_get.pass.cpp diff --git a/libcudacxx/test/libcudacxx/cuda/tuple/vector_types_structured_bindings.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/vector_types_structured_bindings.pass.cpp similarity index 100% rename from libcudacxx/test/libcudacxx/cuda/tuple/vector_types_structured_bindings.pass.cpp rename to libcudacxx/test/libcudacxx/cuda/utilities/tuple/vector_types_structured_bindings.pass.cpp diff --git a/libcudacxx/test/libcudacxx/cuda/tuple/vector_types_tuple_element.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/vector_types_tuple_element.pass.cpp similarity index 100% rename from libcudacxx/test/libcudacxx/cuda/tuple/vector_types_tuple_element.pass.cpp rename to libcudacxx/test/libcudacxx/cuda/utilities/tuple/vector_types_tuple_element.pass.cpp diff --git a/libcudacxx/test/libcudacxx/cuda/tuple/vector_types_tuple_size.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/tuple/vector_types_tuple_size.pass.cpp similarity index 100% rename from libcudacxx/test/libcudacxx/cuda/tuple/vector_types_tuple_size.pass.cpp rename to libcudacxx/test/libcudacxx/cuda/utilities/tuple/vector_types_tuple_size.pass.cpp diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/unexpected/device_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/unexpected/device_only_types.pass.cpp new file mode 100644 index 00000000000..f36e86c2c3f --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/unexpected/device_only_types.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +__device__ void test() +{ + using unexpected = cuda::std::unexpected; + { // in_place zero initialization + unexpected in_place_zero_initialization{cuda::std::in_place}; + assert(in_place_zero_initialization.error() == 0); + } + + { // in_place initialization + unexpected in_place_initialization{cuda::std::in_place, 42}; + assert(in_place_initialization.error() == 42); + } + + { // value initialization + unexpected value_initialization{42}; + assert(value_initialization.error() == 42); + } + + { // initializer_list initialization + unexpected init_list_initialization{cuda::std::in_place, cuda::std::initializer_list{}, 42}; + assert(init_list_initialization.error() == 42); + } + + { // copy construction + unexpected input{42}; + unexpected dest{input}; + assert(dest.error() == 42); + } + + { // move construction + unexpected input{42}; + unexpected dest{cuda::std::move(input)}; + assert(dest.error() == 42); + } + + { // assignment + unexpected input{42}; + unexpected dest{1337}; + dest = input; + assert(dest.error() == 42); + } + + { // comparison with unexpected + unexpected lhs{42}; + unexpected rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + } + + { // swap + unexpected lhs{42}; + unexpected rhs{1337}; + lhs.swap(rhs); + assert(lhs.error() == 1337); + assert(rhs.error() == 42); + + swap(lhs, rhs); + assert(lhs.error() == 42); + assert(rhs.error() == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_DEVICE, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/unexpected/host_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/unexpected/host_only_types.pass.cpp new file mode 100644 index 00000000000..ca12494418c --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/unexpected/host_only_types.pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: nvrtc + +#include +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +void test() +{ + using unexpected = cuda::std::unexpected; + { // in_place zero initialization + unexpected in_place_zero_initialization{cuda::std::in_place}; + assert(in_place_zero_initialization.error() == 0); + } + + { // in_place initialization + unexpected in_place_initialization{cuda::std::in_place, 42}; + assert(in_place_initialization.error() == 42); + } + + { // value initialization + unexpected value_initialization{42}; + assert(value_initialization.error() == 42); + } + + { // initializer_list initialization + unexpected init_list_initialization{cuda::std::in_place, cuda::std::initializer_list{}, 42}; + assert(init_list_initialization.error() == 42); + } + + { // copy construction + unexpected input{42}; + unexpected dest{input}; + assert(dest.error() == 42); + } + + { // move construction + unexpected input{42}; + unexpected dest{cuda::std::move(input)}; + assert(dest.error() == 42); + } + + { // assignment + unexpected input{42}; + unexpected dest{1337}; + dest = input; + assert(dest.error() == 42); + } + + { // comparison with unexpected + unexpected lhs{42}; + unexpected rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + } + + { // swap + unexpected lhs{42}; + unexpected rhs{1337}; + lhs.swap(rhs); + assert(lhs.error() == 1337); + assert(rhs.error() == 42); + + swap(lhs, rhs); + assert(lhs.error() == 42); + assert(rhs.error() == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_HOST, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/device_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/device_only_types.pass.cpp new file mode 100644 index 00000000000..aebdd6e12ea --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/device_only_types.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: nvrtc + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +__device__ void test() +{ + using pair = cuda::std::pair; + { // default construction + pair default_constructed{}; + assert(default_constructed.first == 0); + assert(default_constructed.second == 0); + } + + { // value initialization + pair value_initialization{device_only_type{42}, device_only_type{1337}}; + assert(value_initialization.first == 42); + assert(value_initialization.second == 1337); + } + + { // value initialization + pair value_initialization{42, 1337}; + assert(value_initialization.first == 42); + assert(value_initialization.second == 1337); + } + + { // copy construction + pair input{42, 1337}; + pair dest{input}; + assert(dest.first == 42); + assert(dest.second == 1337); + } + + { // move construction + pair input{42, 1337}; + pair dest{cuda::std::move(input)}; + assert(dest.first == 42); + assert(dest.second == 1337); + } + + { // assignment, value to value + pair input{42, 1337}; + pair dest{1337, 42}; + dest = input; + assert(dest.first == 42); + assert(dest.second == 1337); + } + + { // comparison with pair + pair lhs{42, 1337}; + pair rhs{1337, 42}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + assert(lhs < rhs); + assert(lhs <= rhs); + assert(!(lhs > rhs)); + assert(!(lhs >= rhs)); + } + + { // swap + pair lhs{42, 1337}; + pair rhs{1337, 42}; + lhs.swap(rhs); + assert(lhs.first == 1337); + assert(lhs.second == 42); + assert(rhs.first == 42); + assert(rhs.second == 1337); + + swap(lhs, rhs); + assert(lhs.first == 42); + assert(lhs.second == 1337); + assert(rhs.first == 1337); + assert(rhs.second == 42); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_DEVICE, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/host_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/host_only_types.pass.cpp new file mode 100644 index 00000000000..cf1195f204d --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/host_only_types.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: nvrtc + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +void test() +{ + using pair = cuda::std::pair; + { // default construction + pair default_constructed{}; + assert(default_constructed.first == 0); + assert(default_constructed.second == 0); + } + + { // value initialization + pair value_initialization{host_only_type{42}, host_only_type{1337}}; + assert(value_initialization.first == 42); + assert(value_initialization.second == 1337); + } + + { // value initialization + pair value_initialization{42, 1337}; + assert(value_initialization.first == 42); + assert(value_initialization.second == 1337); + } + + { // copy construction + pair input{42, 1337}; + pair dest{input}; + assert(dest.first == 42); + assert(dest.second == 1337); + } + + { // move construction + pair input{42, 1337}; + pair dest{cuda::std::move(input)}; + assert(dest.first == 42); + assert(dest.second == 1337); + } + + { // assignment, value to value + pair input{42, 1337}; + pair dest{1337, 42}; + dest = input; + assert(dest.first == 42); + assert(dest.second == 1337); + } + + { // comparison with pair + pair lhs{42, 1337}; + pair rhs{1337, 42}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + assert(lhs < rhs); + assert(lhs <= rhs); + assert(!(lhs > rhs)); + assert(!(lhs >= rhs)); + } + + { // swap + pair lhs{42, 1337}; + pair rhs{1337, 42}; + lhs.swap(rhs); + assert(lhs.first == 1337); + assert(lhs.second == 42); + assert(rhs.first == 42); + assert(rhs.second == 1337); + + swap(lhs, rhs); + assert(lhs.first == 42); + assert(lhs.second == 1337); + assert(rhs.first == 1337); + assert(rhs.second == 42); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_HOST, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/pair_interop/pair.assign.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/interop/pair.assign.pass.cpp similarity index 100% rename from libcudacxx/test/libcudacxx/cuda/pair_interop/pair.assign.pass.cpp rename to libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/interop/pair.assign.pass.cpp diff --git a/libcudacxx/test/libcudacxx/cuda/pair_interop/pair.cons.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/interop/pair.cons.pass.cpp similarity index 100% rename from libcudacxx/test/libcudacxx/cuda/pair_interop/pair.cons.pass.cpp rename to libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/interop/pair.cons.pass.cpp diff --git a/libcudacxx/test/libcudacxx/cuda/pair_interop/pair.conv.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/interop/pair.conv.pass.cpp similarity index 100% rename from libcudacxx/test/libcudacxx/cuda/pair_interop/pair.conv.pass.cpp rename to libcudacxx/test/libcudacxx/cuda/utilities/utility/pair/interop/pair.conv.pass.cpp diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/variant/device_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/variant/device_only_types.pass.cpp new file mode 100644 index 00000000000..38ee416a8fc --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/variant/device_only_types.pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +__device__ void test() +{ + using variant = cuda::std::variant; + { // default construction + variant default_constructed{}; + assert(cuda::std::get<0>(default_constructed) == 0); + } + + { // value initialization + variant value_initialization{device_only_type{42}}; + assert(cuda::std::get<0>(value_initialization) == 42); + } + + { // value initialization + variant value_initialization{42}; + assert(cuda::std::get<0>(value_initialization) == 42); + } + + { // in_place_type_t initialization + variant in_place_initialization{cuda::std::in_place_type_t{}, 42}; + assert(cuda::std::get<0>(in_place_initialization) == 42); + } + + { // in_place_index_t initialization + variant in_place_initialization{cuda::std::in_place_index_t<0>{}, 42}; + assert(cuda::std::get<0>(in_place_initialization) == 42); + } + + { // in_place_type_t initializer_list initialization + variant init_list_initialization{ + cuda::std::in_place_type_t{}, cuda::std::initializer_list{}, 42}; + assert(cuda::std::get<0>(init_list_initialization) == 42); + } + + { // in_place_type_t initializer_list initialization + variant init_list_initialization{cuda::std::in_place_index_t<0>{}, cuda::std::initializer_list{}, 42}; + assert(cuda::std::get<0>(init_list_initialization) == 42); + } + + { // copy construction + variant input{42}; + variant dest{input}; + assert(cuda::std::get<0>(dest) == 42); + } + + { // move construction + variant input{42}; + variant dest{cuda::std::move(input)}; + assert(cuda::std::get<0>(dest) == 42); + } + + { // assignment, value to value + variant input{42}; + variant dest{1337}; + dest = input; + assert(cuda::std::get<0>(dest) == 42); + } + + { // emplace + variant var{42}; + var.emplace(42); + assert(cuda::std::get<0>(var) == 42); + } + + { // emplace + variant var{42}; + var.emplace<0>(42); + assert(cuda::std::get<0>(var) == 42); + } + + { // emplace init list + variant var{42}; + var.emplace(cuda::std::initializer_list{}, 42); + assert(cuda::std::get<0>(var) == 42); + } + + { // comparison with variant + variant lhs{42}; + variant rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + assert(lhs < rhs); + assert(lhs <= rhs); + assert(!(lhs > rhs)); + assert(!(lhs >= rhs)); + } + + { // swap + variant lhs{42}; + variant rhs{1337}; + lhs.swap(rhs); + assert(cuda::std::get<0>(lhs) == 1337); + assert(cuda::std::get<0>(rhs) == 42); + + swap(lhs, rhs); + assert(cuda::std::get<0>(lhs) == 42); + assert(cuda::std::get<0>(rhs) == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_DEVICE, (test();)) + return 0; +} diff --git a/libcudacxx/test/libcudacxx/cuda/utilities/variant/host_only_types.pass.cpp b/libcudacxx/test/libcudacxx/cuda/utilities/variant/host_only_types.pass.cpp new file mode 100644 index 00000000000..5f12da6074b --- /dev/null +++ b/libcudacxx/test/libcudacxx/cuda/utilities/variant/host_only_types.pass.cpp @@ -0,0 +1,129 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: nvrtc + +#include +#include + +#include "host_device_types.h" +#include "test_macros.h" + +void test() +{ + using variant = cuda::std::variant; + { // default construction + variant default_constructed{}; + assert(cuda::std::get<0>(default_constructed) == 0); + } + + { // value initialization + variant value_initialization{host_only_type{42}}; + assert(cuda::std::get<0>(value_initialization) == 42); + } + + { // value initialization + variant value_initialization{42}; + assert(cuda::std::get<0>(value_initialization) == 42); + } + + { // in_place_type_t initialization + variant in_place_initialization{cuda::std::in_place_type_t{}, 42}; + assert(cuda::std::get<0>(in_place_initialization) == 42); + } + + { // in_place_index_t initialization + variant in_place_initialization{cuda::std::in_place_index_t<0>{}, 42}; + assert(cuda::std::get<0>(in_place_initialization) == 42); + } + + { // in_place_type_t initializer_list initialization + variant init_list_initialization{ + cuda::std::in_place_type_t{}, cuda::std::initializer_list{}, 42}; + assert(cuda::std::get<0>(init_list_initialization) == 42); + } + + { // in_place_type_t initializer_list initialization + variant init_list_initialization{cuda::std::in_place_index_t<0>{}, cuda::std::initializer_list{}, 42}; + assert(cuda::std::get<0>(init_list_initialization) == 42); + } + + { // copy construction + variant input{42}; + variant dest{input}; + assert(cuda::std::get<0>(dest) == 42); + } + + { // move construction + variant input{42}; + variant dest{cuda::std::move(input)}; + assert(cuda::std::get<0>(dest) == 42); + } + + { // assignment, value to value + variant input{42}; + variant dest{1337}; + dest = input; + assert(cuda::std::get<0>(dest) == 42); + } + + { // assignment, value to empty + variant input{42}; + variant dest{}; + dest = input; + assert(cuda::std::get<0>(dest) == 42); + } + + { // emplace + variant var{42}; + var.emplace(42); + assert(cuda::std::get<0>(var) == 42); + } + + { // emplace + variant var{42}; + var.emplace<0>(42); + assert(cuda::std::get<0>(var) == 42); + } + + { // emplace init list + variant var{42}; + var.emplace(cuda::std::initializer_list{}, 42); + assert(cuda::std::get<0>(var) == 42); + } + + { // comparison with variant + variant lhs{42}; + variant rhs{1337}; + assert(!(lhs == rhs)); + assert(lhs != rhs); + assert(lhs < rhs); + assert(lhs <= rhs); + assert(!(lhs > rhs)); + assert(!(lhs >= rhs)); + } + + { // swap + variant lhs{42}; + variant rhs{1337}; + lhs.swap(rhs); + assert(cuda::std::get<0>(lhs) == 1337); + assert(cuda::std::get<0>(rhs) == 42); + + swap(lhs, rhs); + assert(cuda::std::get<0>(lhs) == 42); + assert(cuda::std::get<0>(rhs) == 1337); + } +} + +int main(int arg, char** argv) +{ + NV_IF_TARGET(NV_IS_HOST, (test();)) + return 0; +} diff --git a/libcudacxx/test/support/host_device_types.h b/libcudacxx/test/support/host_device_types.h new file mode 100644 index 00000000000..e8fa21b85b9 --- /dev/null +++ b/libcudacxx/test/support/host_device_types.h @@ -0,0 +1,148 @@ +//===----------------------------------------------------------------------===// +// +// Part of the libcu++ 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 +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_SUPPORT_HOST_DEVICE_TYPES +#define TEST_SUPPORT_HOST_DEVICE_TYPES + +#include +#include + +#if !_CCCL_COMPILER(NVRTC) +struct host_only_type +{ + int val_; + + host_only_type(const int val = 0) noexcept + : val_(val) + {} + host_only_type(cuda::std::initializer_list, const int val) noexcept + : val_(val) + {} + + host_only_type(const host_only_type& other) noexcept + : val_(other.val_) + {} + host_only_type(host_only_type&& other) noexcept + : val_(cuda::std::exchange(other.val_, -1)) + {} + + host_only_type& operator=(const host_only_type& other) noexcept + { + val_ = other.val_; + return *this; + } + + host_only_type& operator=(host_only_type&& other) noexcept + + { + val_ = cuda::std::exchange(other.val_, -1); + return *this; + } + + ~host_only_type() noexcept {} + + _CCCL_NODISCARD_FRIEND bool operator==(const host_only_type& lhs, const host_only_type& rhs) noexcept + { + return lhs.val_ == rhs.val_; + } + _CCCL_NODISCARD_FRIEND bool operator!=(const host_only_type& lhs, const host_only_type& rhs) noexcept + { + return lhs.val_ != rhs.val_; + } + _CCCL_NODISCARD_FRIEND bool operator<(const host_only_type& lhs, const host_only_type& rhs) noexcept + { + return lhs.val_ < rhs.val_; + } + _CCCL_NODISCARD_FRIEND bool operator<=(const host_only_type& lhs, const host_only_type& rhs) noexcept + { + return lhs.val_ <= rhs.val_; + } + _CCCL_NODISCARD_FRIEND bool operator>(const host_only_type& lhs, const host_only_type& rhs) noexcept + { + return lhs.val_ > rhs.val_; + } + _CCCL_NODISCARD_FRIEND bool operator>=(const host_only_type& lhs, const host_only_type& rhs) noexcept + { + return lhs.val_ >= rhs.val_; + } + + void swap(host_only_type& other) noexcept + { + cuda::std::swap(val_, other.val_); + } +}; +#endif // !_CCCL_COMPILER(NVRTC) + +#if _CCCL_HAS_CUDA_COMPILER +struct device_only_type +{ + int val_; + + __device__ device_only_type(const int val = 0) noexcept + : val_(val) + {} + __device__ device_only_type(cuda::std::initializer_list, const int val) noexcept + : val_(val) + {} + + __device__ device_only_type(const device_only_type& other) noexcept + : val_(other.val_) + {} + __device__ device_only_type(device_only_type&& other) noexcept + : val_(cuda::std::exchange(other.val_, -1)) + {} + + __device__ device_only_type& operator=(const device_only_type& other) noexcept + { + val_ = other.val_; + return *this; + } + + __device__ device_only_type& operator=(device_only_type&& other) noexcept + + { + val_ = cuda::std::exchange(other.val_, -1); + return *this; + } + + __device__ ~device_only_type() noexcept {} + + __device__ _CCCL_NODISCARD_FRIEND bool operator==(const device_only_type& lhs, const device_only_type& rhs) noexcept + { + return lhs.val_ == rhs.val_; + } + __device__ _CCCL_NODISCARD_FRIEND bool operator!=(const device_only_type& lhs, const device_only_type& rhs) noexcept + { + return lhs.val_ != rhs.val_; + } + __device__ _CCCL_NODISCARD_FRIEND bool operator<(const device_only_type& lhs, const device_only_type& rhs) noexcept + { + return lhs.val_ < rhs.val_; + } + __device__ _CCCL_NODISCARD_FRIEND bool operator<=(const device_only_type& lhs, const device_only_type& rhs) noexcept + { + return lhs.val_ <= rhs.val_; + } + __device__ _CCCL_NODISCARD_FRIEND bool operator>(const device_only_type& lhs, const device_only_type& rhs) noexcept + { + return lhs.val_ > rhs.val_; + } + __device__ _CCCL_NODISCARD_FRIEND bool operator>=(const device_only_type& lhs, const device_only_type& rhs) noexcept + { + return lhs.val_ >= rhs.val_; + } + + __device__ void swap(device_only_type& other) noexcept + { + cuda::std::swap(val_, other.val_); + } +}; +#endif // _CCCL_HAS_CUDA_COMPILER + +#endif // TEST_SUPPORT_HOST_DEVICE_TYPES