]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix trivial relocation for constexpr std::vector
authorJonathan Wakely <jwakely@redhat.com>
Fri, 26 Nov 2021 21:34:17 +0000 (21:34 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 26 Nov 2021 22:28:48 +0000 (22:28 +0000)
When implementing constexpr std::vector I added a check for constant
evaluation in vector::_S_use_relocate(), so that we would not try to relocate
trivial objects by using memmove. But I put it in the constexpr function
that decides whether to relocate or not, and calls to that function are
always constant evaluated. This had the effect of disabling relocation
entirely, even in non-constexpr vectors.

This removes the check in _S_use_relocate() and modifies the actual
relocation algorithm, __relocate_a_1, to use the non-trivial
implementation instead of memmove when called during constant
evaluation.

libstdc++-v3/ChangeLog:

* include/bits/stl_uninitialized.h (__relocate_a_1): Do not use
memmove during constant evaluation.
* include/bits/stl_vector.h (vector::_S_use_relocate()): Do not
check is_constant_evaluated in always-constexpr function.

libstdc++-v3/include/bits/stl_uninitialized.h
libstdc++-v3/include/bits/stl_vector.h

index 673f6a076752acc5035d1d9ebecec329551a29e2..f2786c5a46117aec6232ca959ddb1c0e8a27a29d 100644 (file)
@@ -1051,6 +1051,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// @cond undocumented
 
   template<typename _Tp, typename _Up, typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
     inline void
     __relocate_object_a(_Tp* __restrict __dest, _Up* __restrict __orig,
                        _Allocator& __alloc)
@@ -1070,18 +1071,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_bitwise_relocatable
     : is_trivial<_Tp> { };
 
-  template <typename _Tp, typename _Up>
-    _GLIBCXX20_CONSTEXPR
-    inline __enable_if_t<std::__is_bitwise_relocatable<_Tp>::value, _Tp*>
-    __relocate_a_1(_Tp* __first, _Tp* __last,
-                  _Tp* __result, allocator<_Up>&) noexcept
-    {
-      ptrdiff_t __count = __last - __first;
-      if (__count > 0)
-       __builtin_memmove(__result, __first, __count * sizeof(_Tp));
-      return __result + __count;
-    }
-
   template <typename _InputIterator, typename _ForwardIterator,
            typename _Allocator>
     _GLIBCXX20_CONSTEXPR
@@ -1105,6 +1094,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __cur;
     }
 
+  template <typename _Tp, typename _Up>
+    _GLIBCXX20_CONSTEXPR
+    inline __enable_if_t<std::__is_bitwise_relocatable<_Tp>::value, _Tp*>
+    __relocate_a_1(_Tp* __first, _Tp* __last,
+                  _Tp* __result,
+                  [[__maybe_unused__]] allocator<_Up>& __alloc) noexcept
+    {
+      ptrdiff_t __count = __last - __first;
+      if (__count > 0)
+       {
+#ifdef __cpp_lib_is_constant_evaluated
+         if (std::is_constant_evaluated())
+           {
+             // Can't use memmove. Wrap the pointer so that __relocate_a_1
+             // resolves to the non-trivial overload above.
+             __gnu_cxx::__normal_iterator<_Tp*, void> __out(__result);
+             __out = std::__relocate_a_1(__first, __last, __out, __alloc);
+             return __out.base();
+           }
+#endif
+         __builtin_memmove(__result, __first, __count * sizeof(_Tp));
+       }
+      return __result + __count;
+    }
+
+
   template <typename _InputIterator, typename _ForwardIterator,
            typename _Allocator>
     _GLIBCXX20_CONSTEXPR
@@ -1115,9 +1130,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                                     std::__niter_base(__last),
                                     std::__niter_base(__result), __alloc)))
     {
-      return __relocate_a_1(std::__niter_base(__first),
-                           std::__niter_base(__last),
-                           std::__niter_base(__result), __alloc);
+      return std::__relocate_a_1(std::__niter_base(__first),
+                                std::__niter_base(__last),
+                                std::__niter_base(__result), __alloc);
     }
 
   /// @endcond
index bd15b6bd8a8620ee50926f1ec2c0e3de64e5f8ff..4587757637ebe9e70e68726590017ae6a3392810 100644 (file)
@@ -475,10 +475,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       static constexpr bool
       _S_use_relocate()
       {
-#if __cplusplus >= 202002L && __has_builtin(__builtin_is_constant_evaluated)
-       if (__builtin_is_constant_evaluated())
-         return false; // Cannot use memcpy in constant evaluation contexts.
-#endif
        // Instantiating std::__relocate_a might cause an error outside the
        // immediate context (in __relocate_object_a's noexcept-specifier),
        // so only do it if we know the type can be move-inserted into *this.