about summary refs log tree commit diff
path: root/absl
diff options
context:
space:
mode:
Diffstat (limited to 'absl')
-rw-r--r--absl/algorithm/container.h2
-rw-r--r--absl/base/BUILD.bazel1
-rw-r--r--absl/base/thread_annotations.h1
-rw-r--r--absl/container/BUILD.bazel11
-rw-r--r--absl/container/CMakeLists.txt19
-rw-r--r--absl/container/fixed_array.h52
-rw-r--r--absl/container/fixed_array_exception_safety_test.cc117
-rw-r--r--absl/container/inlined_vector.h25
-rw-r--r--absl/memory/memory.h33
-rw-r--r--absl/memory/memory_exception_safety_test.cc18
-rw-r--r--absl/memory/memory_test.cc43
-rw-r--r--absl/numeric/int128.cc26
-rw-r--r--absl/numeric/int128.h58
-rw-r--r--absl/numeric/int128_test.cc11
-rw-r--r--absl/strings/BUILD.bazel3
-rw-r--r--absl/strings/internal/str_split_internal.h26
-rw-r--r--absl/strings/str_format.h20
-rw-r--r--absl/strings/str_split_test.cc28
-rw-r--r--absl/synchronization/BUILD.bazel1
-rw-r--r--absl/types/BUILD.bazel6
-rw-r--r--absl/types/bad_any_cast.cc4
-rw-r--r--absl/types/bad_any_cast.h14
-rw-r--r--absl/types/bad_optional_access.cc4
-rw-r--r--absl/types/bad_optional_access.h14
-rw-r--r--absl/types/bad_variant_access.cc4
-rw-r--r--absl/types/bad_variant_access.h14
26 files changed, 487 insertions, 68 deletions
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index ebe3244555fa..acddec484b0a 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -634,7 +634,7 @@ container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n,
 
 // Note: `c_xx()` <algorithm> container versions for `remove()`, `remove_if()`,
 // and `unique()` are omitted, because it's not clear whether or not such
-// functions should call erase their supplied sequences afterwards. Either
+// functions should call erase on their supplied sequences afterwards. Either
 // behavior would be surprising for a different set of users.
 //
 
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index d117a4fea861..35414a252c62 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -387,6 +387,7 @@ cc_test(
         "//absl:windows": [],
         "//conditions:default": ["-pthread"],
     }),
+    tags = ["no_test_ios_x86_64"],
     deps = [":malloc_internal"],
 )
 
diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h
index 8d30b9324b52..fbb2797b825f 100644
--- a/absl/base/thread_annotations.h
+++ b/absl/base/thread_annotations.h
@@ -31,7 +31,6 @@
 // that evaluate to a concrete mutex object whenever possible. If the mutex
 // you want to refer to is not in scope, you may use a member pointer
 // (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object.
