]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Make byte-sized std::fill_n a constant expression (PR 94933)
authorJonathan Wakely <jwakely@redhat.com>
Tue, 12 May 2020 08:54:24 +0000 (09:54 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 12 May 2020 08:54:24 +0000 (09:54 +0100)
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.

Backport from mainline
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.

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_algobase.h
libstdc++-v3/testsuite/25_algorithms/fill_n/constexpr.cc

index 55d975b84fc1806afc5d3440c42de18980dc5bed..b37c19ace3b796711bcc60b4e1057927f40b28f1 100644 (file)
@@ -1,3 +1,14 @@
+2020-05-12  Jonathan Wakely  <jwakely@redhat.com>
+
+       Backport from mainline
+       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-07  Jonathan Wakely  <jwakely@redhat.com>
 
        Backport from mainline
index a7e92d4b4733d193dc5bf8fb7326fc1e74bffc3c..bed61fd9d00f64decb6f64987646ce395b79a568 100644 (file)
@@ -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);
     }
index c18b6c99edaadf0c27274d5aa3eb6a2034f7ff0e..17c9aa5a8d7a066dddc397860746c4a8c014349b 100644 (file)
@@ -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() );