[libcxx-commits] [libcxx] aa8ebca - [libc++] Remove recursion in basic_string::insert(const_iterator, ForwardIterator, ForwardIterator)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Sat Feb 26 04:30:08 PST 2022


Author: Nikolas Klauser
Date: 2022-02-26T13:29:56+01:00
New Revision: aa8ebcad5dd56d8f31b7044c052337101da00505

URL: https://github.com/llvm/llvm-project/commit/aa8ebcad5dd56d8f31b7044c052337101da00505
DIFF: https://github.com/llvm/llvm-project/commit/aa8ebcad5dd56d8f31b7044c052337101da00505.diff

LOG: [libc++] Remove recursion in basic_string::insert(const_iterator, ForwardIterator, ForwardIterator)

`__addr_in_range` is a non-constexpr function, so we can't call it during constant evaluation.

Reviewed By: Quuxplusone, #libc, miscco

Spies: miscco, libcxx-commits

Differential Revision: https://reviews.llvm.org/D119633

Added: 
    

Modified: 
    libcxx/include/string

Removed: 
    


################################################################################
diff  --git a/libcxx/include/string b/libcxx/include/string
index d33f6edf97e9a..39647ff79db33 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1436,12 +1436,35 @@ private:
         return !__libcpp_is_constant_evaluated() && (__sz < __min_cap);
     }
 
-    _LIBCPP_INLINE_VISIBILITY
-    allocator_type& __alloc() _NOEXCEPT
-        {return __r_.second();}
-    _LIBCPP_INLINE_VISIBILITY
-    const allocator_type& __alloc() const _NOEXCEPT
-        {return __r_.second();}
+    template <class _ForwardIterator>
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+    iterator __insert_from_safe_copy(size_type __n, size_type __ip, _ForwardIterator __first, _ForwardIterator __last) {
+        size_type __sz = size();
+        size_type __cap = capacity();
+        value_type* __p;
+        if (__cap - __sz >= __n)
+        {
+            __p = std::__to_address(__get_pointer());
+            size_type __n_move = __sz - __ip;
+            if (__n_move != 0)
+                traits_type::move(__p + __ip + __n, __p + __ip, __n_move);
+        }
+        else
+        {
+            __grow_by(__cap, __sz + __n - __cap, __sz, __ip, 0, __n);
+            __p = std::__to_address(__get_long_pointer());
+        }
+        __sz += __n;
+        __set_size(__sz);
+        traits_type::assign(__p[__sz], value_type());
+        for (__p += __ip; __first != __last; ++__p, ++__first)
+            traits_type::assign(*__p, *__first);
+
+        return begin() + __ip;
+    }
+
+    _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __r_.second(); }
+    _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); }
 
 #ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
 
@@ -2785,45 +2808,23 @@ __enable_if_t
 >
 basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last)
 {
-  _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this,
-                       "string::insert(iterator, range) called with an iterator not"
-                       " referring to this string");
+    _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this,
+                         "string::insert(iterator, range) called with an iterator not referring to this string");
 
     size_type __ip = static_cast<size_type>(__pos - begin());
-    size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
-    if (__n)
+    size_type __n = static_cast<size_type>(std::distance(__first, __last));
+    if (__n == 0)
+        return begin() + __ip;
+
+    if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first))
     {
-        if (__string_is_trivial_iterator<_ForwardIterator>::value &&
-            !__addr_in_range(*__first))
-        {
-            size_type __sz = size();
-            size_type __cap = capacity();
-            value_type* __p;
-            if (__cap - __sz >= __n)
-            {
-                __p = _VSTD::__to_address(__get_pointer());
-                size_type __n_move = __sz - __ip;
-                if (__n_move != 0)
-                    traits_type::move(__p + __ip + __n, __p + __ip, __n_move);
-            }
-            else
-            {
-                __grow_by(__cap, __sz + __n - __cap, __sz, __ip, 0, __n);
-                __p = _VSTD::__to_address(__get_long_pointer());
-            }
-            __sz += __n;
-            __set_size(__sz);
-            traits_type::assign(__p[__sz], value_type());
-            for (__p += __ip; __first != __last; ++__p, (void) ++__first)
-                traits_type::assign(*__p, *__first);
-        }
-        else
-        {
-            const basic_string __temp(__first, __last, __alloc());
-            return insert(__pos, __temp.data(), __temp.data() + __temp.size());
-        }
+        return __insert_from_safe_copy(__n, __ip, __first, __last);
+    }
+    else
+    {
+        const basic_string __temp(__first, __last, __alloc());
+        return __insert_from_safe_copy(__n, __ip, __temp.begin(), __temp.end());
     }
-    return begin() + __ip;
 }
 
 template <class _CharT, class _Traits, class _Allocator>


        


More information about the libcxx-commits mailing list