-//
 
 #ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
 #define ABSL_BASE_THREAD_ANNOTATIONS_H_
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 119d5c88de2a..07df3675207e 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -63,6 +63,17 @@ cc_test(
 )
 
 cc_test(
+    name = "fixed_array_exception_safety_test",
+    srcs = ["fixed_array_exception_safety_test.cc"],
+    copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
+    deps = [
+        ":fixed_array",
+        "//absl/base:exception_safety_testing",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "fixed_array_benchmark",
     srcs = ["fixed_array_benchmark.cc"],
     copts = ABSL_TEST_COPTS + ["$(STACK_FRAME_UNLIMITED)"],
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index f56ce92d81b5..d580b48976cb 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -84,6 +84,25 @@ absl_test(
 )
 
 
+# test fixed_array_exception_safety_test
+set(FIXED_ARRAY_EXCEPTION_SAFETY_TEST_SRC "fixed_array_exception_safety_test.cc")
+set(FIXED_ARRAY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
+  absl::container
+  absl_base_internal_exception_safety_testing
+)
+
+absl_test(
+  TARGET
+    fixed_array_exception_safety_test
+  SOURCES
+    ${FIXED_ARRAY_EXCEPTION_SAFETY_TEST_SRC}
+  PUBLIC_LIBRARIES
+    ${FIXED_ARRAY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
+  PRIVATE_COMPILE_FLAGS
+    ${ABSL_EXCEPTIONS_FLAG}
+)
+
+
 # test inlined_vector_test
 set(INLINED_VECTOR_TEST_SRC "inlined_vector_test.cc")
 set(INLINED_VECTOR_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate test_instance_tracker_lib)
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index 06bc80095c98..295f01088d21 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -108,33 +108,46 @@ class FixedArray {
           ? kInlineBytesDefault / sizeof(value_type)
           : inlined;
 
-  FixedArray(const FixedArray& other) : rep_(other.begin(), other.end()) {}
+  FixedArray(const FixedArray& other)
+      : FixedArray(other.begin(), other.end()) {}
+
   FixedArray(FixedArray&& other) noexcept(
   // clang-format off
       absl::allocator_is_nothrow<std::allocator<value_type>>::value &&
   // clang-format on
           std::is_nothrow_move_constructible<value_type>::value)
-      : rep_(std::make_move_iterator(other.begin()),
-             std::make_move_iterator(other.end())) {}
+      : FixedArray(std::make_move_iterator(other.begin()),
+                   std::make_move_iterator(other.end())) {}
 
   // Creates an array object that can store `n` elements.
   // Note that trivially constructible elements will be uninitialized.
-  explicit FixedArray(size_type n) : rep_(n) {}
+  explicit FixedArray(size_type n) : rep_(n) {
+    absl::memory_internal::uninitialized_default_construct_n(rep_.begin(),
+                                                             size());
+  }
 
   // Creates an array initialized with `n` copies of `val`.
-  FixedArray(size_type n, const value_type& val) : rep_(n, val) {}
+  FixedArray(size_type n, const value_type& val) : rep_(n) {
+    std::uninitialized_fill_n(data(), size(), val);
+  }
 
   // Creates an array initialized with the elements from the input
   // range. The array's size will always be `std::distance(first, last)`.
   // REQUIRES: Iter must be a forward_iterator or better.
   template <typename Iter, EnableIfForwardIterator<Iter> = 0>
-  FixedArray(Iter first, Iter last) : rep_(first, last) {}
+  FixedArray(Iter first, Iter last) : rep_(std::distance(first, last)) {
+    std::uninitialized_copy(first, last, data());
+  }
 
   // Creates the array from an initializer_list.
   FixedArray(std::initializer_list<T> init_list)
       : FixedArray(init_list.begin(), init_list.end()) {}
 
-  ~FixedArray() {}
+  ~FixedArray() noexcept {
+    for (Holder* cur = rep_.begin(); cur != rep_.end(); ++cur) {
+      cur->~Holder();
+    }
+  }
 
   // Assignments are deleted because they break the invariant that the size of a
   // `FixedArray` never changes.
@@ -431,32 +444,13 @@ class FixedArray {
 
   // Rep
   //
-  // A const Rep object holds FixedArray's size and data pointer.
+  // An instance of Rep manages the inline and out-of-line memory for FixedArray
   //
   class Rep : public InlineSpace<inline_elements> {
    public:
-    Rep(size_type n, const value_type& val) : n_(n), p_(MakeHolder(n)) {
-      std::uninitialized_fill_n(p_, n, val);
-    }
-
-    explicit Rep(size_type n) : n_(n), p_(MakeHolder(n)) {
-      // Loop optimizes to nothing for trivially constructible T.
-      for (Holder* p = p_; p != p_ + n; ++p)
-        // Note: no parens: default init only.
-        // Also note '::' to avoid Holder class placement new operator.
-        ::new (static_cast<void*>(p)) Holder;
-    }
-
-    template <typename Iter>
-    Rep(Iter first, Iter last)
-        : n_(std::distance(first, last)), p_(MakeHolder(n_)) {
-      std::uninitialized_copy(first, last, AsValue(p_));
-    }
+    explicit Rep(size_type n) : n_(n), p_(MakeHolder(n)) {}
 
-    ~Rep() {
-      // Destruction must be in reverse order.
-      // Loop optimizes to nothing for trivially destructible T.
-      for (Holder* p = end(); p != begin();) (--p)->~Holder();
+    ~Rep() noexcept {
       if (IsAllocated(size())) {
         std::allocator<Holder>().deallocate(p_, n_);
       } else {
diff --git a/absl/container/fixed_array_exception_safety_test.cc b/absl/container/fixed_array_exception_safety_test.cc
new file mode 100644
index 000000000000..c123c2a1c0d2
--- /dev/null
+++ b/absl/container/fixed_array_exception_safety_test.cc
@@ -0,0 +1,117 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <initializer_list>
+
+#include "absl/container/fixed_array.h"
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/exception_safety_testing.h"
+
+namespace absl {
+
+namespace {
+
+constexpr size_t kInlined = 25;
+constexpr size_t kSmallSize = kInlined / 2;
+constexpr size_t kLargeSize = kInlined * 2;
+
+constexpr int kInitialValue = 5;
+constexpr int kUpdatedValue = 10;
+
+using ::testing::TestThrowingCtor;
+
+using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
+using FixedArr = absl::FixedArray<Thrower, kInlined>;
+
+using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
+using MoveFixedArr = absl::FixedArray<MoveThrower, kInlined>;
+
+TEST(FixedArrayExceptionSafety, CopyConstructor) {
+  auto small = FixedArr(kSmallSize);
+  TestThrowingCtor<FixedArr>(small);
+
+  auto large = FixedArr(kLargeSize);
+  TestThrowingCtor<FixedArr>(large);
+}
+
+TEST(FixedArrayExceptionSafety, MoveConstructor) {
+  TestThrowingCtor<FixedArr>(FixedArr(kSmallSize));
+  TestThrowingCtor<FixedArr>(FixedArr(kLargeSize));
+
+  // TypeSpec::kNoThrowMove
+  TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kSmallSize));
+  TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kLargeSize));
+}
+
+TEST(FixedArrayExceptionSafety, SizeConstructor) {
+  TestThrowingCtor<FixedArr>(kSmallSize);
+  TestThrowingCtor<FixedArr>(kLargeSize);
+}
+
+TEST(FixedArrayExceptionSafety, SizeValueConstructor) {
+  TestThrowingCtor<FixedArr>(kSmallSize, Thrower());
+  TestThrowingCtor<FixedArr>(kLargeSize, Thrower());
+}
+
+TEST(FixedArrayExceptionSafety, IteratorConstructor) {
+  auto small = FixedArr(kSmallSize);
+  TestThrowingCtor<FixedArr>(small.begin(), small.end());
+
+  auto large = FixedArr(kLargeSize);
+  TestThrowingCtor<FixedArr>(large.begin(), large.end());
+}
+
+TEST(FixedArrayExceptionSafety, InitListConstructor) {
+  constexpr int small_inlined = 3;
+  using SmallFixedArr = absl::FixedArray<Thrower, small_inlined>;
+
+  TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{});
+  // Test inlined allocation
+  TestThrowingCtor<SmallFixedArr>(
+      std::initializer_list<Thrower>{Thrower{}, Thrower{}});
+  // Test out of line allocation
+  TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{
+      Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});
+}
+
+testing::AssertionResult ReadMemory(FixedArr* fixed_arr) {
+  // Marked volatile to prevent optimization. Used for running asan tests.
+  volatile int sum = 0;
+  for (const auto& thrower : *fixed_arr) {
+    sum += thrower.Get();
+  }
+  return testing::AssertionSuccess() << "Values sum to [" << sum << "]";
+}
+
+TEST(FixedArrayExceptionSafety, Fill) {
+  auto test_fill = testing::MakeExceptionSafetyTester()
+                       .WithInvariants(ReadMemory)
+                       .WithOperation([&](FixedArr* fixed_arr_ptr) {
+                         auto thrower =
+                             Thrower(kUpdatedValue, testing::nothrow_ctor);
+                         fixed_arr_ptr->fill(thrower);
+                       });
+
+  EXPECT_TRUE(
+      test_fill.WithInitialValue(FixedArr(kSmallSize, Thrower(kInitialValue)))
+          .Test());
+  EXPECT_TRUE(
+      test_fill.WithInitialValue(FixedArr(kLargeSize, Thrower(kInitialValue)))
+          .Test());
+}
+
+}  // namespace
+
+}  // namespace absl
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 101ded8557eb..03660f165353 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -645,12 +645,12 @@ class InlinedVector {
   class AllocatorAndTag : private allocator_type {
    public:
     explicit AllocatorAndTag(const allocator_type& a, Tag t = Tag())
-        : allocator_type(a), tag_(t) {
-    }
+        : allocator_type(a), tag_(t) {}
     Tag& tag() { return tag_; }
     const Tag& tag() const { return tag_; }
     allocator_type& allocator() { return *this; }
     const allocator_type& allocator() const { return *this; }
+
    private:
     Tag tag_;
   };
@@ -696,19 +696,13 @@ class InlinedVector {
     return reinterpret_cast<const value_type*>(&rep_.inlined_storage.inlined);
   }
 
-  value_type* allocated_space() {
-    return allocation().buffer();
-  }
-  const value_type* allocated_space() const {
-    return allocation().buffer();
-  }
+  value_type* allocated_space() { return allocation().buffer(); }
+  const value_type* allocated_space() const { return allocation().buffer(); }
 
   const allocator_type& allocator() const {
     return allocator_and_tag_.allocator();
   }
-  allocator_type& allocator() {
-    return allocator_and_tag_.allocator();
-  }
+  allocator_type& allocator() { return allocator_and_tag_.allocator(); }
 
   bool allocated() const { return tag().allocated(); }
 
@@ -1128,8 +1122,7 @@ void InlinedVector<T, N, A>::swap(InlinedVector& other) {
     const size_type b_size = b->size();
     assert(a_size >= b_size);
     // 'a' is larger. Swap the elements up to the smaller array size.
-    std::swap_ranges(a->inlined_space(),
-                     a->inlined_space() + b_size,
+    std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
                      b->inlined_space());
 
     // Move the remaining elements: A[b_size,a_size) -> B[b_size,a_size)
@@ -1273,8 +1266,7 @@ void InlinedVector<T, N, A>::Destroy(value_type* ptr, value_type* ptr_last) {
   // scribbling on a vtable pointer.
 #ifndef NDEBUG
   if (ptr != ptr_last) {
-    memset(reinterpret_cast<void*>(ptr), 0xab,
-           sizeof(*ptr) * (ptr_last - ptr));
+    memset(reinterpret_cast<void*>(ptr), 0xab, sizeof(*ptr) * (ptr_last - ptr));
   }
 #endif
 }
@@ -1302,8 +1294,9 @@ void InlinedVector<T, N, A>::AssignRange(Iter first, Iter last,
   // Optimized to avoid reallocation.
   // Prefer reassignment to copy construction for elements.
   iterator out = begin();
-  for ( ; first != last && out != end(); ++first, ++out)
+  for (; first != last && out != end(); ++first, ++out) {
     *out = *first;
+  }
   erase(out, end());
   std::copy(first, last, std::back_inserter(*this));
 }
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index cd818cff4ffa..c43e156682fd 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -636,6 +636,39 @@ struct default_allocator_is_nothrow : std::true_type {};
 struct default_allocator_is_nothrow : std::false_type {};
 #endif
 
+namespace memory_internal {
+// TODO(b110200014): Implement proper backports
+template <typename ForwardIt>
+void DefaultConstruct(ForwardIt it) {
+  using value_type = typename std::iterator_traits<ForwardIt>::value_type;
+  ::new (static_cast<void*>(std::addressof(*it))) value_type;
+}  // namespace memory_internal
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+template <typename ForwardIt, typename Size>
+void uninitialized_default_construct_n(ForwardIt first, Size size) {
+  for (ForwardIt cur = first; size > 0; static_cast<void>(++cur), --size) {
+    try {
+      absl::memory_internal::DefaultConstruct(cur);
+    } catch (...) {
+      using value_type = typename std::iterator_traits<ForwardIt>::value_type;
+      for (; first != cur; ++first) {
+        first->~value_type();
+      }
+      throw;
+    }
+  }
+}
+#else   // ABSL_HAVE_EXCEPTIONS
+template <typename ForwardIt, typename Size>
+void uninitialized_default_construct_n(ForwardIt first, Size size) {
+  for (; size > 0; static_cast<void>(++first), --size) {
+    absl::memory_internal::DefaultConstruct(first);
+  }
+}
+#endif  // ABSL_HAVE_EXCEPTIONS
+}  // namespace memory_internal
+
 }  // namespace absl
 
 #endif  // ABSL_MEMORY_MEMORY_H_
diff --git a/absl/memory/memory_exception_safety_test.cc b/absl/memory/memory_exception_safety_test.cc
index 55e8f36f2feb..fb8b561d59fb 100644
--- a/absl/memory/memory_exception_safety_test.cc
+++ b/absl/memory/memory_exception_safety_test.cc
@@ -20,11 +20,14 @@
 namespace absl {
 namespace {
 
-using Thrower = ::testing::ThrowingValue<>;
+constexpr int kLength = 50;
+using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
+using ThrowerStorage =
+    absl::aligned_storage_t<sizeof(Thrower), alignof(Thrower)>;
+using ThrowerList = std::array<ThrowerStorage, kLength>;
 
 TEST(MakeUnique, CheckForLeaks) {
   constexpr int kValue = 321;
-  constexpr size_t kLength = 10;
   auto tester = testing::MakeExceptionSafetyTester()
                     .WithInitialValue(Thrower(kValue))
                     // Ensures make_unique does not modify the input. The real
@@ -45,5 +48,16 @@ TEST(MakeUnique, CheckForLeaks) {
   }));
 }
 
+TEST(MemoryInternal, UninitDefaultConstructNNonTrivial) {
+  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
+                  .WithInitialValue(ThrowerList{})
+                  .WithOperation([&](ThrowerList* list_ptr) {
+                    absl::memory_internal::uninitialized_default_construct_n(
+                        list_ptr->data(), kLength);
+                  })
+                  .WithInvariants([&](...) { return true; })
+                  .Test());
+}
+
 }  // namespace
 }  // namespace absl
diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc
index dee9b486a30d..8ff1945debe5 100644
--- a/absl/memory/memory_test.cc
+++ b/absl/memory/memory_test.cc
@@ -611,4 +611,47 @@ TEST(AllocatorNoThrowTest, CustomAllocator) {
   EXPECT_FALSE(absl::allocator_is_nothrow<UnspecifiedAllocator>::value);
 }
 
+TEST(MemoryInternal, UninitDefaultConstructNTrivial) {
+  constexpr int kInitialValue = 123;
+  constexpr int kExpectedValue = kInitialValue;  // Expect no-op behavior
+  constexpr int len = 5;
+
+  struct TestObj {
+    int val;
+  };
+  static_assert(absl::is_trivially_default_constructible<TestObj>::value, "");
+  static_assert(absl::is_trivially_destructible<TestObj>::value, "");
+
+  TestObj objs[len];
+  for (auto& obj : objs) {
+    obj.val = kInitialValue;
+  }
+
+  absl::memory_internal::uninitialized_default_construct_n(objs, len);
+  for (auto& obj : objs) {
+    EXPECT_EQ(obj.val, kExpectedValue);
+  }
+}
+
+TEST(MemoryInternal, UninitDefaultConstructNNonTrivial) {
+  constexpr int kInitialValue = 123;
+  constexpr int kExpectedValue = 0;  // Expect value-construction behavior
+  constexpr int len = 5;
+
+  struct TestObj {
+    int val{kExpectedValue};
+  };
+  static_assert(absl::is_trivially_destructible<TestObj>::value, "");
+
+  TestObj objs[len];
+  for (auto& obj : objs) {
+    obj.val = kInitialValue;
+  }
+
+  absl::memory_internal::uninitialized_default_construct_n(objs, len);
+  for (auto& obj : objs) {
+    EXPECT_EQ(obj.val, kExpectedValue);
+  }
+}
+
 }  // namespace
diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc
index 3688e5efef45..cd79534f3bfd 100644
--- a/absl/numeric/int128.cc
+++ b/absl/numeric/int128.cc
@@ -223,3 +223,29 @@ std::ostream& operator<<(std::ostream& os, uint128 v) {
 }
 
 }  // namespace absl
+
+namespace std {
+constexpr bool numeric_limits<absl::uint128>::is_specialized;
+constexpr bool numeric_limits<absl::uint128>::is_signed;
+constexpr bool numeric_limits<absl::uint128>::is_integer;
+constexpr bool numeric_limits<absl::uint128>::is_exact;
+constexpr bool numeric_limits<absl::uint128>::has_infinity;
+constexpr bool numeric_limits<absl::uint128>::has_quiet_NaN;
+constexpr bool numeric_limits<absl::uint128>::has_signaling_NaN;
+constexpr float_denorm_style numeric_limits<absl::uint128>::has_denorm;
+constexpr bool numeric_limits<absl::uint128>::has_denorm_loss;
+constexpr float_round_style numeric_limits<absl::uint128>::round_style;
+constexpr bool numeric_limits<absl::uint128>::is_iec559;
+constexpr bool numeric_limits<absl::uint128>::is_bounded;
+constexpr bool numeric_limits<absl::uint128>::is_modulo;
+constexpr int numeric_limits<absl::uint128>::digits;
+constexpr int numeric_limits<absl::uint128>::digits10;
+constexpr int numeric_limits<absl::uint128>::max_digits10;
+constexpr int numeric_limits<absl::uint128>::radix;
+constexpr int numeric_limits<absl::uint128>::min_exponent;
+constexpr int numeric_limits<absl::uint128>::min_exponent10;
+constexpr int numeric_limits<absl::uint128>::max_exponent;
+constexpr int numeric_limits<absl::uint128>::max_exponent10;
+constexpr bool numeric_limits<absl::uint128>::traps;
+constexpr bool numeric_limits<absl::uint128>::tinyness_before;
+}  // namespace std
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index bc7dbb47ae81..e4f39c305152 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -219,21 +219,69 @@ std::ostream& operator<<(std::ostream& os, uint128 v);
 
 // TODO(strel) add operator>>(std::istream&, uint128)
 
