summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 ebe32445..acddec48 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 d117a4fe..35414a25 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 8d30b932..fbb2797b 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 119d5c88..07df3675 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 f56ce92d..d580b489 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 06bc8009..295f0108 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 00000000..c123c2a1
--- /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 101ded85..03660f16 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 cd818cff..c43e1566 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 55e8f36f..fb8b561d 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 dee9b486..8ff1945d 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 3688e5ef..cd79534f 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 bc7dbb47..e4f39c30 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 79bcca90..1eb3e0ec 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 3e50d24a..17831c20 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 a1b10f3a..9cf0833f 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 98e0fef4..a3fb89c7 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 c172a762..c6898863 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 372874e1..8d302e01 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 c50ec425..096c119e 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 c9b73300..2e2fd29a 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 3b963077..60390132 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 6bc67df7..55870776 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 e9aa8b83..c6c27460 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 817fd789..d27d7756 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 67abe713..e7355a5a 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_