[libcxx-commits] [libcxx] [libc++][NFC] Use early returns in a few basic_string functions (PR #137299)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Apr 25 02:09:45 PDT 2025


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/137299

Using early returns tends to make the code easier to read, without any changes to the generated code.


>From eaa173b20c54e8a6a0297af29ee62b6d79fe68f2 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 25 Apr 2025 11:08:52 +0200
Subject: [PATCH] [libc++][NFC] Use early returns in a few basic_string
 functions

---
 libcxx/include/string | 275 ++++++++++++++++++++++--------------------
 1 file changed, 143 insertions(+), 132 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index f60616d522cfe..2d7581270b9e6 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1406,19 +1406,21 @@ public:
     size_type __sz  = size();
     size_type __cap = capacity();
     size_type __n   = static_cast<size_type>(std::distance(__first, __last));
-    if (__n) {
-      if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) {
-        if (__cap - __sz < __n)
-          __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
-        __annotate_increase(__n);
-        auto __end = __copy_non_overlapping_range(__first, __last, std::__to_address(__get_pointer() + __sz));
-        traits_type::assign(*__end, value_type());
-        __set_size(__sz + __n);
-      } else {
-        const basic_string __temp(__first, __last, __alloc_);
-        append(__temp.data(), __temp.size());
-      }
+    if (__n == 0)
+      return *this;
+
+    if (__string_is_trivial_iterator<_ForwardIterator>::value && __addr_in_range(*__first)) {
+      const basic_string __temp(__first, __last, __alloc_);
+      append(__temp.data(), __temp.size());
+      return *this;
     }
+
+    if (__cap - __sz < __n)
+      __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
+    __annotate_increase(__n);
+    auto __end = __copy_non_overlapping_range(__first, __last, std::__to_address(__get_pointer() + __sz));
+    traits_type::assign(*__end, value_type());
+    __set_size(__sz + __n);
     return *this;
   }
 
@@ -2783,24 +2785,22 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Al
 basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* __s, size_type __n) {
   const auto __cap  = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap();
   const auto __size = __is_short ? __get_short_size() : __get_long_size();
-  if (__n < __cap) {
-    if (__n > __size)
-      __annotate_increase(__n - __size);
-    pointer __p;
-    if (__is_short) {
-      __p = __get_short_pointer();
-      __set_short_size(__n);
-    } else {
-      __p = __get_long_pointer();
-      __set_long_size(__n);
-    }
-    traits_type::copy(std::__to_address(__p), __s, __n);
-    traits_type::assign(__p[__n], value_type());
-    if (__size > __n)
-      __annotate_shrink(__size);
-  } else {
+  if (__n >= __cap) {
     __grow_by_and_replace(__cap - 1, __n - __cap + 1, __size, 0, __size, __n, __s);
+    return *this;
+  }
+
+  auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
+  pointer __p;
+  if (__is_short) {
+    __p = __get_short_pointer();
+    __set_short_size(__n);
+  } else {
+    __p = __get_long_pointer();
+    __set_long_size(__n);
   }
+  traits_type::copy(std::__to_address(__p), __s, __n);
+  traits_type::assign(__p[__n], value_type());
   return *this;
 }
 
@@ -3014,52 +3014,56 @@ basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_ty
   _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::append received nullptr");
   size_type __cap = capacity();
   size_type __sz  = size();
-  if (__cap - __sz >= __n) {
-    if (__n) {
-      __annotate_increase(__n);
-      value_type* __p = std::__to_address(__get_pointer());
-      traits_type::copy(__p + __sz, __s, __n);
-      __sz += __n;
-      __set_size(__sz);
-      traits_type::assign(__p[__sz], value_type());
-    }
-  } else
+  if (__cap - __sz < __n) {
     __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __sz, 0, __n, __s);
+    return *this;
+  }
+
+  if (__n == 0)
+    return *this;
+
+  __annotate_increase(__n);
+  value_type* __p = std::__to_address(__get_pointer());
+  traits_type::copy(__p + __sz, __s, __n);
+  __sz += __n;
+  __set_size(__sz);
+  traits_type::assign(__p[__sz], value_type());
   return *this;
 }
 
 template <class _CharT, class _Traits, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c) {
-  if (__n) {
-    size_type __cap = capacity();
-    size_type __sz  = size();
-    if (__cap - __sz < __n)
-      __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
-    __annotate_increase(__n);
-    pointer __p = __get_pointer();
-    traits_type::assign(std::__to_address(__p) + __sz, __n, __c);
-    __sz += __n;
-    __set_size(__sz);
-    traits_type::assign(__p[__sz], value_type());
-  }
+  if (__n == 0)
+    return *this;
+
+  size_type __cap = capacity();
+  size_type __sz  = size();
+  if (__cap - __sz < __n)
+    __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
+  __annotate_increase(__n);
+  pointer __p = __get_pointer();
+  traits_type::assign(std::__to_address(__p) + __sz, __n, __c);
+  __sz += __n;
+  __set_size(__sz);
+  traits_type::assign(__p[__sz], value_type());
   return *this;
 }
 
 template <class _CharT, class _Traits, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
 basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n) {
-  if (__n) {
-    size_type __cap = capacity();
-    size_type __sz  = size();
-    if (__cap - __sz < __n)
-      __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
-    __annotate_increase(__n);
-    pointer __p = __get_pointer();
-    __sz += __n;
-    __set_size(__sz);
-    traits_type::assign(__p[__sz], value_type());
-  }
+  if (__n == 0)
+    return;
+  size_type __cap = capacity();
+  size_type __sz  = size();
+  if (__cap - __sz < __n)
+    __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
+  __annotate_increase(__n);
+  pointer __p = __get_pointer();
+  __sz += __n;
+  __set_size(__sz);
+  traits_type::assign(__p[__sz], value_type());
 }
 
 template <class _CharT, class _Traits, class _Allocator>
