diff --git a/sycl/include/sycl/ext/oneapi/properties/properties.hpp b/sycl/include/sycl/ext/oneapi/properties/properties.hpp index 587c59a8b28c3..5b83abf6cef5a 100644 --- a/sycl/include/sycl/ext/oneapi/properties/properties.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/properties.hpp @@ -232,12 +232,5 @@ struct is_device_copyable< std::enable_if_t>::value>> : is_device_copyable {}; -template -struct is_device_copyable< - const ext::oneapi::experimental::properties, - std::enable_if_t>::value>> - : is_device_copyable {}; - } // __SYCL_INLINE_VER_NAMESPACE(_V1) } // namespace sycl diff --git a/sycl/include/sycl/types.hpp b/sycl/include/sycl/types.hpp index 4fc68a0c50073..80a7cb5699af5 100644 --- a/sycl/include/sycl/types.hpp +++ b/sycl/include/sycl/types.hpp @@ -58,6 +58,8 @@ #include #include #include +#include +#include #ifndef __SYCL_DEVICE_ONLY__ #include #endif @@ -2393,6 +2395,12 @@ __SYCL_DECLARE_FLOAT_VECTOR_CONVERTERS(double) template struct is_device_copyable : std::false_type {}; +// NOTE: this specialization is a candidate for all T such that T is trivially +// copyable, including std::array, std::optional, std::variant, +// sycl::marray and T[N]. Thus, specializations for all these mentioned +// types are guarded by `std::enable_if_t>` +// so that they are candidates only for non-trivially-copyable types. +// Otherwise, there are several candidates and the compiler can't decide. template struct is_device_copyable< T, std::enable_if_t::value>> @@ -2401,16 +2409,56 @@ struct is_device_copyable< template inline constexpr bool is_device_copyable_v = is_device_copyable::value; +// std::array is implicitly device copyable type. +template +struct is_device_copyable> : std::true_type {}; + +// std::array is implicitly device copyable type if T is device copyable +template +struct is_device_copyable< + std::array, + std::enable_if_t>::value>> + : is_device_copyable {}; + +// std::optional is implicitly device copyable type if T is device copyable +template +struct is_device_copyable< + std::optional, + std::enable_if_t>::value>> + : is_device_copyable {}; + +// std::pair is implicitly device copyable type if T1 and T2 are device +// copyable +template +struct is_device_copyable< + std::pair, + std::enable_if_t>::value>> + : detail::bool_constant::value && + is_device_copyable::value> {}; + // std::tuple<> is implicitly device copyable type. template <> struct is_device_copyable> : std::true_type {}; // std::tuple is implicitly device copyable type if each type T of Ts... // is device copyable. template -struct is_device_copyable> +struct is_device_copyable< + std::tuple, + std::enable_if_t>::value>> : detail::bool_constant::value && is_device_copyable>::value> {}; +// std::variant<> is implicitly device copyable type +template <> struct is_device_copyable> : std::true_type {}; + +// std::variant is implicitly device copyable type if each type T of +// Ts... is device copyable +template +struct is_device_copyable< + std::variant, + std::enable_if_t>::value>> + : is_device_copyable {}; + // marray is device copyable if element type is device copyable and it is also // not trivially copyable (if the element type is trivially copyable, the marray // is device copyable by default). @@ -2420,6 +2468,18 @@ struct is_device_copyable< !std::is_trivially_copyable::value>> : std::true_type {}; +// array is device copyable if element type is device copyable +template +struct is_device_copyable< + T[N], std::enable_if_t::value>> + : is_device_copyable {}; + +template +struct is_device_copyable< + T, std::enable_if_t::value && + (std::is_const_v || std::is_volatile_v)>> + : is_device_copyable> {}; + namespace detail { template struct IsDeprecatedDeviceCopyable : std::false_type {}; @@ -2433,9 +2493,13 @@ struct __SYCL2020_DEPRECATED("This type isn't device copyable in SYCL 2020") std::is_trivially_destructible::value && !is_device_copyable::value>> : std::true_type {}; +template +struct __SYCL2020_DEPRECATED("This type isn't device copyable in SYCL 2020") + IsDeprecatedDeviceCopyable : IsDeprecatedDeviceCopyable {}; + #ifdef __SYCL_DEVICE_ONLY__ -// Checks that the fields of the type T with indices 0 to (NumFieldsToCheck - 1) -// are device copyable. +// Checks that the fields of the type T with indices 0 to (NumFieldsToCheck - +// 1) are device copyable. template struct CheckFieldsAreDeviceCopyable : CheckFieldsAreDeviceCopyable { diff --git a/sycl/test/basic_tests/implicit_device_copyable_types.cpp b/sycl/test/basic_tests/implicit_device_copyable_types.cpp new file mode 100644 index 0000000000000..b1f72115f42af --- /dev/null +++ b/sycl/test/basic_tests/implicit_device_copyable_types.cpp @@ -0,0 +1,100 @@ +// RUN: %clangxx -fsycl -fsyntax-only %s + +#include +#include + +struct ACopyable { + int i; + ACopyable() = default; + ACopyable(int _i) : i(_i) {} + ACopyable(const ACopyable &x) : i(x.i) {} +}; + +template <> struct sycl::is_device_copyable : std::true_type {}; + +int main() { + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v); +#if __cpp_lib_span >= 202002 + static_assert(sycl::is_device_copyable_v>); +#endif + static_assert(sycl::is_device_copyable_v>); + + // const + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v); +#if __cpp_lib_span >= 202002 + static_assert(sycl::is_device_copyable_v>); +#endif + static_assert(sycl::is_device_copyable_v>); + + // volatile + static_assert(sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v); +#if __cpp_lib_span >= 202002 + static_assert(sycl::is_device_copyable_v>); +#endif + static_assert(sycl::is_device_copyable_v>); + + // const volatile + static_assert( + sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v< + const volatile std::tuple>); + static_assert(sycl::is_device_copyable_v< + const volatile std::variant>); + static_assert( + sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v>); + static_assert( + sycl::is_device_copyable_v>); + static_assert(sycl::is_device_copyable_v); +#if __cpp_lib_span >= 202002 + static_assert(sycl::is_device_copyable_v>); +#endif + static_assert(sycl::is_device_copyable_v>); + + return 0; +}