[libcxx-commits] [libcxx] [libc++][vector] Make constructor vector(count, value, allocator) exception-safe (PR #82033)

Mateusz Zych via libcxx-commits libcxx-commits at lists.llvm.org
Fri Feb 16 15:44:48 PST 2024


https://github.com/mtezych updated https://github.com/llvm/llvm-project/pull/82033

>From 7ff58b52a916bf4c64be0be2e84dff11668d3de4 Mon Sep 17 00:00:00 2001
From: Mateusz Zych <mte.zych at gmail.com>
Date: Fri, 16 Feb 2024 23:35:10 +0300
Subject: [PATCH 1/2] [libc++][vector] Make constructor vector(count, value,
 allocator) exception-safe

---
 libcxx/include/vector | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcxx/include/vector b/libcxx/include/vector
index ce7df7a9f04207..c3e3f05671f8fa 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -433,10 +433,12 @@ public:
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
   vector(size_type __n, const value_type& __x, const allocator_type& __a)
       : __end_cap_(nullptr, __a) {
+    auto __guard = std::__make_exception_guard(__destroy_vector(*this));
     if (__n > 0) {
       __vallocate(__n);
       __construct_at_end(__n, __x);
     }
+    __guard.__complete();
   }
 
   template <class _InputIterator,

>From 8bb312934ccfc3dae276e88d7d698fffaf848a13 Mon Sep 17 00:00:00 2001
From: Mateusz Zych <mte.zych at gmail.com>
Date: Fri, 16 Feb 2024 21:48:15 +0300
Subject: [PATCH 2/2] exception safety tests for constructors of std::vector

---
 .../vector/vector.cons/exceptions.pass.cpp    | 26 ++++++++++++++++---
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp
index 3ef5aeecc1b0c9..0bf632292ea1d0 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp
@@ -41,6 +41,7 @@ struct Allocator {
 
 struct ThrowingT {
   int* throw_after_n_ = nullptr;
+
   ThrowingT() { throw 0; }
 
   ThrowingT(int& throw_after_n) : throw_after_n_(&throw_after_n) {
@@ -104,6 +105,7 @@ void check_new_delete_called() {
 
 int main(int, char**) {
   using AllocVec = std::vector<int, Allocator<int> >;
+
   try { // vector()
     AllocVec vec;
   } catch (int) {
@@ -111,23 +113,23 @@ int main(int, char**) {
   check_new_delete_called();
 
   try { // Throw in vector(size_type) from type
-    std::vector<ThrowingT> get_alloc(1);
+    std::vector<ThrowingT> vec(1);
   } catch (int) {
   }
   check_new_delete_called();
 
 #if TEST_STD_VER >= 14
-  try { // Throw in vector(size_type, value_type) from type
+  try { // Throw in vector(size_type, const value_type&) from type
     int throw_after = 1;
     ThrowingT v(throw_after);
-    std::vector<ThrowingT> get_alloc(1, v);
+    std::vector<ThrowingT> vec(1, v);
   } catch (int) {
   }
   check_new_delete_called();
 
   try { // Throw in vector(size_type, const allocator_type&) from allocator
     Allocator<int> alloc(false);
-    AllocVec get_alloc(0, alloc);
+    AllocVec vec(0, alloc);
   } catch (int) {
   }
   check_new_delete_called();
@@ -137,6 +139,22 @@ int main(int, char**) {
   } catch (int) {
   }
   check_new_delete_called();
+
+  // https://github.com/llvm/llvm-project/commit/8ff4d218a80b887bb645ec426aefa1ab7144c5f3
+  // https://github.com/llvm/llvm-project/commit/7da4ee6f23dd14464ee869caec18b5421d1cf7ca
+  // https://godbolt.org/z/E47aYG8Mj
+  // https://github.com/llvm/llvm-project/issues/59651
+  // https://github.com/llvm/llvm-project/issues/58392
+
+  try { // Throw in vector(size_type, const value_type&, const allocator_type&) from allocator
+  } catch (int) {
+  }
+  check_new_delete_called();
+
+  try { // Throw in vector(size_type, const value_type&, const allocator_type&) from the type
+  } catch (int) {
+  }
+  check_new_delete_called();
 #endif  // TEST_STD_VER >= 14
 
   try { // Throw in vector(InputIterator, InputIterator) from input iterator



More information about the libcxx-commits mailing list