+constexpr uint128 Uint128Max() {
+  return uint128(std::numeric_limits<uint64_t>::max(),
+                 std::numeric_limits<uint64_t>::max());
+}
+
+}  // namespace absl
+
+// Specialized numeric_limits for uint128.
+namespace std {
+template <>
+class numeric_limits<absl::uint128> {
+ public:
+  static constexpr bool is_specialized = true;
+  static constexpr bool is_signed = false;
+  static constexpr bool is_integer = true;
+  static constexpr bool is_exact = true;
+  static constexpr bool has_infinity = false;
+  static constexpr bool has_quiet_NaN = false;
+  static constexpr bool has_signaling_NaN = false;
+  static constexpr float_denorm_style has_denorm = denorm_absent;
+  static constexpr bool has_denorm_loss = false;
+  static constexpr float_round_style round_style = round_toward_zero;
+  static constexpr bool is_iec559 = false;
+  static constexpr bool is_bounded = true;
+  static constexpr bool is_modulo = true;
+  static constexpr int digits = 128;
+  static constexpr int digits10 = 38;
+  static constexpr int max_digits10 = 0;
+  static constexpr int radix = 2;
+  static constexpr int min_exponent = 0;
+  static constexpr int min_exponent10 = 0;
+  static constexpr int max_exponent = 0;
+  static constexpr int max_exponent10 = 0;
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+  static constexpr bool traps = numeric_limits<unsigned __int128>::traps;
+#else   // ABSL_HAVE_INTRINSIC_INT128
+  static constexpr bool traps = numeric_limits<uint64_t>::traps;
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+  static constexpr bool tinyness_before = false;
+
+  static constexpr absl::uint128 min() { return 0; }
+  static constexpr absl::uint128 lowest() { return 0; }
+  static constexpr absl::uint128 max() { return absl::Uint128Max(); }
+  static constexpr absl::uint128 epsilon() { return 0; }
+  static constexpr absl::uint128 round_error() { return 0; }
+  static constexpr absl::uint128 infinity() { return 0; }
+  static constexpr absl::uint128 quiet_NaN() { return 0; }
+  static constexpr absl::uint128 signaling_NaN() { return 0; }
+  static constexpr absl::uint128 denorm_min() { return 0; }
+};
+}  // namespace std
+
 // TODO(absl-team): Implement signed 128-bit type
 
 // --------------------------------------------------------------------------
 //                      Implementation details follow
 // --------------------------------------------------------------------------
