about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--absl/container/fixed_array_exception_safety_test.cc87
-rw-r--r--absl/container/inlined_vector_exception_safety_test.cc26
-rw-r--r--absl/container/internal/inlined_vector.h8
-rw-r--r--absl/strings/internal/str_format/bind.cc9
-rw-r--r--absl/strings/internal/str_format/bind.h8
5 files changed, 115 insertions, 23 deletions
diff --git a/absl/container/fixed_array_exception_safety_test.cc b/absl/container/fixed_array_exception_safety_test.cc
index 9aabfd5c95a6..5ebeac05b7b4 100644
--- a/absl/container/fixed_array_exception_safety_test.cc
+++ b/absl/container/fixed_array_exception_safety_test.cc
@@ -12,9 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/container/fixed_array.h"
-
 #include "absl/base/config.h"
+#include "absl/container/fixed_array.h"
 
 #ifdef ABSL_HAVE_EXCEPTIONS
 
@@ -37,10 +36,19 @@ constexpr int kUpdatedValue = 10;
 using ::testing::TestThrowingCtor;
 
 using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
+using ThrowAlloc =
+    testing::ThrowingAllocator<Thrower, testing::AllocSpec::kEverythingThrows>;
+using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
+using MoveThrowAlloc =
+    testing::ThrowingAllocator<MoveThrower,
+                               testing::AllocSpec::kEverythingThrows>;
+
 using FixedArr = absl::FixedArray<Thrower, kInlined>;
+using FixedArrWithAlloc = absl::FixedArray<Thrower, kInlined, ThrowAlloc>;
 
-using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
 using MoveFixedArr = absl::FixedArray<MoveThrower, kInlined>;
+using MoveFixedArrWithAlloc =
+    absl::FixedArray<MoveThrower, kInlined, MoveThrowAlloc>;
 
 TEST(FixedArrayExceptionSafety, CopyConstructor) {
   auto small = FixedArr(kSmallSize);
@@ -50,6 +58,14 @@ TEST(FixedArrayExceptionSafety, CopyConstructor) {
   TestThrowingCtor<FixedArr>(large);
 }
 
+TEST(FixedArrayExceptionSafety, CopyConstructorWithAlloc) {
+  auto small = FixedArrWithAlloc(kSmallSize);
+  TestThrowingCtor<FixedArrWithAlloc>(small);
+
+  auto large = FixedArrWithAlloc(kLargeSize);
+  TestThrowingCtor<FixedArrWithAlloc>(large);
+}
+
 TEST(FixedArrayExceptionSafety, MoveConstructor) {
   TestThrowingCtor<FixedArr>(FixedArr(kSmallSize));
   TestThrowingCtor<FixedArr>(FixedArr(kLargeSize));
@@ -59,16 +75,35 @@ TEST(FixedArrayExceptionSafety, MoveConstructor) {
   TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kLargeSize));
 }
 
+TEST(FixedArrayExceptionSafety, MoveConstructorWithAlloc) {
+  TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kSmallSize));
+  TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kLargeSize));
+
+  // TypeSpec::kNoThrowMove
+  TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kSmallSize));
+  TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kLargeSize));
+}
+
 TEST(FixedArrayExceptionSafety, SizeConstructor) {
   TestThrowingCtor<FixedArr>(kSmallSize);
   TestThrowingCtor<FixedArr>(kLargeSize);
 }
 
+TEST(FixedArrayExceptionSafety, SizeConstructorWithAlloc) {
+  TestThrowingCtor<FixedArrWithAlloc>(kSmallSize);
+  TestThrowingCtor<FixedArrWithAlloc>(kLargeSize);
+}
+
 TEST(FixedArrayExceptionSafety, SizeValueConstructor) {
   TestThrowingCtor<FixedArr>(kSmallSize, Thrower());
   TestThrowingCtor<FixedArr>(kLargeSize, Thrower());
 }
 
