Export of internal Abseil changes.
-- 8becce38c862a044db194a9aea1b505796a46d6f by Abseil Team <absl-team@google.com>: Updates the FixedArray's constructors to be exception safe by preventing double deletions. Also adds exception safety tests for FixedArray to document/enforce the expected behavior. PiperOrigin-RevId: 201964431 -- 794188b401a602b4be97190fb8738066fe1f9ca5 by Derek Mauro <dmauro@google.com>: Fixes for str_format.h documentation. PiperOrigin-RevId: 201951760 -- beae3bdd6eee2cf61101102fddc35ada188f330b by Alex Strelnikov <strel@google.com>: Add numeric_limits specialization for uint128. Turns out numeric_limits is a case where the consensus is that it is okay to specialize for a user defined type. PiperOrigin-RevId: 201944736 -- b2b3444a52b36878ade1ae8801e69932b05fc4f9 by Shaindel Schwartz <shaindel@google.com>: Internal change. PiperOrigin-RevId: 201718662 -- aa924c459922f39caabfc193998c58d0f4981ac0 by Abseil Team <absl-team@google.com>: Typo fix. PiperOrigin-RevId: 201692176 -- bbfcaa7b1af331d9b97c92470608240c5c864fbc by Xiaoyi Zhang <zhangxy@google.com>: Use ABSL_HAVE_ANY/OPTIONAL/VARIANT to conditionally compile out the definition of absl::bad_any_cast, absl::bad_optional_access, absl::bad_variant_access. This would fix the issues where users #include those header directly in C++17 modes. PiperOrigin-RevId: 201683792 GitOrigin-RevId: 8becce38c862a044db194a9aea1b505796a46d6f Change-Id: I60a7ad043136a439d82c374d225a1804016b0509
This commit is contained in:
		
							parent
							
								
									4491d606df
								
							
						
					
					
						commit
						87a4c07856
					
				
					 20 changed files with 422 additions and 48 deletions
				
			
		| 
						 | 
				
			
			@ -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.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,6 +62,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"],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()),
 | 
			
		||||
      : 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)) {}
 | 
			
		||||
 | 
			
		||||
    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_));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										117
									
								
								absl/container/fixed_array_exception_safety_test.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								absl/container/fixed_array_exception_safety_test.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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_
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue