From: Jonathan Wakely Date: Thu, 3 Dec 2020 19:17:13 +0000 (+0000) Subject: libstdc++: Add std::bit_cast for C++20 [PR 93121] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9e433b3461ab64b38350817392a77efb67bb78b4;p=gcc.git libstdc++: Add std::bit_cast for C++20 [PR 93121] Thanks to Jakub's addition of the built-in, we can add this to the library now. The compiler tests for the built-in are quite extensive, including verifying the constraints, so this only adds minimal tests to the library testsuite. This doesn't add a new _GLIBCXX_HAVE_BUILTIN_BIT_CAST because using __has_builtin(__builtin_bit_cast) works for GCC and versions of Clang that provide the built-in. libstdc++-v3/ChangeLog: PR libstdc++/93121 * include/std/bit (__cpp_lib_bit_cast, bit_cast): Define. * include/std/version (__cpp_lib_bit_cast): Define. * testsuite/26_numerics/bit/bit.cast/bit_cast.cc: New test. * testsuite/26_numerics/bit/bit.cast/version.cc: New test. --- diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit index 16f7eba46d7..1d99c807c4a 100644 --- a/libstdc++-v3/include/std/bit +++ b/libstdc++-v3/include/std/bit @@ -49,6 +49,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ +#if __cplusplus > 201703l && __has_builtin(__builtin_bit_cast) +#define __cpp_lib_bit_cast 201806L + + /// Create a value of type `To` from the bits of `from`. + template + constexpr _To + bit_cast(const _From& __from) noexcept + { + return __builtin_bit_cast(_To, __from); + } +#endif + /// @cond undoc template diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 25f628f399d..6e4bd99b361 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -201,6 +201,9 @@ # define __cpp_lib_atomic_wait 201907L #endif #define __cpp_lib_bind_front 201907L +#if __has_builtin(__builtin_bit_cast) +# define __cpp_lib_bit_cast 201806L +#endif // FIXME: #define __cpp_lib_execution 201902L #define __cpp_lib_integer_comparison_functions 202002L #define __cpp_lib_constexpr_algorithms 201806L diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bit.cast/bit_cast.cc b/libstdc++-v3/testsuite/26_numerics/bit/bit.cast/bit_cast.cc new file mode 100644 index 00000000000..b451f152b47 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.cast/bit_cast.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +#ifndef __cpp_lib_bit_cast +# error "Feature-test macro for bit_cast wait missing in " +#elif __cpp_lib_bit_cast != 201806L +# error "Feature-test macro for bit_cast wait has wrong value in " +#endif + +#include +#include +#include + +template +constexpr bool +check(const From& from) +{ + return std::bit_cast(std::bit_cast(from)) == from; +} + +void +test01() +{ + static_assert( std::bit_cast(123) == 123 ); + static_assert( std::bit_cast(123u) == 123 ); + static_assert( std::bit_cast(~0u) == ~0 ); + + if constexpr (sizeof(int) == sizeof(float)) + static_assert( check(12.34f) ); + if constexpr (sizeof(unsigned long long) == sizeof(double)) + static_assert( check(123.456) ); + if constexpr (sizeof(std::intptr_t) == sizeof(void(*)())) + VERIFY( check(&test01) ); +} + +void +test02() +{ + struct S + { + int i; + + bool operator==(const char* s) const + { return std::memcmp(&i, s, sizeof(i)) == 0; } + }; + + char arr[sizeof(int)]; + char arr2[sizeof(int)]; + for (int i = 0; i < sizeof(int); ++i) + { + arr[i] = i + 1; + arr2[i] = (i + 1) * -(i % 2); + } + VERIFY( std::bit_cast(arr) == arr ); + VERIFY( std::bit_cast(arr2) == arr2 ); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bit.cast/version.cc b/libstdc++-v3/testsuite/26_numerics/bit/bit.cast/version.cc new file mode 100644 index 00000000000..688d44bbb89 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.cast/version.cc @@ -0,0 +1,27 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +#ifndef __cpp_lib_bit_cast +# error "Feature-test macro for bit_cast wait missing in " +#elif __cpp_lib_bit_cast != 201806L +# error "Feature-test macro for bit_cast wait has wrong value in " +#endif