[libcxx-commits] [libcxx] [libc++] Fix ambiguous call to std::max in vector<bool> (PR #119801)

Peng Liu via libcxx-commits libcxx-commits at lists.llvm.org
Fri Mar 14 21:06:45 PDT 2025


https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/119801

>From 20796d5c7126899a066a3bcb52eb1db93592927b Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Thu, 12 Dec 2024 21:33:15 -0500
Subject: [PATCH 1/3] Fix ambiguous call to std::max  in vector<bool>

---
 libcxx/include/__cxx03/string         | 8 ++++++--
 libcxx/include/__cxx03/vector         | 2 +-
 libcxx/include/__vector/vector_bool.h | 2 +-
 libcxx/include/string                 | 2 +-
 4 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/__cxx03/string b/libcxx/include/__cxx03/string
index c4431dcb04d41..c29f74290bd41 100644
--- a/libcxx/include/__cxx03/string
+++ b/libcxx/include/__cxx03/string
@@ -2483,7 +2483,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
     __throw_length_error();
   pointer __old_p = __get_pointer();
   size_type __cap =
-      __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1;
+      __old_cap < __ms / 2 - __alignment
+          ? __recommend(std::max<size_type>(__old_cap + __delta_cap, 2 * __old_cap))
+          : __ms - 1;
   __annotate_delete();
   auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
   pointer __p       = __allocation.ptr;
@@ -2526,7 +2528,9 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
     __throw_length_error();
   pointer __old_p = __get_pointer();
   size_type __cap =
-      __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1;
+      __old_cap < __ms / 2 - __alignment
+          ? __recommend(std::max<size_type>(__old_cap + __delta_cap, 2 * __old_cap))
+          : __ms - 1;
   __annotate_delete();
   auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
   pointer __p       = __allocation.ptr;
diff --git a/libcxx/include/__cxx03/vector b/libcxx/include/__cxx03/vector
index 6ee35b4e36258..80da74ded67b7 100644
--- a/libcxx/include/__cxx03/vector
+++ b/libcxx/include/__cxx03/vector
@@ -2328,7 +2328,7 @@ vector<bool, _Allocator>::__recommend(size_type __new_size) const {
   const size_type __cap = capacity();
   if (__cap >= __ms / 2)
     return __ms;
-  return std::max(2 * __cap, __align_it(__new_size));
+  return std::max<size_type>(2 * __cap, __align_it(__new_size));
 }
 
 //  Default constructs __n objects starting at __end_
diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h
index b02b0dc1725f2..a888b9ab9fcc0 100644
--- a/libcxx/include/__vector/vector_bool.h
+++ b/libcxx/include/__vector/vector_bool.h
@@ -549,7 +549,7 @@ vector<bool, _Allocator>::__recommend(size_type __new_size) const {
   const size_type __cap = capacity();
   if (__cap >= __ms / 2)
     return __ms;
-  return std::max(2 * __cap, __align_it(__new_size));
+  return std::max<size_type>(2 * __cap, __align_it(__new_size));
 }
 
 //  Default constructs __n objects starting at __end_
diff --git a/libcxx/include/string b/libcxx/include/string
index ea9ba24084a3b..fa16cf6302590 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -2623,7 +2623,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
     __throw_length_error();
   pointer __old_p = __get_pointer();
   size_type __cap =
-      __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms;
+      __old_cap < __ms / 2 - __alignment ? __recommend(std::max<size_type>(__old_cap + __delta_cap, 2 * __old_cap)) : __ms;
   __annotate_delete();
   auto __guard      = std::__make_scope_guard(__annotate_new_size(*this));
   auto __allocation = std::__allocate_at_least(__alloc_, __cap + 1);

>From 3c84df6ba855b5cab8317ca8dc929f8b8d1934f7 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Thu, 9 Jan 2025 08:42:10 -0500
Subject: [PATCH 2/3] Add new tests

---
 .../vector.bool/sized_allocator.pass.cpp      | 121 ++++++++++++++++++
 1 file changed, 121 insertions(+)
 create mode 100644 libcxx/test/std/containers/sequences/vector.bool/sized_allocator.pass.cpp

diff --git a/libcxx/test/std/containers/sequences/vector.bool/sized_allocator.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/sized_allocator.pass.cpp
new file mode 100644
index 0000000000000..0964f3a57ed70
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/sized_allocator.pass.cpp
@@ -0,0 +1,121 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+// vector<bool>
+
+// This test examines ambiguous calls to std::max in vector<bool>
+// Fix https://github.com/llvm/llvm-project/issues/121713
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <memory>
+#include <new>
+#include <vector>
+
+#include "test_macros.h"
+
+template <typename T, typename SIZE_TYPE = std::size_t, typename DIFF_TYPE = std::ptrdiff_t>
+class sized_allocator {
+  template <typename U, typename Sz, typename Diff>
+  friend class sized_allocator;
+
+public:
+  using value_type                  = T;
+  using size_type                   = SIZE_TYPE;
+  using difference_type             = DIFF_TYPE;
+  using propagate_on_container_swap = std::true_type;
+
+  TEST_CONSTEXPR_CXX20 explicit sized_allocator(int d = 0) : data_(d) {}
+
+  template <typename U, typename Sz, typename Diff>
+  TEST_CONSTEXPR_CXX20 sized_allocator(const sized_allocator<U, Sz, Diff>& a) TEST_NOEXCEPT : data_(a.data_) {}
+
+  TEST_CONSTEXPR_CXX20 T* allocate(size_type n) {
+    if (n > max_size())
+      TEST_THROW(std::bad_array_new_length());
+    return std::allocator<T>().allocate(n);
+  }
+
+  TEST_CONSTEXPR_CXX20 void deallocate(T* p, size_type n) TEST_NOEXCEPT { std::allocator<T>().deallocate(p, n); }
+
+  TEST_CONSTEXPR size_type max_size() const TEST_NOEXCEPT {
+    return std::numeric_limits<size_type>::max() / sizeof(value_type);
+  }
+
+private:
+  int data_;
+
+  TEST_CONSTEXPR friend bool operator==(const sized_allocator& a, const sized_allocator& b) {
+    return a.data_ == b.data_;
+  }
+  TEST_CONSTEXPR friend bool operator!=(const sized_allocator& a, const sized_allocator& b) {
+    return a.data_ != b.data_;
+  }
+};
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  // The following tests are typical ways to trigger reallocations where `std::max` is used to calculate the capacity.
+  {
+    using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.resize(10);
+  }
+  {
+    using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.assign(10, true);
+  }
+  {
+    using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.insert(c.end(), true);
+  }
+  {
+    using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.insert(c.end(), 10, true);
+  }
+  {
+    using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.push_back(true);
+  }
+  {
+    using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.resize(10, true);
+  }
+  {
+    using Alloc = sized_allocator<bool, std::uint32_t, std::int32_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.resize(10);
+  }
+  {
+    using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.resize(10);
+  }
+  {
+    using Alloc = sized_allocator<bool, std::size_t, std::ptrdiff_t>;
+    std::vector<bool, Alloc> c(Alloc(1));
+    c.resize(10);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER >= 20
+  static_assert(tests());
+#endif
+  return 0;
+}

>From 6a4cb625372c05636c66191c954080d3f2e7f286 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 15 Jan 2025 13:04:11 -0500
Subject: [PATCH 3/3] Address ldionne's comments

---
 libcxx/include/__cxx03/string                 | 41 ++++++-------
 libcxx/include/__cxx03/vector                 |  2 +-
 libcxx/include/string                         | 36 +++++------
 .../vector.bool/sized_allocator.pass.cpp      | 59 +++++++------------
 4 files changed, 58 insertions(+), 80 deletions(-)

diff --git a/libcxx/include/__cxx03/string b/libcxx/include/__cxx03/string
index c29f74290bd41..e93b444386340 100644
--- a/libcxx/include/__cxx03/string
+++ b/libcxx/include/__cxx03/string
@@ -728,8 +728,8 @@ operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs, basic_strin
 
 #endif
 
-extern template _LIBCPP_EXPORTED_FROM_ABI string operator+
-    <char, char_traits<char>, allocator<char> >(char const*, string const&);
+extern template
+    _LIBCPP_EXPORTED_FROM_ABI string operator+ <char, char_traits<char>, allocator<char> >(char const*, string const&);
 
 template <class _Iter>
 struct __string_is_trivial_iterator : public false_type {};
@@ -1534,8 +1534,8 @@ public:
   }
 #endif // _LIBCPP_CXX03_LANG
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
-  insert(size_type __pos1, const basic_string& __str) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const basic_string& __str) {
     return insert(__pos1, __str.data(), __str.size());
   }
 
