diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2020-05-03 12:46:15 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-05-03 13:33:15 +0100 |
commit | 22b6b5d6cfb76deb68ca5bc0bcae8b4245df946d (patch) | |
tree | 57cdb833b8970bc3301816c9862d9b748b0e5c21 /libstdc++-v3 | |
parent | 18a6e4130fb3c63a974295a18ed6e4bef070df03 (diff) | |
download | gcc-22b6b5d6cfb76deb68ca5bc0bcae8b4245df946d.zip gcc-22b6b5d6cfb76deb68ca5bc0bcae8b4245df946d.tar.gz gcc-22b6b5d6cfb76deb68ca5bc0bcae8b4245df946d.tar.bz2 |
libstdc++: Make byte-sized std::fill_n a constant expression (PR 94933)
The overload for byte types uses memset and isn't constexpr. This adds
the specifier and uses std::is_constant_evaluated() to provide a
compile-time alternative.
PR libstdc++/94933
* include/bits/stl_algobase.h (__fill_a1): Make overload for byte types
usable in constant expressions.
* testsuite/25_algorithms/fill_n/constexpr.cc: Test with bytes and
non-scalars.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 8 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_algobase.h | 9 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/fill_n/constexpr.cc | 32 |
3 files changed, 48 insertions, 1 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1bf1081..7f11117 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2020-05-03 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/94933 + * include/bits/stl_algobase.h (__fill_a1): Make overload for byte types + usable in constant expressions. + * testsuite/25_algorithms/fill_n/constexpr.cc: Test with bytes and + non-scalars. + 2020-05-01 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/94901 diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index a7e92d4..bed61fd9 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -875,11 +875,20 @@ _GLIBCXX_END_NAMESPACE_CONTAINER // Specialization: for char types we can use memset. template<typename _Tp> + _GLIBCXX20_CONSTEXPR inline typename __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, void>::__type __fill_a1(_Tp* __first, _Tp* __last, const _Tp& __c) { const _Tp __tmp = __c; +#if __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + for (; __first != __last; ++__first) + *__first = __tmp; + return; + } +#endif if (const size_t __len = __last - __first) __builtin_memset(__first, static_cast<unsigned char>(__tmp), __len); } diff --git a/libstdc++-v3/testsuite/25_algorithms/fill_n/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/fill_n/constexpr.cc index c18b6c9..17c9aa5 100644 --- a/libstdc++-v3/testsuite/25_algorithms/fill_n/constexpr.cc +++ b/libstdc++-v3/testsuite/25_algorithms/fill_n/constexpr.cc @@ -28,7 +28,37 @@ test() const auto outd = std::fill_n(ma0.begin(), 6, 77); - return outd == ma0.begin() + 6; + return outd == ma0.begin() + 6 && ma0[5] == 77 && ma0[6] == 0; } static_assert(test()); + +constexpr bool +test_byte() +{ + // PR libstdc++/94933 + std::array<char, 12> ma0{}; + + const auto outd = std::fill_n(ma0.begin(), 6, 77); + + return outd == ma0.begin() + 6 && ma0[5] == 77 && ma0[6] == 0; +} + +static_assert( test_byte() ); + +struct S +{ + int i = 0; +}; + +constexpr bool +test_nonscalar() +{ + std::array<S, 12> ma0{}; + + const auto outd = std::fill_n(ma0.begin(), 6, S{77}); + + return outd == ma0.begin() + 6 && ma0[5].i == 77 && ma0[6].i == 0; +} + +static_assert( test_nonscalar() ); |