+TEST(FixedArrayExceptionSafety, SizeValueConstructorWithAlloc) {
+  TestThrowingCtor<FixedArrWithAlloc>(kSmallSize, Thrower());
+  TestThrowingCtor<FixedArrWithAlloc>(kLargeSize, Thrower());
+}
+
 TEST(FixedArrayExceptionSafety, IteratorConstructor) {
   auto small = FixedArr(kSmallSize);
   TestThrowingCtor<FixedArr>(small.begin(), small.end());
@@ -77,6 +112,14 @@ TEST(FixedArrayExceptionSafety, IteratorConstructor) {
   TestThrowingCtor<FixedArr>(large.begin(), large.end());
 }
 
+TEST(FixedArrayExceptionSafety, IteratorConstructorWithAlloc) {
+  auto small = FixedArrWithAlloc(kSmallSize);
+  TestThrowingCtor<FixedArrWithAlloc>(small.begin(), small.end());
+
+  auto large = FixedArrWithAlloc(kLargeSize);
+  TestThrowingCtor<FixedArrWithAlloc>(large.begin(), large.end());
+}
+
 TEST(FixedArrayExceptionSafety, InitListConstructor) {
   constexpr int small_inlined = 3;
   using SmallFixedArr = absl::FixedArray<Thrower, small_inlined>;
@@ -90,7 +133,22 @@ TEST(FixedArrayExceptionSafety, InitListConstructor) {
       Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});
 }
 
