aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2020-05-03 12:46:15 +0100
committerJonathan Wakely <jwakely@redhat.com>2020-05-03 13:33:15 +0100
commit22b6b5d6cfb76deb68ca5bc0bcae8b4245df946d (patch)
tree57cdb833b8970bc3301816c9862d9b748b0e5c21
parent18a6e4130fb3c63a974295a18ed6e4bef070df03 (diff)
downloadgcc-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.
-rw-r--r--libstdc++-v3/ChangeLog8
-rw-r--r--libstdc++-v3/include/bits/stl_algobase.h9
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/fill_n/constexpr.cc32
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() );