@@ -1574,8 +1574,8 @@ public:
   }
 #endif
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
-  insert(const_iterator __pos, size_type __n, value_type __c) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, size_type __n, value_type __c) {
     difference_type __p = __pos - begin();
     insert(static_cast<size_type>(__p), __n, __c);
     return begin() + __p;
@@ -1590,8 +1590,8 @@ public:
   insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last);
 
 #ifndef _LIBCPP_CXX03_LANG
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
-  insert(const_iterator __pos, initializer_list<value_type> __il) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, initializer_list<value_type> __il) {
     return insert(__pos, __il.begin(), __il.end());
   }
 #endif // _LIBCPP_CXX03_LANG
@@ -1678,8 +1678,8 @@ public:
   _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const;
 
 #if _LIBCPP_STD_VER <= 20
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string
-  substr(size_type __pos = 0, size_type __n = npos) const {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string substr(size_type __pos = 0, size_type __n = npos) const {
     return basic_string(*this, __pos, __n);
   }
 #else
@@ -2277,8 +2277,8 @@ template <class _CharT,
           class _Traits,
           class _Allocator = allocator<_CharT>,
           class            = enable_if_t<__is_allocator<_Allocator>::value> >
-explicit basic_string(basic_string_view<_CharT, _Traits>,
-                      const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>;
+explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
+    -> basic_string<_CharT, _Traits, _Allocator>;
 
 template <class _CharT,
           class _Traits,
@@ -2482,10 +2482,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
   if (__delta_cap > __ms - __old_cap - 1)
     __throw_length_error();
   pointer __old_p = __get_pointer();
-  size_type __cap =
-      __old_cap < __ms / 2 - __alignment
-          ? __recommend(std::max<size_type>(__old_cap + __delta_cap, 2 * __old_cap))
-          : __ms - 1;
+  size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(__old_cap + __delta_cap, 2 * __old_cap) : __ms - 1;
   __annotate_delete();
   auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
   pointer __p       = __allocation.ptr;
@@ -2528,9 +2525,7 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
     __throw_length_error();
   pointer __old_p = __get_pointer();
   size_type __cap =
-      __old_cap < __ms / 2 - __alignment
-          ? __recommend(std::max<size_type>(__old_cap + __delta_cap, 2 * __old_cap))
-          : __ms - 1;
+      __old_cap < __ms / 2 - __alignment ? __recommend(std::max__old_cap + __delta_cap, 2 * __old_cap) : __ms - 1;
   __annotate_delete();
   auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
   pointer __p       = __allocation.ptr;
@@ -4303,8 +4298,8 @@ operator""s(const char* __str, size_t __len) {
 }
 
 #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<wchar_t>
-operator""s(const wchar_t* __str, size_t __len) {
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<wchar_t> operator""s(const wchar_t* __str, size_t __len) {
   return basic_string<wchar_t>(__str, __len);
 }
 #  endif
@@ -4315,8 +4310,8 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string<char8_t> operator""s(const c
 }
 #  endif
 
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char16_t>
-operator""s(const char16_t* __str, size_t __len) {
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char16_t> operator""s(const char16_t* __str, size_t __len) {
   return basic_string<char16_t>(__str, __len);
 }
 
diff --git a/libcxx/include/__cxx03/vector b/libcxx/include/__cxx03/vector
index 80da74ded67b7..6ee35b4e36258 100644
--- a/libcxx/include/__cxx03/vector
+++ b/libcxx/include/__cxx03/vector
@@ -2328,7 +2328,7 @@ vector<bool, _Allocator>::__recommend(size_type __new_size) const {
   const size_type __cap = capacity();
   if (__cap >= __ms / 2)
     return __ms;
-  return std::max<size_type>(2 * __cap, __align_it(__new_size));
+  return std::max(2 * __cap, __align_it(__new_size));
 }
 
 //  Default constructs __n objects starting at __end_
diff --git a/libcxx/include/string b/libcxx/include/string
index fa16cf6302590..aa97405aa910f 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1215,8 +1215,8 @@ public:
     return assign(__il.begin(), __il.size());
   }
 #  endif
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
-  operator=(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) {
     return assign(__s);
   }
 #  if _LIBCPP_STD_VER >= 23
@@ -1520,8 +1520,8 @@ public:
   }
 #  endif // _LIBCPP_CXX03_LANG
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
-  insert(size_type __pos1, const basic_string& __str) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const basic_string& __str) {
     return insert(__pos1, __str.data(), __str.size());
   }
 
@@ -1560,8 +1560,8 @@ public:
   }
 #  endif
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
-  insert(const_iterator __pos, size_type __n, value_type __c) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, size_type __n, value_type __c) {
     difference_type __p = __pos - begin();
     insert(static_cast<size_type>(__p), __n, __c);
     return begin() + __p;
@@ -1576,8 +1576,8 @@ public:
   insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last);
 
 #  ifndef _LIBCPP_CXX03_LANG
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
-  insert(const_iterator __pos, initializer_list<value_type> __il) {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, initializer_list<value_type> __il) {
     return insert(__pos, __il.begin(), __il.end());
   }
 #  endif // _LIBCPP_CXX03_LANG