-testing::AssertionResult ReadMemory(FixedArr* fixed_arr) {
+TEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) {
+  constexpr int small_inlined = 3;
+  using SmallFixedArrWithAlloc =
+      absl::FixedArray<Thrower, small_inlined, ThrowAlloc>;
+
+  TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{});
+  // Test inlined allocation
+  TestThrowingCtor<SmallFixedArrWithAlloc>(
+      std::initializer_list<Thrower>{Thrower{}, Thrower{}});
+  // Test out of line allocation
+  TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{
+      Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});
+}
+
+template <typename FixedArrT>
+testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) {
   // Marked volatile to prevent optimization. Used for running asan tests.
   volatile int sum = 0;
   for (const auto& thrower : *fixed_arr) {
@@ -101,7 +159,7 @@ testing::AssertionResult ReadMemory(FixedArr* fixed_arr) {
 
 TEST(FixedArrayExceptionSafety, Fill) {
   auto test_fill = testing::MakeExceptionSafetyTester()
-                       .WithContracts(ReadMemory)
+                       .WithContracts(ReadMemory<FixedArr>)
                        .WithOperation([&](FixedArr* fixed_arr_ptr) {
                          auto thrower =
                              Thrower(kUpdatedValue, testing::nothrow_ctor);
@@ -116,6 +174,25 @@ TEST(FixedArrayExceptionSafety, Fill) {
           .Test());
 }
 
+TEST(FixedArrayExceptionSafety, FillWithAlloc) {
+  auto test_fill = testing::MakeExceptionSafetyTester()
+                       .WithContracts(ReadMemory<FixedArrWithAlloc>)
+                       .WithOperation([&](FixedArrWithAlloc* fixed_arr_ptr) {
+                         auto thrower =
+                             Thrower(kUpdatedValue, testing::nothrow_ctor);
+                         fixed_arr_ptr->fill(thrower);
+                       });
+
+  EXPECT_TRUE(test_fill
+                  .WithInitialValue(
+                      FixedArrWithAlloc(kSmallSize, Thrower(kInitialValue)))
+                  .Test());
+  EXPECT_TRUE(test_fill
+                  .WithInitialValue(
+                      FixedArrWithAlloc(kLargeSize, Thrower(kInitialValue)))
+                  .Test());
+}
+
 }  // namespace
 
 }  // namespace absl
diff --git a/absl/container/inlined_vector_exception_safety_test.cc b/absl/container/inlined_vector_exception_safety_test.cc
index 937e43a5bf21..0e6a05b5f6a7 100644
--- a/absl/container/inlined_vector_exception_safety_test.cc
+++ b/absl/container/inlined_vector_exception_safety_test.cc
@@ -364,9 +364,11 @@ TYPED_TEST(OneSizeTest, EmplaceBack) {
   using VecT = typename TypeParam::VecT;
   constexpr static auto size = TypeParam::GetSizeAt(0);
 
+  // For testing calls to `emplace_back(...)` that reallocate.
   VecT full_vec{size};
   full_vec.resize(full_vec.capacity());
 
+  // For testing calls to `emplace_back(...)` that don't reallocate.
   VecT nonfull_vec{size};
   nonfull_vec.reserve(size + 1);
 
@@ -374,12 +376,11 @@ TYPED_TEST(OneSizeTest, EmplaceBack) {
       InlinedVectorInvariants<VecT>);
 
   EXPECT_TRUE(tester.WithInitialValue(nonfull_vec).Test([](VecT* vec) {
-    vec->emplace_back();  //
+    vec->emplace_back();
   }));
 
-  EXPECT_TRUE(tester.WithInitialValue(full_vec).Test([](VecT* vec) {
-    vec->emplace_back();  //
-  }));
+  EXPECT_TRUE(tester.WithInitialValue(full_vec).Test(
+      [](VecT* vec) { vec->emplace_back(); }));
 }
 
 TYPED_TEST(OneSizeTest, PopBack) {
@@ -418,6 +419,19 @@ TYPED_TEST(OneSizeTest, Erase) {
 
   EXPECT_TRUE(tester.Test([](VecT* vec) {
     auto it = vec->begin();
+    vec->erase(it, it);
+  }));
+  EXPECT_TRUE(tester.Test([](VecT* vec) {
+    auto it = vec->begin() + (vec->size() / 2);
+    vec->erase(it, it);
+  }));
+  EXPECT_TRUE(tester.Test([](VecT* vec) {
+    auto it = vec->begin() + (vec->size() - 1);
+    vec->erase(it, it);
+  }));
+
+  EXPECT_TRUE(tester.Test([](VecT* vec) {
+    auto it = vec->begin();
     vec->erase(it, it + 1);
   }));
   EXPECT_TRUE(tester.Test([](VecT* vec) {
@@ -452,9 +466,7 @@ TYPED_TEST(TwoSizeTest, Reserve) {
                     .WithInitialValue(VecT{from_size})
                     .WithContracts(InlinedVectorInvariants<VecT>);
 
-  EXPECT_TRUE(tester.Test([](VecT* vec) {
-    vec->reserve(to_capacity);  //
-  }));
+  EXPECT_TRUE(tester.Test([](VecT* vec) { vec->reserve(to_capacity); }));
 }
 
 TYPED_TEST(OneSizeTest, ShrinkToFit) {
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
index 54369c856829..7d08f7e306e4 100644
--- a/absl/container/internal/inlined_vector.h
+++ b/absl/container/internal/inlined_vector.h
@@ -539,12 +539,12 @@ template <typename ValueAdapter>
 auto Storage<T, N, A>::Resize(ValueAdapter values, size_type new_size) -> void {
   StorageView storage_view = MakeStorageView();
 
-  AllocationTransaction allocation_tx(GetAllocPtr());
-  ConstructionTransaction construction_tx(GetAllocPtr());
-
   IteratorValueAdapter<MoveIterator> move_values(
       MoveIterator(storage_view.data));
 
+  AllocationTransaction allocation_tx(GetAllocPtr());
+  ConstructionTransaction construction_tx(GetAllocPtr());
+
   absl::Span<value_type> construct_loop;
   absl::Span<value_type> move_construct_loop;
   absl::Span<value_type> destroy_loop;
@@ -727,8 +727,6 @@ auto Storage<T, N, A>::EmplaceBack(Args&&... args) -> reference {
 template <typename T, size_t N, typename A>
 auto Storage<T, N, A>::Erase(const_iterator from, const_iterator to)
     -> iterator {
-  assert(from != to);
-
   StorageView storage_view = MakeStorageView();
 
   size_type erase_size = std::distance(from, to);
diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc
index a31859ece2bc..45e335a30948 100644
--- a/absl/strings/internal/str_format/bind.cc
+++ b/absl/strings/internal/str_format/bind.cc
@@ -196,6 +196,15 @@ std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format,
   return *out;
 }
 
+std::string FormatPack(const UntypedFormatSpecImpl format,
+                       absl::Span<const FormatArgImpl> args) {
+  std::string out;
+  if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) {
+    out.clear();
+  }
+  return out;
+}
+
 int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
             absl::Span<const FormatArgImpl> args) {
   FILERawSink sink(output);
diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h
index 7df140a43633..7f46035113bb 100644
--- a/absl/strings/internal/str_format/bind.h
+++ b/absl/strings/internal/str_format/bind.h
@@ -178,12 +178,8 @@ bool FormatUntyped(FormatRawSinkImpl raw_sink,
 std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
                         absl::Span<const FormatArgImpl> args);
 
-inline std::string FormatPack(const UntypedFormatSpecImpl format,
-                              absl::Span<const FormatArgImpl> args) {
-  std::string out;
-  AppendPack(&out, format, args);
-  return out;
-}
+std::string FormatPack(const UntypedFormatSpecImpl format,
+                       absl::Span<const FormatArgImpl> args);
 
 int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
             absl::Span<const FormatArgImpl> args);