Tested x86_64-linux, pushed to trunk.

libstdc++-v3/ChangeLog:

        PR libstdc++/101608
        * include/bits/ranges_algobase.h (__fill_n_fn): Check for
        constant evaluation before using memset.
        * testsuite/25_algorithms/fill_n/constrained.cc: Check
        byte-sized values as well.
---
 libstdc++-v3/include/bits/ranges_algobase.h   | 28 ++++++++++++-------
 .../25_algorithms/fill_n/constrained.cc       |  6 ++--
 2 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_algobase.h 
b/libstdc++-v3/include/bits/ranges_algobase.h
index c8c4d032983..9929e5e828b 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -527,17 +527,25 @@ namespace ranges
        if (__n <= 0)
          return __first;
 
-       // TODO: Generalize this optimization to contiguous iterators.
-       if constexpr (is_pointer_v<_Out>
-                     // Note that __is_byte already implies !is_volatile.
-                     && __is_byte<remove_pointer_t<_Out>>::__value
-                     && integral<_Tp>)
-         {
-           __builtin_memset(__first, static_cast<unsigned char>(__value), __n);
-           return __first + __n;
-         }
-       else if constexpr (is_scalar_v<_Tp>)
+       if constexpr (is_scalar_v<_Tp>)
          {
+           // TODO: Generalize this optimization to contiguous iterators.
+           if constexpr (is_pointer_v<_Out>
+                         // Note that __is_byte already implies !is_volatile.
+                         && __is_byte<remove_pointer_t<_Out>>::__value
+                         && integral<_Tp>)
+             {
+#ifdef __cpp_lib_is_constant_evaluated
+               if (!std::is_constant_evaluated())
+#endif
+                 {
+                   __builtin_memset(__first,
+                                    static_cast<unsigned char>(__value),
+                                    __n);
+                   return __first + __n;
+                 }
+             }
+
            const auto __tmp = __value;
            for (; __n > 0; --__n, (void)++__first)
              *__first = __tmp;
diff --git a/libstdc++-v3/testsuite/25_algorithms/fill_n/constrained.cc 
b/libstdc++-v3/testsuite/25_algorithms/fill_n/constrained.cc
index 6a015d34a89..1d1e1c104d4 100644
--- a/libstdc++-v3/testsuite/25_algorithms/fill_n/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/fill_n/constrained.cc
@@ -73,11 +73,12 @@ test01()
     }
 }
 
+template<typename T>
 constexpr bool
 test02()
 {
   bool ok = true;
-  int x[6] = { 1, 2, 3, 4, 5, 6 };
+  T x[6] = { 1, 2, 3, 4, 5, 6 };
   const int y[6] = { 1, 2, 3, 4, 5, 6 };
   const int z[6] = { 17, 17, 17, 4, 5, 6 };
 
@@ -94,5 +95,6 @@ int
 main()
 {
   test01();
-  static_assert(test02());
+  static_assert(test02<int>());
+  static_assert(test02<unsigned char>()); // PR libstdc++/101608
 }
-- 
2.31.1

Reply via email to