diff --git a/projects/clr/hipamd/include/hip/hcc_detail/helpers.hpp b/projects/clr/hipamd/include/hip/hcc_detail/helpers.hpp index cdae0e0fc4..b94b126994 100644 --- a/projects/clr/hipamd/include/hip/hcc_detail/helpers.hpp +++ b/projects/clr/hipamd/include/hip/hcc_detail/helpers.hpp @@ -27,6 +27,26 @@ THE SOFTWARE. // std::false_type, std result_of and std::true_type. #include // For std::declval. +#ifdef __has_include // Check if __has_include is present +# if __has_include() // Check for version header +# include +# if defined(__cpp_lib_is_invocable) && !defined(HIP_HAS_INVOCABLE) +# define HIP_HAS_INVOCABLE __cpp_lib_is_invocable +# endif +# if defined(__cpp_lib_result_of_sfinae) && !defined(HIP_HAS_RESULT_OF_SFINAE) +# define HIP_HAS_RESULT_OF_SFINAE __cpp_lib_result_of_sfinae +# endif +# endif +#endif + +#ifndef HIP_HAS_INVOCABLE +#define HIP_HAS_INVOCABLE 0 +#endif + +#ifndef HIP_HAS_RESULT_OF_SFINAE +#define HIP_HAS_RESULT_OF_SFINAE 0 +#endif + namespace std { // TODO: these should be removed as soon as possible. #if (__cplusplus < 201406L) #if (__cplusplus < 201402L) @@ -48,58 +68,56 @@ namespace hip_impl { template using void_t_ = void; -#if (__cplusplus < 201402L) -template -struct is_callable_impl : is_callable_impl {}; +#if HIP_HAS_INVOCABLE +template +struct is_callable_impl; -// Pointer to member function, call through non-pointer. -template -struct is_callable_impl< - F(C, Ts...), 0u, - void_t_().*std::declval())(std::declval()...))> > - : std::true_type {}; - -// Pointer to member function, call through pointer. -template -struct is_callable_impl< - F(C, Ts...), 1u, - void_t_()).*std::declval())(std::declval()...))> > - : std::true_type {}; - -// Pointer to member data, call through non-pointer, no args. -template -struct is_callable_impl().*std::declval())> > - : std::true_type {}; - -// Pointer to member data, call through pointer, no args. -template -struct is_callable_impl().*std::declval())> > - : std::true_type {}; - -// General call, n args. template -struct is_callable_impl()(std::declval()...))> > - : std::true_type {}; - -// Not callable. -template -struct is_callable_impl : std::false_type {}; -#elif (__cplusplus < 201703L) +struct is_callable_impl : std::is_invocable {}; +#elif HIP_HAS_RESULT_OF_SFINAE template struct is_callable_impl : std::false_type {}; template struct is_callable_impl::type > > : std::true_type {}; #else +template +auto simple_invoke(T Base::*pmd, Derived&& ref) +-> decltype(static_cast(ref).*pmd); + +template +auto simple_invoke(PMD&& pmd, Pointer&& ptr) +-> decltype((*static_cast(ptr)).*static_cast(pmd)); -// C++17 +template +auto simple_invoke(T Base::*pmd, const std::reference_wrapper& ref) +-> decltype(ref.get().*pmd); + +template +auto simple_invoke(T Base::*pmf, Derived&& ref, Args&&... args) +-> decltype((static_cast(ref).*pmf)(static_cast(args)...)); + +template +auto simple_invoke(PMF&& pmf, Pointer&& ptr, Args&&... args) +-> decltype(((*static_cast(ptr)).*static_cast(pmf))(static_cast(args)...)); + +template +auto simple_invoke(T Base::*pmf, const std::reference_wrapper& ref, Args&&... args) +-> decltype((ref.get().*pmf)(static_cast(args)...)); + +template +auto simple_invoke(F&& f, Ts&&... xs) +-> decltype(f(static_cast(xs)...)); template struct is_callable_impl : std::false_type {}; template -struct is_callable_impl > > : std::true_type {}; +struct is_callable_impl(), std::declval()...))> > + : std::true_type {}; + #endif + template struct is_callable : is_callable_impl {}; diff --git a/projects/clr/hipamd/tests/src/cppstd/hipInvocable11.cpp b/projects/clr/hipamd/tests/src/cppstd/hipInvocable11.cpp new file mode 100644 index 0000000000..6fa7e53622 --- /dev/null +++ b/projects/clr/hipamd/tests/src/cppstd/hipInvocable11.cpp @@ -0,0 +1,31 @@ +/* +Copyright (c) 2019 - present Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +/* HIT_START + * BUILD: %t %s ../test_common.cpp HIPCC_OPTIONS -std=c++11 EXCLUDE_HIP_PLATFORM nvcc + * TEST: %t + * HIT_END + */ + +#include "is_callable_test.hpp" +#include + +int main() { passed(); } diff --git a/projects/clr/hipamd/tests/src/cppstd/hipInvocable11Fallback.cpp b/projects/clr/hipamd/tests/src/cppstd/hipInvocable11Fallback.cpp new file mode 100644 index 0000000000..071dce8997 --- /dev/null +++ b/projects/clr/hipamd/tests/src/cppstd/hipInvocable11Fallback.cpp @@ -0,0 +1,34 @@ +/* +Copyright (c) 2019 - present Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +/* HIT_START + * BUILD: %t %s ../test_common.cpp HIPCC_OPTIONS -std=c++11 EXCLUDE_HIP_PLATFORM nvcc + * TEST: %t + * HIT_END + */ + +// Ensure fallback path is chosen +#define HIP_HAS_RESULT_OF_SFINAE 0 +#define HIP_HAS_INVOCABLE 0 +#include "is_callable_test.hpp" +#include + +int main() { passed(); } diff --git a/projects/clr/hipamd/tests/src/cppstd/hipInvocable14.cpp b/projects/clr/hipamd/tests/src/cppstd/hipInvocable14.cpp new file mode 100644 index 0000000000..41b58bd7dd --- /dev/null +++ b/projects/clr/hipamd/tests/src/cppstd/hipInvocable14.cpp @@ -0,0 +1,31 @@ +/* +Copyright (c) 2019 - present Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +/* HIT_START + * BUILD: %t %s ../test_common.cpp HIPCC_OPTIONS -std=c++14 EXCLUDE_HIP_PLATFORM nvcc + * TEST: %t + * HIT_END + */ + +#include "is_callable_test.hpp" +#include + +int main() { passed(); } diff --git a/projects/clr/hipamd/tests/src/cppstd/hipInvocable17.cpp b/projects/clr/hipamd/tests/src/cppstd/hipInvocable17.cpp new file mode 100644 index 0000000000..aa37aac5fb --- /dev/null +++ b/projects/clr/hipamd/tests/src/cppstd/hipInvocable17.cpp @@ -0,0 +1,31 @@ +/* +Copyright (c) 2019 - present Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +/* HIT_START + * BUILD: %t %s ../test_common.cpp HIPCC_OPTIONS -std=c++17 EXCLUDE_HIP_PLATFORM nvcc + * TEST: %t + * HIT_END + */ + +#include "is_callable_test.hpp" +#include + +int main() { passed(); } diff --git a/projects/clr/hipamd/tests/src/cppstd/is_callable_test.hpp b/projects/clr/hipamd/tests/src/cppstd/is_callable_test.hpp new file mode 100644 index 0000000000..87e4e35b8b --- /dev/null +++ b/projects/clr/hipamd/tests/src/cppstd/is_callable_test.hpp @@ -0,0 +1,209 @@ +/* +Copyright (c) 2017 - present Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include + +using hip_impl::is_callable; + +template +struct callable_rank : callable_rank +{}; + +template<> +struct callable_rank<0> +{}; + +struct test1 +{ + struct is_callable_class + { + void operator()(int) const + { + } + }; + struct callable_test_param {}; + + void is_callable_function(int) + { + } + + struct is_callable_rank_class + { + void operator()(int, callable_rank<3>) const + { + } + + void operator()(int, callable_rank<4>) const + { + } + }; + + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(not is_callable::value, "callable failed"); + static_assert(not is_callable::value, "callable failed"); + static_assert(not is_callable::value, "callable failed"); + + typedef void (*is_callable_function_pointer)(int); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(is_callable::value, "Not callable"); + static_assert(not is_callable::value, "callable failed"); + static_assert(not is_callable::value, "callable failed"); + static_assert(not is_callable::value, "callable failed"); + + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + static_assert(is_callable)>::value, "Not callable"); + + static_assert(not is_callable)>::value, "callable failed"); + static_assert(not is_callable)>::value, "callable failed"); + static_assert(not is_callable)>::value, "callable failed"); + static_assert(not is_callable)>::value, "callable failed"); + static_assert(not is_callable)>::value, "callable failed"); + static_assert(not is_callable)>::value, "callable failed"); + + static_assert(not is_callable::value, "callable failed"); + static_assert(not is_callable, callable_test_param)>::value, "callable failed"); + static_assert(not is_callable, callable_test_param)>::value, "callable failed"); + static_assert(not is_callable)>::value, "callable failed"); + static_assert(not is_callable)>::value, "callable failed"); + static_assert(not is_callable::value, "callable failed"); + static_assert(not is_callable::value, "callable failed"); +}; + +struct test2 +{ + typedef int(callable_rank<0>::*fn)(int); + + static_assert(is_callable&, int)>::value, "Failed"); + static_assert(is_callable&, int)>::value, "Failed"); + static_assert(not is_callable&)>::value, "Failed"); + static_assert(not is_callable const&, int)>::value, "Failed"); +}; + +struct test3 +{ + typedef int(callable_rank<0>::*fn)(int); + + typedef callable_rank<0>* T; + typedef callable_rank<1>* DT; + typedef const callable_rank<0>* CT; + typedef std::unique_ptr> ST; + + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + static_assert(not is_callable::value, "Failed"); + +}; + +struct test4 +{ + typedef int(callable_rank<0>::*fn); + + static_assert(not is_callable::value, "Failed"); +}; + +struct test5 +{ + typedef int(callable_rank<0>::*fn); + + static_assert(is_callable&)>::value, "Failed"); + static_assert(is_callable&&)>::value, "Failed"); + static_assert(is_callable&)>::value, "Failed"); + static_assert(is_callable&)>::value, "Failed"); +}; + +struct test6 +{ + typedef int(callable_rank<0>::*fn); + + typedef callable_rank<0>* T; + typedef callable_rank<1>* DT; + typedef const callable_rank<0>* CT; + typedef std::unique_ptr> ST; + + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + static_assert(is_callable::value, "Failed"); + +}; + +struct test7 +{ + typedef void(*fp)(callable_rank<0>&, int); + + static_assert(is_callable&, int)>::value, "Failed"); + static_assert(is_callable&, int)>::value, "Failed"); + static_assert(not is_callable&, int)>::value, "Failed"); + static_assert(not is_callable::value, "Failed"); + static_assert(not is_callable&)>::value, "Failed"); +}; + +struct test8 +{ + typedef void(&fp)(callable_rank<0>&, int); + + static_assert(is_callable&, int)>::value, "Failed"); + static_assert(is_callable&, int)>::value, "Failed"); + static_assert(not is_callable&, int)>::value, "Failed"); + static_assert(not is_callable::value, "Failed"); + static_assert(not is_callable&)>::value, "Failed"); +};