@@ -3117,23 +3121,27 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_t
   if (__pos > __sz)
     this->__throw_out_of_range();
   size_type __cap = capacity();
-  if (__cap - __sz >= __n) {
-    if (__n) {
-      __annotate_increase(__n);
-      value_type* __p    = std::__to_address(__get_pointer());
-      size_type __n_move = __sz - __pos;
-      if (__n_move != 0) {
-        if (std::__is_pointer_in_range(__p + __pos, __p + __sz, __s))
-          __s += __n;
-        traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
-      }
-      traits_type::move(__p + __pos, __s, __n);
-      __sz += __n;
-      __set_size(__sz);
-      traits_type::assign(__p[__sz], value_type());
-    }
-  } else
+
+  if (__cap - __sz < __n) {
     __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s);
+    return *this;
+  }
+
+  if (__n == 0)
+    return *this;
+
+  __annotate_increase(__n);
+  value_type* __p    = std::__to_address(__get_pointer());
+  size_type __n_move = __sz - __pos;
+  if (__n_move != 0) {
+    if (std::__is_pointer_in_range(__p + __pos, __p + __sz, __s))
+      __s += __n;
+    traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
+  }
+  traits_type::move(__p + __pos, __s, __n);
+  __sz += __n;
+  __set_size(__sz);
+  traits_type::assign(__p[__sz], value_type());
   return *this;
 }
 
@@ -3143,24 +3151,26 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n
   size_type __sz = size();
   if (__pos > __sz)
     this->__throw_out_of_range();
-  if (__n) {
-    size_type __cap = capacity();
-    value_type* __p;
-    if (__cap - __sz >= __n) {
-      __annotate_increase(__n);
-      __p                = std::__to_address(__get_pointer());
-      size_type __n_move = __sz - __pos;
-      if (__n_move != 0)
-        traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
-    } else {
-      __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n);
-      __p = std::__to_address(__get_long_pointer());
-    }
-    traits_type::assign(__p + __pos, __n, __c);
-    __sz += __n;
-    __set_size(__sz);
-    traits_type::assign(__p[__sz], value_type());
+
+  if (__n == 0)
+    return *this;
+
+  size_type __cap = capacity();
+  value_type* __p;
+  if (__cap - __sz >= __n) {
+    __annotate_increase(__n);
+    __p                = std::__to_address(__get_pointer());
+    size_type __n_move = __sz - __pos;
+    if (__n_move != 0)
+      traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
+  } else {
+    __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n);
+    __p = std::__to_address(__get_long_pointer());
   }