@@ -1664,8 +1664,8 @@ public:
   _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const;
 
 #  if _LIBCPP_STD_VER <= 20
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string
-  substr(size_type __pos = 0, size_type __n = npos) const {
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string substr(size_type __pos = 0, size_type __n = npos) const {
     return basic_string(*this, __pos, __n);
   }
 #  else
@@ -2441,8 +2441,8 @@ template <class _CharT,
           class _Traits,
           class _Allocator = allocator<_CharT>,
           class            = enable_if_t<__is_allocator<_Allocator>::value> >
-explicit basic_string(basic_string_view<_CharT, _Traits>,
-                      const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>;
+explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
+    -> basic_string<_CharT, _Traits, _Allocator>;
 
 template <class _CharT,
           class _Traits,
@@ -2623,7 +2623,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
     __throw_length_error();
   pointer __old_p = __get_pointer();
   size_type __cap =
-      __old_cap < __ms / 2 - __alignment ? __recommend(std::max<size_type>(__old_cap + __delta_cap, 2 * __old_cap)) : __ms;
+      __old_cap < __ms / 2 - __alignment
+          ? __recommend(std::max<size_type>(__old_cap + __delta_cap, 2 * __old_cap))
+          : __ms;
   __annotate_delete();
   auto __guard      = std::__make_scope_guard(__annotate_new_size(*this));
   auto __allocation = std::__allocate_at_least(__alloc_, __cap + 1);
@@ -4048,8 +4050,8 @@ operator""s(const char* __str, size_t __len) {
 }
 
 #    if _LIBCPP_HAS_WIDE_CHARACTERS
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<wchar_t>
-operator""s(const wchar_t* __str, size_t __len) {
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<wchar_t> operator""s(const wchar_t* __str, size_t __len) {
   return basic_string<wchar_t>(__str, __len);
 }
 #    endif
@@ -4060,8 +4062,8 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string<char8_t> operator""s(const c
 }
 #    endif
 
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char16_t>
-operator""s(const char16_t* __str, size_t __len) {
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char16_t> operator""s(const char16_t* __str, size_t __len) {
   return basic_string<char16_t>(__str, __len);
 }
 
diff --git a/libcxx/test/std/containers/sequences/vector.bool/sized_allocator.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/sized_allocator.pass.cpp
index 0964f3a57ed70..a322dd4f8649e 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/sized_allocator.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/sized_allocator.pass.cpp
@@ -20,93 +20,74 @@
 #include <new>
 #include <vector>
 
+#include "sized_allocator.h"
 #include "test_macros.h"
 
-template <typename T, typename SIZE_TYPE = std::size_t, typename DIFF_TYPE = std::ptrdiff_t>
-class sized_allocator {
-  template <typename U, typename Sz, typename Diff>
-  friend class sized_allocator;
-
-public:
-  using value_type                  = T;
-  using size_type                   = SIZE_TYPE;
-  using difference_type             = DIFF_TYPE;
-  using propagate_on_container_swap = std::true_type;
-
-  TEST_CONSTEXPR_CXX20 explicit sized_allocator(int d = 0) : data_(d) {}
-
-  template <typename U, typename Sz, typename Diff>
-  TEST_CONSTEXPR_CXX20 sized_allocator(const sized_allocator<U, Sz, Diff>& a) TEST_NOEXCEPT : data_(a.data_) {}
-
-  TEST_CONSTEXPR_CXX20 T* allocate(size_type n) {
-    if (n > max_size())
-      TEST_THROW(std::bad_array_new_length());
-    return std::allocator<T>().allocate(n);
-  }
-
-  TEST_CONSTEXPR_CXX20 void deallocate(T* p, size_type n) TEST_NOEXCEPT { std::allocator<T>().deallocate(p, n); }
-
-  TEST_CONSTEXPR size_type max_size() const TEST_NOEXCEPT {
-    return std::numeric_limits<size_type>::max() / sizeof(value_type);
-  }
-
-private:
-  int data_;
-
-  TEST_CONSTEXPR friend bool operator==(const sized_allocator& a, const sized_allocator& b) {
-    return a.data_ == b.data_;
-  }
-  TEST_CONSTEXPR friend bool operator!=(const sized_allocator& a, const sized_allocator& b) {
-    return a.data_ != b.data_;
-  }
-};
-
 TEST_CONSTEXPR_CXX20 bool tests() {
   // The following tests are typical ways to trigger reallocations where `std::max` is used to calculate the capacity.
+  // The purpose of these tests is to ensure that the ambiguous internal calls to `std::max` have been fixed.
   {
     using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.resize(10);
+    assert(c.size() == 10);
+    assert(c.capacity() >= 10);
   }
   {
     using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.assign(10, true);
+    assert(c.size() == 10);
+    assert(c.capacity() >= 10);
   }
   {
     using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.insert(c.end(), true);
+    assert(c.size() == 1);
+    assert(c.capacity() >= 1);
   }
   {
     using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.insert(c.end(), 10, true);
+    assert(c.size() == 10);
+    assert(c.capacity() >= 10);
   }
   {
     using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.push_back(true);
+    assert(c.size() == 1);
+    assert(c.capacity() >= 1);
   }
   {
     using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.resize(10, true);
+    assert(c.size() == 10);
+    assert(c.capacity() >= 10);
   }
   {
     using Alloc = sized_allocator<bool, std::uint32_t, std::int32_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.resize(10);
+    assert(c.size() == 10);
+    assert(c.capacity() >= 10);
   }
   {
     using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.resize(10);
+    assert(c.size() == 10);
+    assert(c.capacity() >= 10);
   }
   {
     using Alloc = sized_allocator<bool, std::size_t, std::ptrdiff_t>;
     std::vector<bool, Alloc> c(Alloc(1));
     c.resize(10);
+    assert(c.size() == 10);
+    assert(c.capacity() >= 10);
   }
 
   return true;



More information about the libcxx-commits mailing list