[libcxx-commits] [libcxx] be10b1f - [libcxx] Make allocator<T>:allocate throw bad_array_new_length
Mikhail Maltsev via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Oct 18 11:13:37 PDT 2021
Author: Mikhail Maltsev
Date: 2021-10-18T19:12:42+01:00
New Revision: be10b1f1cc5fc621c378da97810ffc13b2a9af71
URL: https://github.com/llvm/llvm-project/commit/be10b1f1cc5fc621c378da97810ffc13b2a9af71
DIFF: https://github.com/llvm/llvm-project/commit/be10b1f1cc5fc621c378da97810ffc13b2a9af71.diff
LOG: [libcxx] Make allocator<T>:allocate throw bad_array_new_length
Currently the member functions std::allocator<T>::allocate,
std::experimental::pmr::polymorphic_allocator::allocate and
std::resource_adaptor<T>::do_allocate throw an exception of type
std::length_error when the requested size exceeds the maximum size.
According to the C++ standard ([allocator.members]/4,
[mem.poly.allocator.mem]/1), std::allocator<T>::allocate and
std::pmr::polymorphic_allocator::allocate must throw a
std::bad_array_new_length exception in this case.
The patch fixes the issue with std::allocator<T>::allocate and changes
the type the exception thrown by
std::experimental::pmr::resource_adaptor<T>::do_allocate to
std::bad_array_new_length as well for consistency.
The patch resolves LWG 3237, LWG 3038 and LWG 3190.
Reviewed By: ldionne, #libc, Quuxplusone
Differential Revision: https://reviews.llvm.org/D110846
Added:
Modified:
libcxx/docs/ReleaseNotes.rst
libcxx/docs/Status/Cxx20Issues.csv
libcxx/include/__memory/allocator.h
libcxx/include/experimental/memory_resource
libcxx/include/new
libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
libcxx/test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/allocate.pass.cpp
libcxx/test/std/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/do_allocate_and_deallocate.pass.cpp
libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index 8d01a49a7efb9..7ad192361b09c 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -72,6 +72,12 @@ API Changes
Calls to these functions where the template argument was deduced by the
compiler are unaffected by this change.
+- The functions ``std::allocator<T>::allocate`` and
+ ``std::experimental::pmr::polymorphic_allocator<T>::allocate`` now throw
+ an exception of type ``std::bad_array_new_length`` when the requested size
+ exceeds the maximum supported size, as required by the C++ standard.
+ Previously the type ``std::length_error`` was used.
+
Build System Changes
--------------------
diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index e2c994019424c..410cedcaa53de 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -108,7 +108,7 @@
"`3025 <https://wg21.link/LWG3025>`__","Map-like container deduction guides should use ``pair<Key, T>``\ , not ``pair<const Key, T>``\ ","San Diego","|Complete|",""
"`3031 <https://wg21.link/LWG3031>`__","Algorithms and predicates with non-const reference arguments","San Diego","",""
"`3037 <https://wg21.link/LWG3037>`__","``polymorphic_allocator``\ and incomplete types","San Diego","",""
-"`3038 <https://wg21.link/LWG3038>`__","``polymorphic_allocator::allocate``\ should not allow integer overflow to create vulnerabilities","San Diego","",""
+"`3038 <https://wg21.link/LWG3038>`__","``polymorphic_allocator::allocate``\ should not allow integer overflow to create vulnerabilities","San Diego","|Complete|","14.0"
"`3054 <https://wg21.link/LWG3054>`__","``uninitialized_copy``\ appears to not be able to meet its exception-safety guarantee","San Diego","",""
"`3065 <https://wg21.link/LWG3065>`__","LWG 2989 missed that all ``path``\ 's other operators should be hidden friends as well","San Diego","|Complete|",""
"`3096 <https://wg21.link/LWG3096>`__","``path::lexically_relative``\ is confused by trailing slashes","San Diego","|Complete|",""
@@ -162,7 +162,7 @@
"","","","",""
"`3231 <https://wg21.link/LWG3231>`__","``year_month_day_last::day``\ specification does not cover ``!ok()``\ values","Belfast","|Nothing To Do|",""
"`3225 <https://wg21.link/LWG3225>`__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","Belfast","","","|chrono|"
-"`3190 <https://wg21.link/LWG3190>`__","``std::allocator::allocate``\ sometimes returns too little storage","Belfast","",""
+"`3190 <https://wg21.link/LWG3190>`__","``std::allocator::allocate``\ sometimes returns too little storage","Belfast","|Complete|","14.0"
"`3218 <https://wg21.link/LWG3218>`__","Modifier for ``%d``\ parse flag does not match POSIX and ``format``\ specification","Belfast","","","|chrono| |format|"
"`3224 <https://wg21.link/LWG3224>`__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","Belfast","","","|chrono|"
"`3230 <https://wg21.link/LWG3230>`__","Format specifier ``%y/%Y``\ is missing locale alternative versions","Belfast","","","|chrono| |format|"
@@ -200,7 +200,7 @@
"`3201 <https://wg21.link/LWG3201>`__","``lerp``\ should be marked as ``noexcept``\ ","Prague","|Complete|",""
"`3226 <https://wg21.link/LWG3226>`__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time<Duration2, TimeZonePtr2>``\ ","Prague","","","|chrono|"
"`3233 <https://wg21.link/LWG3233>`__","Broken requirements for ``shared_ptr``\ converting constructors","Prague","",""
-"`3237 <https://wg21.link/LWG3237>`__","LWG 3038 and 3190 have inconsistent PRs","Prague","",""
+"`3237 <https://wg21.link/LWG3237>`__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","14.0"
"`3238 <https://wg21.link/LWG3238>`__","Insufficiently-defined behavior of ``std::function``\ deduction guides","Prague","",""
"`3242 <https://wg21.link/LWG3242>`__","``std::format``\ : missing rules for ``arg-id``\ in ``width``\ and ``precision``\ ","Prague","|Complete|","Clang 14","|format|"
"`3243 <https://wg21.link/LWG3243>`__","``std::format``\ and negative zeroes","Prague","","","|format|"
diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h
index f99bee2b8f1b9..283212fb703dd 100644
--- a/libcxx/include/__memory/allocator.h
+++ b/libcxx/include/__memory/allocator.h
@@ -98,8 +98,7 @@ class _LIBCPP_TEMPLATE_VIS allocator
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_Tp* allocate(size_t __n) {
if (__n > allocator_traits<allocator>::max_size(*this))
- __throw_length_error("allocator<T>::allocate(size_t n)"
- " 'n' exceeds maximum supported size");
+ __throw_bad_array_new_length();
if (__libcpp_is_constant_evaluated()) {
return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
} else {
@@ -181,8 +180,7 @@ class _LIBCPP_TEMPLATE_VIS allocator<const _Tp>
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
const _Tp* allocate(size_t __n) {
if (__n > allocator_traits<allocator>::max_size(*this))
- __throw_length_error("allocator<const T>::allocate(size_t n)"
- " 'n' exceeds maximum supported size");
+ __throw_bad_array_new_length();
if (__libcpp_is_constant_evaluated()) {
return static_cast<const _Tp*>(::operator new(__n * sizeof(_Tp)));
} else {
diff --git a/libcxx/include/experimental/memory_resource b/libcxx/include/experimental/memory_resource
index 816d21f513681..75e502d78c2db 100644
--- a/libcxx/include/experimental/memory_resource
+++ b/libcxx/include/experimental/memory_resource
@@ -183,11 +183,8 @@ public:
// 8.6.3, memory.polymorphic.allocator.mem
_LIBCPP_INLINE_VISIBILITY
_ValueType* allocate(size_t __n) {
- if (__n > __max_size()) {
- __throw_length_error(
- "std::experimental::pmr::polymorphic_allocator<T>::allocate(size_t n)"
- " 'n' exceeds maximum supported size");
- }
+ if (__n > __max_size())
+ __throw_bad_array_new_length();
return static_cast<_ValueType*>(
__res_->allocate(__n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType))
);
@@ -384,11 +381,8 @@ public:
private:
virtual void * do_allocate(size_t __bytes, size_t)
{
- if (__bytes > __max_size()) {
- __throw_length_error(
- "std::experimental::pmr::resource_adaptor<T>::do_allocate(size_t bytes, size_t align)"
- " 'bytes' exceeds maximum supported size");
- }
+ if (__bytes > __max_size())
+ __throw_bad_array_new_length();
size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign;
return __alloc_.allocate(__s);
}
diff --git a/libcxx/include/new b/libcxx/include/new
index 2d1417a97586d..711b3ccd225fd 100644
--- a/libcxx/include/new
+++ b/libcxx/include/new
@@ -149,6 +149,16 @@ _LIBCPP_FUNC_VIS new_handler get_new_handler() _NOEXCEPT;
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_bad_alloc(); // not in C++ spec
+_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
+void __throw_bad_array_new_length()
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ throw bad_array_new_length();
+#else
+ _VSTD::abort();
+#endif
+}
+
#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) && \
!defined(_LIBCPP_ABI_VCRUNTIME)
#ifndef _LIBCPP_CXX03_LANG
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
index 927b36f594511..fd20a7d97fda1 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
@@ -7,6 +7,8 @@
{'is_defined': False, 'name': '_ZNSt13runtime_errorD2Ev', 'type': 'FUNC'}
{'is_defined': False, 'name': '_ZNSt14overflow_errorD1Ev', 'type': 'FUNC'}
{'is_defined': False, 'name': '_ZNSt16invalid_argumentD1Ev', 'type': 'FUNC'}
+{'is_defined': False, 'name': '_ZNSt20bad_array_new_lengthC1Ev', 'type': 'FUNC'}
+{'is_defined': False, 'name': '_ZNSt20bad_array_new_lengthD1Ev', 'type': 'FUNC'}
{'is_defined': False, 'name': '_ZNSt8bad_castC1Ev', 'type': 'FUNC'}
{'is_defined': False, 'name': '_ZNSt8bad_castD1Ev', 'type': 'FUNC'}
{'is_defined': False, 'name': '_ZNSt8bad_castD2Ev', 'type': 'FUNC'}
@@ -20,6 +22,7 @@
{'is_defined': False, 'name': '_ZTISt13runtime_error', 'size': 0, 'type': 'OBJECT'}
{'is_defined': False, 'name': '_ZTISt14overflow_error', 'size': 0, 'type': 'OBJECT'}
{'is_defined': False, 'name': '_ZTISt16invalid_argument', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': False, 'name': '_ZTISt20bad_array_new_length', 'size': 0, 'type': 'OBJECT'}
{'is_defined': False, 'name': '_ZTISt8bad_cast', 'size': 0, 'type': 'OBJECT'}
{'is_defined': False, 'name': '_ZTISt9bad_alloc', 'size': 0, 'type': 'OBJECT'}
{'is_defined': False, 'name': '_ZTISt9exception', 'size': 0, 'type': 'OBJECT'}
diff --git a/libcxx/test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/allocate.pass.cpp b/libcxx/test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/allocate.pass.cpp
index 53c7c31443d34..779c0eb231c64 100644
--- a/libcxx/test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/allocate.pass.cpp
+++ b/libcxx/test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/allocate.pass.cpp
@@ -61,11 +61,11 @@ void testAllocForSizeThrows() {
size_t sizeTypeMax = std::numeric_limits<std::size_t>::max();
if (maxSize != sizeTypeMax)
{
- // Test that allocating size_t(~0) throws bad alloc.
+ // Test that allocating size_t(~0) throws bad_array_new_length.
try {
a.allocate(sizeTypeMax);
assert(false);
- } catch (std::exception const&) {
+ } catch (std::bad_array_new_length const&) {
}
// Test that allocating even one more than the max size does throw.
@@ -73,7 +73,7 @@ void testAllocForSizeThrows() {
try {
a.allocate(overSize);
assert(false);
- } catch (std::exception const&) {
+ } catch (std::bad_array_new_length const&) {
}
}
}
diff --git a/libcxx/test/std/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/do_allocate_and_deallocate.pass.cpp b/libcxx/test/std/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/do_allocate_and_deallocate.pass.cpp
index 40ffbb1cbdbb1..3c17520aeff2e 100644
--- a/libcxx/test/std/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/do_allocate_and_deallocate.pass.cpp
+++ b/libcxx/test/std/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/do_allocate_and_deallocate.pass.cpp
@@ -99,7 +99,7 @@ void check_alloc_max_size() {
try {
m1.allocate(size);
assert(false);
- } catch (std::exception const&) {
+ } catch (std::bad_array_new_length const&) {
}
}
#endif
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp
index 42013de1ccdf6..6b9b12c822424 100644
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp
@@ -24,7 +24,7 @@ void test_max(size_t count)
try {
TEST_IGNORE_NODISCARD a.allocate(count);
assert(false);
- } catch (const std::exception &) {
+ } catch (const std::bad_array_new_length &) {
}
}
More information about the libcxx-commits
mailing list