+  traits_type::assign(__p + __pos, __n, __c);
+  __sz += __n;
+  __set_size(__sz);
+  traits_type::assign(__p[__sz], value_type());
   return *this;
 }
 
@@ -3234,38 +3244,38 @@ basic_string<_CharT, _Traits, _Allocator>::replace(
     this->__throw_out_of_range();
   __n1            = std::min(__n1, __sz - __pos);
   size_type __cap = capacity();
-  if (__cap - __sz + __n1 >= __n2) {
-    value_type* __p = std::__to_address(__get_pointer());
-    if (__n1 != __n2) {
-      if (__n2 > __n1)
-        __annotate_increase(__n2 - __n1);
-      size_type __n_move = __sz - __pos - __n1;
-      if (__n_move != 0) {
-        if (__n1 > __n2) {
-          traits_type::move(__p + __pos, __s, __n2);
-          traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
-          return __null_terminate_at(__p, __sz + (__n2 - __n1));
-        }
-        if (std::__is_pointer_in_range(__p + __pos + 1, __p + __sz, __s)) {
-          if (__p + __pos + __n1 <= __s)
-            __s += __n2 - __n1;
-          else // __p + __pos < __s < __p + __pos + __n1
-          {
-            traits_type::move(__p + __pos, __s, __n1);
-            __pos += __n1;
-            __s += __n2;
-            __n2 -= __n1;
-            __n1 = 0;
-          }
-        }
+  if (__cap - __sz + __n1 < __n2) {
+    __grow_by_and_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2, __s);
+    return *this;
+  }
+
+  value_type* __p = std::__to_address(__get_pointer());
+  if (__n1 != __n2) {
+    if (__n2 > __n1)
+      __annotate_increase(__n2 - __n1);
+    size_type __n_move = __sz - __pos - __n1;
+    if (__n_move != 0) {
+      if (__n1 > __n2) {
+        traits_type::move(__p + __pos, __s, __n2);
         traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
+        return __null_terminate_at(__p, __sz + (__n2 - __n1));
+      }
+      if (std::__is_pointer_in_range(__p + __pos + 1, __p + __sz, __s)) {
+        if (__p + __pos + __n1 <= __s) {
+          __s += __n2 - __n1;
+        } else { // __p + __pos < __s < __p + __pos + __n1
+          traits_type::move(__p + __pos, __s, __n1);
+          __pos += __n1;
+          __s += __n2;
+          __n2 -= __n1;
+          __n1 = 0;
+        }
       }
+      traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
     }
-    traits_type::move(__p + __pos, __s, __n2);
-    return __null_terminate_at(__p, __sz + (__n2 - __n1));
-  } else
-    __grow_by_and_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2, __s);
-  return *this;
+  }
+  traits_type::move(__p + __pos, __s, __n2);
+  return __null_terminate_at(__p, __sz + (__n2 - __n1));
 }
 
 template <class _CharT, class _Traits, class _Allocator>
@@ -3318,15 +3328,16 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __
 template <class _CharT, class _Traits, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void
 basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move(size_type __pos, size_type __n) {
-  if (__n) {
-    size_type __sz     = size();
-    value_type* __p    = std::__to_address(__get_pointer());
-    __n                = std::min(__n, __sz - __pos);
-    size_type __n_move = __sz - __pos - __n;
-    if (__n_move != 0)
-      traits_type::move(__p + __pos, __p + __pos + __n, __n_move);
-    __null_terminate_at(__p, __sz - __n);
-  }
+  if (__n == 0)
+    return;
+
+  size_type __sz     = size();
+  value_type* __p    = std::__to_address(__get_pointer());
+  __n                = std::min(__n, __sz - __pos);
+  size_type __n_move = __sz - __pos - __n;
+  if (__n_move != 0)
+    traits_type::move(__p + __pos, __p + __pos + __n, __n_move);
+  __null_terminate_at(__p, __sz - __n);
 }
 
 template <class _CharT, class _Traits, class _Allocator>



More information about the libcxx-commits mailing list