From 08a4b660592ea5dd488812f3ec4c3c07891b0fec Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Tue, 14 May 2024 23:27:56 -0700 Subject: [PATCH] Avoid ABI issues due to MSVC EBCO issues (#1739) * Ensure that `variant` SFINAE base classes do use EBCO * Ensure that `expected` SFINAE base classes do use EBCO * Ensure that `optional` SFINAE base classes do use EBCO MSVC allows empty base class optimization only for the last base class. So we cannot use multiple inheritance --- .../include/cuda/std/__expected/expected.h | 10 +- .../cuda/std/__expected/expected_base.h | 164 ++++++++++++------ .../cuda/std/__tuple_dir/sfinae_helpers.h | 95 +++++----- .../cuda/std/detail/libcxx/include/optional | 111 +++++++++--- .../cuda/std/detail/libcxx/include/variant | 6 +- .../assign/assign.copy.pass.cpp | 2 + .../expected.void/object_size.pass.cpp | 36 ++++ .../optional.object/object_size.pass.cpp | 26 +++ .../variant.variant/object_size.pass.cpp | 33 ++++ 9 files changed, 349 insertions(+), 134 deletions(-) create mode 100644 libcudacxx/test/libcudacxx/std/utilities/expected/expected.void/object_size.pass.cpp create mode 100644 libcudacxx/test/libcudacxx/std/utilities/optional/optional.object/object_size.pass.cpp create mode 100644 libcudacxx/test/libcudacxx/std/utilities/variant/variant.variant/object_size.pass.cpp diff --git a/libcudacxx/include/cuda/std/__expected/expected.h b/libcudacxx/include/cuda/std/__expected/expected.h index 5e891de1b39..5166aafaa75 100644 --- a/libcudacxx/include/cuda/std/__expected/expected.h +++ b/libcudacxx/include/cuda/std/__expected/expected.h @@ -103,10 +103,7 @@ _LIBCUDACXX_INLINE_VAR constexpr bool __can_swap = } // namespace __expected template -class expected - : private __expected_move_assign<_Tp, _Err> - , private __expected_sfinae_ctor_base_t<_Tp, _Err> - , private __expected_sfinae_assign_base_t<_Tp, _Err> +class expected : private __expected_move_assign<_Tp, _Err> { using __base = __expected_move_assign<_Tp, _Err>; @@ -1212,10 +1209,7 @@ class expected }; template -class expected - : private __expected_move_assign - , private __expected_void_sfinae_ctor_base_t<_Err> - , private __expected_void_sfinae_assign_base_t<_Err> +class expected : private __expected_move_assign { using __base = __expected_move_assign; static_assert(__unexpected::__valid_unexpected<_Err>, diff --git a/libcudacxx/include/cuda/std/__expected/expected_base.h b/libcudacxx/include/cuda/std/__expected/expected_base.h index ca65590de3c..8343f566474 100644 --- a/libcudacxx/include/cuda/std/__expected/expected_base.h +++ b/libcudacxx/include/cuda/std/__expected/expected_base.h @@ -518,17 +518,24 @@ struct __expected_storage : __expected_destruct<_Tp, _Err> } }; -template +template +_LIBCUDACXX_INLINE_VAR constexpr __smf_availability __expected_can_copy_construct = + (_CCCL_TRAIT(is_trivially_copy_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_trivially_copy_constructible, _Err) + ? __smf_availability::__trivial + : (_CCCL_TRAIT(is_copy_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_copy_constructible, _Err) + ? __smf_availability::__available + : __smf_availability::__deleted; + +template > struct __expected_copy : __expected_storage<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_copy, __expected_storage, _Tp, _Err); }; template -struct __expected_copy<_Tp, _Err, false> : __expected_storage<_Tp, _Err> +struct __expected_copy<_Tp, _Err, __smf_availability::__available> : __expected_storage<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_copy, __expected_storage, _Tp, _Err); @@ -551,17 +558,35 @@ struct __expected_copy<_Tp, _Err, false> : __expected_storage<_Tp, _Err> __expected_copy& operator=(__expected_copy&&) = default; }; -template +template +struct __expected_copy<_Tp, _Err, __smf_availability::__deleted> : __expected_storage<_Tp, _Err> +{ + _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_copy, __expected_storage, _Tp, _Err); + + __expected_copy(const __expected_copy&) = delete; + __expected_copy(__expected_copy&&) = default; + __expected_copy& operator=(const __expected_copy&) = default; + __expected_copy& operator=(__expected_copy&&) = default; +}; + +template +_LIBCUDACXX_INLINE_VAR constexpr __smf_availability __expected_can_move_construct = + (_CCCL_TRAIT(is_trivially_move_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_trivially_move_constructible, _Err) + ? __smf_availability::__trivial + : (_CCCL_TRAIT(is_move_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_move_constructible, _Err) + ? __smf_availability::__available + : __smf_availability::__deleted; + +template > struct __expected_move : __expected_copy<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_move, __expected_copy, _Tp, _Err); }; template -struct __expected_move<_Tp, _Err, false> : __expected_copy<_Tp, _Err> +struct __expected_move<_Tp, _Err, __smf_availability::__available> : __expected_copy<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_move, __expected_copy, _Tp, _Err); @@ -585,21 +610,46 @@ struct __expected_move<_Tp, _Err, false> : __expected_copy<_Tp, _Err> __expected_move& operator=(__expected_move&&) = default; }; -template +template +struct __expected_move<_Tp, _Err, __smf_availability::__deleted> : __expected_copy<_Tp, _Err> +{ + _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_move, __expected_copy, _Tp, _Err); + + __expected_move(const __expected_move&) = default; + __expected_move(__expected_move&&) = delete; + __expected_move& operator=(const __expected_move&) = default; + __expected_move& operator=(__expected_move&&) = default; +}; + +// Need to also check against is_nothrow_move_constructible in the trivial case as that is stupidly in the constraints +template +_LIBCUDACXX_INLINE_VAR constexpr __smf_availability __expected_can_copy_assign = + (_CCCL_TRAIT(is_trivially_destructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_trivially_destructible, _Err) + && (_CCCL_TRAIT(is_trivially_copy_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_trivially_copy_constructible, _Err) + && (_CCCL_TRAIT(is_trivially_copy_assignable, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_trivially_copy_assignable, _Err) + && (_CCCL_TRAIT(is_nothrow_move_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void) + || _CCCL_TRAIT(is_nothrow_move_constructible, _Err)) + ? __smf_availability::__trivial + : (_CCCL_TRAIT(is_copy_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_copy_constructible, _Err) + && (_CCCL_TRAIT(is_copy_assignable, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_copy_assignable, _Err) + && (_CCCL_TRAIT(is_nothrow_move_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void) + || _CCCL_TRAIT(is_nothrow_move_constructible, _Err)) + ? __smf_availability::__available + : __smf_availability::__deleted; + +template > struct __expected_copy_assign : __expected_move<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_copy_assign, __expected_move, _Tp, _Err); }; template -struct __expected_copy_assign<_Tp, _Err, false> : __expected_move<_Tp, _Err> +struct __expected_copy_assign<_Tp, _Err, __smf_availability::__available> : __expected_move<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_copy_assign, __expected_move, _Tp, _Err); @@ -636,21 +686,43 @@ struct __expected_copy_assign<_Tp, _Err, false> : __expected_move<_Tp, _Err> __expected_copy_assign& operator=(__expected_copy_assign&&) = default; }; -template +template +struct __expected_copy_assign<_Tp, _Err, __smf_availability::__deleted> : __expected_move<_Tp, _Err> +{ + _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_copy_assign, __expected_move, _Tp, _Err); + + __expected_copy_assign(const __expected_copy_assign&) = default; + __expected_copy_assign(__expected_copy_assign&&) = default; + __expected_copy_assign& operator=(const __expected_copy_assign&) = delete; + __expected_copy_assign& operator=(__expected_copy_assign&&) = default; +}; + +template +_LIBCUDACXX_INLINE_VAR constexpr __smf_availability __expected_can_move_assign = + (_CCCL_TRAIT(is_trivially_destructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_trivially_destructible, _Err) + && (_CCCL_TRAIT(is_trivially_move_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_trivially_move_constructible, _Err) + && (_CCCL_TRAIT(is_trivially_move_assignable, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_trivially_move_assignable, _Err) + ? __smf_availability::__trivial + : (_CCCL_TRAIT(is_move_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_move_constructible, _Err) + && (_CCCL_TRAIT(is_move_assignable, _Tp) || _CCCL_TRAIT(is_same, _Tp, void)) + && _CCCL_TRAIT(is_move_assignable, _Err) + && (_CCCL_TRAIT(is_nothrow_move_constructible, _Tp) || _CCCL_TRAIT(is_same, _Tp, void) + || _CCCL_TRAIT(is_nothrow_move_constructible, _Err)) + ? __smf_availability::__available + : __smf_availability::__deleted; + +template > struct __expected_move_assign : __expected_copy_assign<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_move_assign, __expected_copy_assign, _Tp, _Err); }; template -struct __expected_move_assign<_Tp, _Err, false> : __expected_copy_assign<_Tp, _Err> +struct __expected_move_assign<_Tp, _Err, __smf_availability::__available> : __expected_copy_assign<_Tp, _Err> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_move_assign, __expected_copy_assign, _Tp, _Err); @@ -687,18 +759,15 @@ struct __expected_move_assign<_Tp, _Err, false> : __expected_copy_assign<_Tp, _E }; template -using __expected_sfinae_ctor_base_t = - __sfinae_ctor_base<_CCCL_TRAIT(is_copy_constructible, _Tp) && _CCCL_TRAIT(is_copy_constructible, _Err), - _CCCL_TRAIT(is_move_constructible, _Tp) && _CCCL_TRAIT(is_move_constructible, _Err)>; +struct __expected_move_assign<_Tp, _Err, __smf_availability::__deleted> : __expected_copy_assign<_Tp, _Err> +{ + _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_move_assign, __expected_copy_assign, _Tp, _Err); -template -using __expected_sfinae_assign_base_t = __sfinae_assign_base< - _CCCL_TRAIT(is_copy_constructible, _Tp) && _CCCL_TRAIT(is_copy_constructible, _Err) - && _CCCL_TRAIT(is_copy_assignable, _Tp) && _CCCL_TRAIT(is_copy_assignable, _Err) - && (_CCCL_TRAIT(is_nothrow_move_constructible, _Tp) || _CCCL_TRAIT(is_nothrow_move_constructible, _Err)), - _CCCL_TRAIT(is_move_constructible, _Tp) && _CCCL_TRAIT(is_move_constructible, _Err) - && _CCCL_TRAIT(is_move_assignable, _Tp) && _CCCL_TRAIT(is_move_assignable, _Err) - && (_CCCL_TRAIT(is_nothrow_move_constructible, _Tp) || _CCCL_TRAIT(is_nothrow_move_constructible, _Err))>; + __expected_move_assign(const __expected_move_assign&) = default; + __expected_move_assign(__expected_move_assign&&) = default; + __expected_move_assign& operator=(const __expected_move_assign&) = default; + __expected_move_assign& operator=(__expected_move_assign&&) = delete; +}; // expected base classtemplate // MSVC complains about [[no_unique_address]] prior to C++20 as a vendor extension @@ -863,7 +932,7 @@ struct __expected_storage : __expected_destruct }; template -struct __expected_copy : __expected_storage +struct __expected_copy : __expected_storage { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_copy, __expected_storage, void, _Err); @@ -883,7 +952,7 @@ struct __expected_copy : __expected_storage }; template -struct __expected_move : __expected_copy +struct __expected_move : __expected_copy { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_move, __expected_copy, void, _Err); @@ -904,7 +973,7 @@ struct __expected_move : __expected_copy }; template -struct __expected_copy_assign : __expected_move +struct __expected_copy_assign : __expected_move { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_copy_assign, __expected_move, void, _Err); @@ -940,7 +1009,7 @@ struct __expected_copy_assign : __expected_move }; template -struct __expected_move_assign : __expected_copy_assign +struct __expected_move_assign : __expected_copy_assign { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__expected_move_assign, __expected_copy_assign, void, _Err); @@ -974,15 +1043,6 @@ struct __expected_move_assign : __expected_copy_assign -using __expected_void_sfinae_ctor_base_t = - __sfinae_ctor_base<_CCCL_TRAIT(is_copy_constructible, _Err), _CCCL_TRAIT(is_move_constructible, _Err)>; - -template -using __expected_void_sfinae_assign_base_t = - __sfinae_assign_base<_CCCL_TRAIT(is_copy_constructible, _Err) && _CCCL_TRAIT(is_copy_assignable, _Err), - _CCCL_TRAIT(is_move_constructible, _Err) && _CCCL_TRAIT(is_move_assignable, _Err)>; - _LIBCUDACXX_END_NAMESPACE_STD #endif // _CCCL_STD_VER > 2011 diff --git a/libcudacxx/include/cuda/std/__tuple_dir/sfinae_helpers.h b/libcudacxx/include/cuda/std/__tuple_dir/sfinae_helpers.h index d2bead65f7c..88e07d83a56 100644 --- a/libcudacxx/include/cuda/std/__tuple_dir/sfinae_helpers.h +++ b/libcudacxx/include/cuda/std/__tuple_dir/sfinae_helpers.h @@ -147,67 +147,68 @@ struct _LIBCUDACXX_TYPE_VIS __check_tuple_constructor_fail #if _CCCL_STD_VER > 2011 -template -struct __sfinae_ctor_base -{}; -template <> -struct __sfinae_ctor_base +enum class __smf_availability { - __sfinae_ctor_base() = default; - __sfinae_ctor_base(__sfinae_ctor_base const&) = delete; - __sfinae_ctor_base(__sfinae_ctor_base&&) = delete; - __sfinae_ctor_base& operator=(__sfinae_ctor_base const&) = default; - __sfinae_ctor_base& operator=(__sfinae_ctor_base&&) = default; -}; -template <> -struct __sfinae_ctor_base -{ - __sfinae_ctor_base() = default; - __sfinae_ctor_base(__sfinae_ctor_base const&) = default; - __sfinae_ctor_base(__sfinae_ctor_base&&) = delete; - __sfinae_ctor_base& operator=(__sfinae_ctor_base const&) = default; - __sfinae_ctor_base& operator=(__sfinae_ctor_base&&) = default; + __trivial, + __available, + __deleted, }; + +template +struct __sfinae_copy_base +{}; template <> -struct __sfinae_ctor_base +struct __sfinae_copy_base { - __sfinae_ctor_base() = default; - __sfinae_ctor_base(__sfinae_ctor_base const&) = delete; - __sfinae_ctor_base(__sfinae_ctor_base&&) = default; - __sfinae_ctor_base& operator=(__sfinae_ctor_base const&) = default; - __sfinae_ctor_base& operator=(__sfinae_ctor_base&&) = default; + __sfinae_copy_base() = default; + __sfinae_copy_base(__sfinae_copy_base const&) = delete; + __sfinae_copy_base(__sfinae_copy_base&&) = default; + __sfinae_copy_base& operator=(__sfinae_copy_base const&) = default; + __sfinae_copy_base& operator=(__sfinae_copy_base&&) = default; }; template -struct __sfinae_assign_base +struct __sfinae_move_base : __sfinae_copy_base<_CanCopy> {}; -template <> -struct __sfinae_assign_base +template +struct __sfinae_move_base<_CanCopy, false> : __sfinae_copy_base<_CanCopy> { - __sfinae_assign_base() = default; - __sfinae_assign_base(__sfinae_assign_base const&) = default; - __sfinae_assign_base(__sfinae_assign_base&&) = default; - __sfinae_assign_base& operator=(__sfinae_assign_base const&) = delete; - __sfinae_assign_base& operator=(__sfinae_assign_base&&) = delete; + __sfinae_move_base() = default; + __sfinae_move_base(__sfinae_move_base const&) = default; + __sfinae_move_base(__sfinae_move_base&&) = delete; + __sfinae_move_base& operator=(__sfinae_move_base const&) = default; + __sfinae_move_base& operator=(__sfinae_move_base&&) = default; }; -template <> -struct __sfinae_assign_base + +template +struct __sfinae_copy_assign_base : __sfinae_move_base<_CanCopy, _CanMove> +{}; +template +struct __sfinae_copy_assign_base<_CanCopy, _CanMove, false> : __sfinae_move_base<_CanCopy, _CanMove> { - __sfinae_assign_base() = default; - __sfinae_assign_base(__sfinae_assign_base const&) = default; - __sfinae_assign_base(__sfinae_assign_base&&) = default; - __sfinae_assign_base& operator=(__sfinae_assign_base const&) = default; - __sfinae_assign_base& operator=(__sfinae_assign_base&&) = delete; + __sfinae_copy_assign_base() = default; + __sfinae_copy_assign_base(__sfinae_copy_assign_base const&) = default; + __sfinae_copy_assign_base(__sfinae_copy_assign_base&&) = default; + __sfinae_copy_assign_base& operator=(__sfinae_copy_assign_base const&) = delete; + __sfinae_copy_assign_base& operator=(__sfinae_copy_assign_base&&) = default; }; -template <> -struct __sfinae_assign_base + +template +struct __sfinae_move_assign_base : __sfinae_copy_assign_base<_CanCopy, _CanMove, _CanCopyAssign> +{}; +template +struct __sfinae_move_assign_base<_CanCopy, _CanMove, _CanCopyAssign, false> + : __sfinae_copy_assign_base<_CanCopy, _CanMove, _CanCopyAssign> { - __sfinae_assign_base() = default; - __sfinae_assign_base(__sfinae_assign_base const&) = default; - __sfinae_assign_base(__sfinae_assign_base&&) = default; - __sfinae_assign_base& operator=(__sfinae_assign_base const&) = delete; - __sfinae_assign_base& operator=(__sfinae_assign_base&&) = default; + __sfinae_move_assign_base() = default; + __sfinae_move_assign_base(__sfinae_move_assign_base const&) = default; + __sfinae_move_assign_base(__sfinae_move_assign_base&&) = default; + __sfinae_move_assign_base& operator=(__sfinae_move_assign_base const&) = default; + __sfinae_move_assign_base& operator=(__sfinae_move_assign_base&&) = delete; }; + +template +using __sfinae_base = __sfinae_move_assign_base<_CanCopy, _CanMove, _CanCopyAssign, _CanMoveAssign>; #endif // _CCCL_STD_VER > 2011 _LIBCUDACXX_END_NAMESPACE_STD diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/optional b/libcudacxx/include/cuda/std/detail/libcxx/include/optional index bc3e0bb5970..bb7e430f99a 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/optional +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/optional @@ -178,9 +178,14 @@ template #include #include #include +#include #include #include #include +#include +#include +#include +#include #include #include #include @@ -194,11 +199,10 @@ template #include #include #include +#include #include // all public C++ headers provide the assertion handler #include #include -#include -#include #include // standard-mandated includes @@ -420,14 +424,21 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> } }; -template ::value> +template +_LIBCUDACXX_INLINE_VAR constexpr __smf_availability __optional_can_copy_construct = + _CCCL_TRAIT(is_trivially_copy_constructible, _Tp) ? __smf_availability::__trivial + : _CCCL_TRAIT(is_copy_constructible, _Tp) + ? __smf_availability::__available + : __smf_availability::__deleted; + +template > struct __optional_copy_base : __optional_storage_base<_Tp> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_copy_base, __optional_storage_base, _Tp); }; template -struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> +struct __optional_copy_base<_Tp, __smf_availability::__available> : __optional_storage_base<_Tp> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_copy_base, __optional_storage_base, _Tp); @@ -445,14 +456,31 @@ struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> __optional_copy_base& operator=(__optional_copy_base&&) = default; }; -template ::value> +template +struct __optional_copy_base<_Tp, __smf_availability::__deleted> : __optional_storage_base<_Tp> +{ + _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_copy_base, __optional_storage_base, _Tp); + __optional_copy_base(const __optional_copy_base&) = delete; + __optional_copy_base(__optional_copy_base&&) = default; + __optional_copy_base& operator=(const __optional_copy_base&) = default; + __optional_copy_base& operator=(__optional_copy_base&&) = default; +}; + +template +_LIBCUDACXX_INLINE_VAR constexpr __smf_availability __optional_can_move_construct = + _CCCL_TRAIT(is_trivially_move_constructible, _Tp) ? __smf_availability::__trivial + : _CCCL_TRAIT(is_move_constructible, _Tp) + ? __smf_availability::__available + : __smf_availability::__deleted; + +template > struct __optional_move_base : __optional_copy_base<_Tp> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_move_base, __optional_copy_base, _Tp); }; template -struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> +struct __optional_move_base<_Tp, __smf_availability::__available> : __optional_copy_base<_Tp> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_move_base, __optional_copy_base, _Tp); @@ -468,16 +496,34 @@ struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> __optional_move_base& operator=(__optional_move_base&&) = default; }; -template ::value && is_trivially_copy_constructible<_Tp>::value - && is_trivially_copy_assignable<_Tp>::value> +template +struct __optional_move_base<_Tp, __smf_availability::__deleted> : __optional_copy_base<_Tp> +{ + _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_move_base, __optional_copy_base, _Tp); + + __optional_move_base(const __optional_move_base&) = default; + __optional_move_base(__optional_move_base&&) = delete; + __optional_move_base& operator=(const __optional_move_base&) = default; + __optional_move_base& operator=(__optional_move_base&&) = default; +}; + +template +_LIBCUDACXX_INLINE_VAR constexpr __smf_availability __optional_can_copy_assign = + _CCCL_TRAIT(is_trivially_destructible, _Tp) && _CCCL_TRAIT(is_trivially_copy_constructible, _Tp) + && _CCCL_TRAIT(is_trivially_copy_assignable, _Tp) + ? __smf_availability::__trivial + : _CCCL_TRAIT(is_destructible, _Tp) && _CCCL_TRAIT(is_copy_constructible, _Tp) && _CCCL_TRAIT(is_copy_assignable, _Tp) + ? __smf_availability::__available + : __smf_availability::__deleted; + +template > struct __optional_copy_assign_base : __optional_move_base<_Tp> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_copy_assign_base, __optional_move_base, _Tp); }; template -struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> +struct __optional_copy_assign_base<_Tp, __smf_availability::__available> : __optional_move_base<_Tp> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_copy_assign_base, __optional_move_base, _Tp); @@ -494,16 +540,34 @@ struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; }; -template ::value && is_trivially_move_constructible<_Tp>::value - && is_trivially_move_assignable<_Tp>::value> +template +struct __optional_copy_assign_base<_Tp, __smf_availability::__deleted> : __optional_move_base<_Tp> +{ + _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_copy_assign_base, __optional_move_base, _Tp); + + __optional_copy_assign_base(const __optional_copy_assign_base&) = default; + __optional_copy_assign_base(__optional_copy_assign_base&&) = default; + __optional_copy_assign_base& operator=(const __optional_copy_assign_base&) = delete; + __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; +}; + +template +_LIBCUDACXX_INLINE_VAR constexpr __smf_availability __optional_can_move_assign = + _CCCL_TRAIT(is_trivially_destructible, _Tp) && _CCCL_TRAIT(is_trivially_move_constructible, _Tp) + && _CCCL_TRAIT(is_trivially_move_assignable, _Tp) + ? __smf_availability::__trivial + : _CCCL_TRAIT(is_destructible, _Tp) && _CCCL_TRAIT(is_move_constructible, _Tp) && _CCCL_TRAIT(is_move_assignable, _Tp) + ? __smf_availability::__available + : __smf_availability::__deleted; + +template > struct __optional_move_assign_base : __optional_copy_assign_base<_Tp> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_move_assign_base, __optional_copy_assign_base, _Tp); }; template -struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> +struct __optional_move_assign_base<_Tp, __smf_availability::__available> : __optional_copy_assign_base<_Tp> { _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_move_assign_base, __optional_copy_assign_base, _Tp); @@ -521,13 +585,15 @@ struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp }; template -using __optional_sfinae_ctor_base_t = - __sfinae_ctor_base::value, is_move_constructible<_Tp>::value>; +struct __optional_move_assign_base<_Tp, __smf_availability::__deleted> : __optional_copy_assign_base<_Tp> +{ + _LIBCUDACXX_DELEGATE_CONSTRUCTORS(__optional_move_assign_base, __optional_copy_assign_base, _Tp); -template -using __optional_sfinae_assign_base_t = - __sfinae_assign_base<(is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), - (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)>; + __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; + __optional_move_assign_base(__optional_move_assign_base&&) = default; + __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; + __optional_move_assign_base& operator=(__optional_move_assign_base&&) = delete; +}; template class optional; @@ -589,10 +655,7 @@ _LIBCUDACXX_INLINE_VAR constexpr bool __opt_is_assignable_from_opt = && !__opt_check_assignable_from_opt<_Tp, _Up>::value; template -class optional - : private __optional_move_assign_base<_Tp> - , private __optional_sfinae_ctor_base_t<_Tp> - , private __optional_sfinae_assign_base_t<_Tp> +class optional : private __optional_move_assign_base<_Tp> { using __base = __optional_move_assign_base<_Tp>; diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/variant b/libcudacxx/include/cuda/std/detail/libcxx/include/variant index d5aa19d00b8..7e09dd72384 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/variant +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/variant @@ -1506,9 +1506,9 @@ struct __variant_constraints template class _LIBCUDACXX_TEMPLATE_VIS variant - : private __sfinae_ctor_base<__all<_CCCL_TRAIT(is_copy_constructible, _Types)...>::value, - __all<_CCCL_TRAIT(is_move_constructible, _Types)...>::value> - , private __sfinae_assign_base< + : private __sfinae_base< + __all<_CCCL_TRAIT(is_copy_constructible, _Types)...>::value, + __all<_CCCL_TRAIT(is_move_constructible, _Types)...>::value, __all<(_CCCL_TRAIT(is_copy_constructible, _Types) && _CCCL_TRAIT(is_copy_assignable, _Types))...>::value, __all<(_CCCL_TRAIT(is_move_constructible, _Types) && _CCCL_TRAIT(is_move_assignable, _Types))...>::value> { diff --git a/libcudacxx/test/libcudacxx/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp b/libcudacxx/test/libcudacxx/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp index c4c77114b10..6776497b32a 100644 --- a/libcudacxx/test/libcudacxx/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp +++ b/libcudacxx/test/libcudacxx/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp @@ -87,6 +87,8 @@ static_assert(cuda::std::is_copy_assignable_v && !is_nothrow_move_constructible_v +static_assert( + cuda::std::__expected_can_copy_assign == cuda::std::__smf_availability::__deleted, ""); static_assert(!cuda::std::is_copy_assignable_v>, ""); #endif // TEST_COMPILER_ICC diff --git a/libcudacxx/test/libcudacxx/std/utilities/expected/expected.void/object_size.pass.cpp b/libcudacxx/test/libcudacxx/std/utilities/expected/expected.void/object_size.pass.cpp new file mode 100644 index 00000000000..5cfe11b189a --- /dev/null +++ b/libcudacxx/test/libcudacxx/std/utilities/expected/expected.void/object_size.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11 +// + +#include + +#include "test_macros.h" + +using cuda::std::expected; + +int main(int, char**) +{ + static_assert(sizeof(expected) == 2 * sizeof(char), ""); + static_assert(sizeof(expected) == 2 * sizeof(short), ""); + static_assert(sizeof(expected) == 2 * sizeof(int), ""); + static_assert(sizeof(expected) == 2 * sizeof(long long), ""); + + static_assert(sizeof(expected) == 2 * sizeof(long long), ""); + static_assert(sizeof(expected) == 2 * sizeof(long long), ""); + static_assert(sizeof(expected) == 2 * sizeof(long long), ""); + static_assert(sizeof(expected) == 2 * sizeof(long long), ""); + + static_assert(sizeof(expected) == 2 * sizeof(char), ""); + static_assert(sizeof(expected) == 2 * sizeof(short), ""); + static_assert(sizeof(expected) == 2 * sizeof(int), ""); + static_assert(sizeof(expected) == 2 * sizeof(long long), ""); + return 0; +} diff --git a/libcudacxx/test/libcudacxx/std/utilities/optional/optional.object/object_size.pass.cpp b/libcudacxx/test/libcudacxx/std/utilities/optional/optional.object/object_size.pass.cpp new file mode 100644 index 00000000000..9a3c0efc934 --- /dev/null +++ b/libcudacxx/test/libcudacxx/std/utilities/optional/optional.object/object_size.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11 +// + +#include + +#include "test_macros.h" + +using cuda::std::optional; + +int main(int, char**) +{ + static_assert(sizeof(optional) == 2 * sizeof(char), ""); + static_assert(sizeof(optional) == 2 * sizeof(short), ""); + static_assert(sizeof(optional) == 2 * sizeof(int), ""); + static_assert(sizeof(optional) == 2 * sizeof(long long), ""); + return 0; +} diff --git a/libcudacxx/test/libcudacxx/std/utilities/variant/variant.variant/object_size.pass.cpp b/libcudacxx/test/libcudacxx/std/utilities/variant/variant.variant/object_size.pass.cpp new file mode 100644 index 00000000000..274a268f138 --- /dev/null +++ b/libcudacxx/test/libcudacxx/std/utilities/variant/variant.variant/object_size.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11 +// UNSUPPORTED: msvc-19.16 + +// + +#include + +#include "test_macros.h" + +using cuda::std::variant; + +int main(int, char**) +{ + static_assert(sizeof(variant) == 2 * sizeof(char), ""); + static_assert(sizeof(variant) == 2 * sizeof(short), ""); + static_assert(sizeof(variant) == 2 * sizeof(int), ""); + static_assert(sizeof(variant) == 2 * sizeof(long long), ""); + + static_assert(sizeof(variant) == 2 * sizeof(char), ""); + static_assert(sizeof(variant) == 2 * sizeof(short), ""); + static_assert(sizeof(variant) == 2 * sizeof(int), ""); + static_assert(sizeof(variant) == 2 * sizeof(long long), ""); + return 0; +}