+namespace absl {
 
 constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
   return uint128(high, low);
 }
 
-constexpr uint128 Uint128Max() {
-  return uint128(std::numeric_limits<uint64_t>::max(),
-                 std::numeric_limits<uint64_t>::max());
-}
-
 // Assignment from integer types.
 
 inline uint128& uint128::operator=(int v) { return *this = uint128(v); }
diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc
index 79bcca907ae9..1eb3e0ec8961 100644
--- a/absl/numeric/int128_test.cc
+++ b/absl/numeric/int128_test.cc
@@ -428,4 +428,15 @@ TEST(Uint128, ConstexprTest) {
   EXPECT_EQ(minus_two, absl::MakeUint128(-1, -2));
 }
 
+TEST(Uint128, NumericLimitsTest) {
+  static_assert(std::numeric_limits<absl::uint128>::is_specialized, "");
+  static_assert(!std::numeric_limits<absl::uint128>::is_signed, "");
+  static_assert(std::numeric_limits<absl::uint128>::is_integer, "");
+  EXPECT_EQ(static_cast<int>(128 * std::log10(2)),
+            std::numeric_limits<absl::uint128>::digits10);
+  EXPECT_EQ(0, std::numeric_limits<absl::uint128>::min());
+  EXPECT_EQ(0, std::numeric_limits<absl::uint128>::lowest());
+  EXPECT_EQ(absl::Uint128Max(), std::numeric_limits<absl::uint128>::max());
+}
+
 }  // namespace
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 3e50d24a322a..17831c208230 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -486,6 +486,9 @@ cc_test(
     srcs = [
         "charconv_benchmark.cc",
     ],
+    tags = [
+        "benchmark",
+    ],
     deps = [
         ":strings",
         "//absl/base",
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index a1b10f3addcf..9cf0833f4902 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -228,14 +228,31 @@ struct IsInitializerList
 // compiled in C++11 will get an error due to ambiguous conversion paths (in
 // C++11 std::vector<T>::operator= is overloaded to take either a std::vector<T>
 // or an std::initializer_list<T>).
+
+template <typename C, bool has_value_type, bool has_mapped_type>
+struct SplitterIsConvertibleToImpl : std::false_type {};
+
+template <typename C>
+struct SplitterIsConvertibleToImpl<C, true, false>
+    : std::is_constructible<typename C::value_type, absl::string_view> {};
+
+template <typename C>
+struct SplitterIsConvertibleToImpl<C, true, true>
+    : absl::conjunction<
+          std::is_constructible<typename C::key_type, absl::string_view>,
+          std::is_constructible<typename C::mapped_type, absl::string_view>> {};
+
 template <typename C>
 struct SplitterIsConvertibleTo
-    : std::enable_if<
+    : SplitterIsConvertibleToImpl<
+          C,
 #ifdef _GLIBCXX_DEBUG
           !IsStrictlyBaseOfAndConvertibleToSTLContainer<C>::value &&
 #endif  // _GLIBCXX_DEBUG
-          !IsInitializerList<C>::value && HasValueType<C>::value &&
-          HasConstIterator<C>::value> {
+              !IsInitializerList<
+                  typename std::remove_reference<C>::type>::value &&
+              HasValueType<C>::value && HasConstIterator<C>::value,
+          HasMappedType<C>::value> {
 };
 
 // This class implements the range that is returned by absl::StrSplit(). This
@@ -281,7 +298,8 @@ class Splitter {
   // An implicit conversion operator that is restricted to only those containers
   // that the splitter is convertible to.
   template <typename Container,
-            typename OnlyIf = typename SplitterIsConvertibleTo<Container>::type>
+            typename = typename std::enable_if<
+                SplitterIsConvertibleTo<Container>::value>::type>
   operator Container() const {  // NOLINT(runtime/explicit)
     return ConvertToContainer<Container, typename Container::value_type,
                               HasMappedType<Container>::value>()(*this);
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index 98e0fef4906b..a3fb89c79581 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -344,13 +344,13 @@ ABSL_MUST_USE_RESULT str_format_internal::Streamable StreamFormat(
 // PrintF()
 //
 // Writes to stdout given a format std::string and zero or more arguments. This
-// function is functionally equivalent to `std::print()` (and type-safe); prefer
-// `absl::PrintF()` over `std::printf()`.
+// function is functionally equivalent to `std::printf()` (and type-safe);
+// prefer `absl::PrintF()` over `std::printf()`.
 //
 // Example:
 //
 //   std::string_view s = "Ulaanbaatar";
-//   absl::PrintF("The capital of Mongolia is: %s \n", s);
+//   absl::PrintF("The capital of Mongolia is %s", s);
 //
 //   Outputs: "The capital of Mongolia is Ulaanbaatar"
 //
@@ -364,13 +364,13 @@ int PrintF(const FormatSpec<Args...>& format, const Args&... args) {
 // FPrintF()
 //
 // Writes to a file given a format std::string and zero or more arguments. This
-// function is functionally equivalent to `std::fprint()` (and type-safe);
+// function is functionally equivalent to `std::fprintf()` (and type-safe);
 // prefer `absl::FPrintF()` over `std::fprintf()`.
 //
 // Example:
 //
 //   std::string_view s = "Ulaanbaatar";
-//   absl::FPrintF("The capital of Mongolia is: %s \n", s);
+//   absl::FPrintF("The capital of Mongolia is %s", s);
 //
 //   Outputs: "The capital of Mongolia is Ulaanbaatar"
 //
@@ -385,15 +385,17 @@ int FPrintF(std::FILE* output, const FormatSpec<Args...>& format,
 // SNPrintF()
 //
 // Writes to a sized buffer given a format std::string and zero or more arguments.
-// This function is functionally equivalent to `std::snprint()` (and type-safe);
-// prefer `absl::SNPrintF()` over `std::snprintf()`.
+// This function is functionally equivalent to `std::snprintf()` (and
+// type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.
 //
 // Example:
 //
 //   std::string_view s = "Ulaanbaatar";
-//   absl::FPrintF("The capital of Mongolia is: %s \n", s);
+//   char output[128];
+//   absl::SNPrintF(output, sizeof(output),
+//                  "The capital of Mongolia is %s", s);
 //
-//   Outputs: "The capital of Mongolia is Ulaanbaatar"
+//   Post-condition: output == "The capital of Mongolia is Ulaanbaatar"
 //
 template <typename... Args>
 int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format,
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc
index c172a7629933..c6898863dc0e 100644
--- a/absl/strings/str_split_test.cc
+++ b/absl/strings/str_split_test.cc
@@ -37,6 +37,34 @@ using ::testing::ElementsAre;
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
 
+TEST(Split, TraitsTest) {
+  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<int>::value,
+                "");
+  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<std::string>::value,
+                "");
+  static_assert(absl::strings_internal::SplitterIsConvertibleTo<
+                    std::vector<std::string>>::value,
+                "");
+  static_assert(
+      !absl::strings_internal::SplitterIsConvertibleTo<std::vector<int>>::value,
+      "");
+  static_assert(absl::strings_internal::SplitterIsConvertibleTo<
+                    std::vector<absl::string_view>>::value,
+                "");
+  static_assert(absl::strings_internal::SplitterIsConvertibleTo<
+                    std::map<std::string, std::string>>::value,
+                "");
+  static_assert(absl::strings_internal::SplitterIsConvertibleTo<
+                    std::map<absl::string_view, absl::string_view>>::value,
+                "");
+  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<
+                    std::map<int, std::string>>::value,
+                "");
+  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<
+                    std::map<std::string, int>>::value,
+                "");
+}
+
 // This tests the overall split API, which is made up of the absl::StrSplit()
 // function and the Delimiter objects in the absl:: namespace.
 // This TEST macro is outside of any namespace to require full specification of
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index 372874e1104e..8d302e01223b 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -225,6 +225,7 @@ cc_test(
         "//absl:windows": [],
         "//conditions:default": ["-pthread"],
     }),
+    tags = ["no_test_ios_x86_64"],
     deps = [
         ":synchronization",
         "//absl/base",
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index c50ec425aea6..096c119e638c 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -42,7 +42,10 @@ cc_library(
     name = "bad_any_cast",
     hdrs = ["bad_any_cast.h"],
     copts = ABSL_DEFAULT_COPTS,
-    deps = [":bad_any_cast_impl"],
+    deps = [
+        ":bad_any_cast_impl",
+        "//absl/base:config",
+    ],
 )
 
 cc_library(
@@ -253,6 +256,7 @@ cc_test(
         "variant_benchmark.cc",
     ],
     copts = ABSL_TEST_COPTS,
+    tags = ["benchmark"],
     deps = [
         ":variant",
         "//absl/utility",
diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc
index c9b73300690f..2e2fd29a3378 100644
--- a/absl/types/bad_any_cast.cc
+++ b/absl/types/bad_any_cast.cc
@@ -14,6 +14,8 @@
 
 #include "absl/types/bad_any_cast.h"
 
+#ifndef ABSL_HAVE_STD_ANY
+
 #include <cstdlib>
 
 #include "absl/base/config.h"
@@ -38,3 +40,5 @@ void ThrowBadAnyCast() {
 
 }  // namespace any_internal
 }  // namespace absl
+
+#endif  // ABSL_HAVE_STD_ANY
diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h
index 3b963077d417..603901324afc 100644
--- a/absl/types/bad_any_cast.h
+++ b/absl/types/bad_any_cast.h
@@ -23,6 +23,18 @@
 
 #include <typeinfo>
 
+#include "absl/base/config.h"
+
+#ifdef ABSL_HAVE_STD_ANY
+
+#include <any>
+
+namespace absl {
+using std::bad_any_cast;
+}  // namespace absl
+
+#else  // ABSL_HAVE_STD_ANY
+
 namespace absl {
 
 // -----------------------------------------------------------------------------
@@ -54,4 +66,6 @@ namespace any_internal {
 }  // namespace any_internal
 }  // namespace absl
 
+#endif  // ABSL_HAVE_STD_ANY
+
 #endif  // ABSL_TYPES_BAD_ANY_CAST_H_
diff --git a/absl/types/bad_optional_access.cc b/absl/types/bad_optional_access.cc
index 6bc67df77c9a..558707760e9d 100644
--- a/absl/types/bad_optional_access.cc
+++ b/absl/types/bad_optional_access.cc
@@ -14,6 +14,8 @@
 
 #include "absl/types/bad_optional_access.h"
 
+#ifndef ABSL_HAVE_STD_OPTIONAL
+
 #include <cstdlib>
 
 #include "absl/base/config.h"
@@ -40,3 +42,5 @@ void throw_bad_optional_access() {
 
 }  // namespace optional_internal
 }  // namespace absl
+
+#endif  // ABSL_HAVE_STD_OPTIONAL
diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h
index e9aa8b83eda1..c6c27460a76d 100644
--- a/absl/types/bad_optional_access.h
+++ b/absl/types/bad_optional_access.h
@@ -23,6 +23,18 @@
 
 #include <stdexcept>
 
+#include "absl/base/config.h"
+
+#ifdef ABSL_HAVE_STD_OPTIONAL
+
+#include <optional>
+
+namespace absl {
+using std::bad_optional_access;
+}  // namespace absl
+
+#else  // ABSL_HAVE_STD_OPTIONAL
+
 namespace absl {
 
 // -----------------------------------------------------------------------------
@@ -57,4 +69,6 @@ namespace optional_internal {
 }  // namespace optional_internal
 }  // namespace absl
 
+#endif  // ABSL_HAVE_STD_OPTIONAL
+
 #endif  // ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc
index 817fd78909a5..d27d77561791 100644
--- a/absl/types/bad_variant_access.cc
+++ b/absl/types/bad_variant_access.cc
@@ -14,6 +14,8 @@
 
 #include "absl/types/bad_variant_access.h"
 
+#ifndef ABSL_HAVE_STD_VARIANT
+
 #include <cstdlib>
 #include <stdexcept>
 
@@ -56,3 +58,5 @@ void Rethrow() {
 
 }  // namespace variant_internal
 }  // namespace absl
+
+#endif  // ABSL_HAVE_STD_VARIANT
diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h
index 67abe7136b7b..e7355a5a74c8 100644
--- a/absl/types/bad_variant_access.h
+++ b/absl/types/bad_variant_access.h
@@ -23,6 +23,18 @@
 
 #include <stdexcept>
 
+#include "absl/base/config.h"
+
+#ifdef ABSL_HAVE_STD_VARIANT
+
+#include <variant>
+
+namespace absl {
+using std::bad_variant_access;
+}  // namespace absl
+
+#else  // ABSL_HAVE_STD_VARIANT
+
 namespace absl {
 
 // -----------------------------------------------------------------------------
@@ -61,4 +73,6 @@ namespace variant_internal {
 }  // namespace variant_internal
 }  // namespace absl
 
+#endif  // ABSL_HAVE_STD_VARIANT
+
 #endif  // ABSL_TYPES_BAD_VARIANT_ACCESS_H_