diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index 1d55240..e52d456 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake
@@ -65,6 +65,8 @@ "base/policy_checks.h" "base/port.h" "base/thread_annotations.h" + "base/throw_delegate.h" + "base/throw_delegate.cc" "cleanup/cleanup.h" "cleanup/internal/cleanup.h" "container/btree_map.h"
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 1d27796..72f9e24 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel
@@ -377,13 +377,16 @@ cc_library( name = "throw_delegate", - srcs = ["internal/throw_delegate.cc"], - hdrs = ["internal/throw_delegate.h"], + srcs = [ + "internal/throw_delegate.cc", + "throw_delegate.cc", + ], + hdrs = [ + "internal/throw_delegate.h", + "throw_delegate.h", + ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], deps = [ ":config", ":raw_logging_internal",
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 84decab..f39a9ae 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt
@@ -290,14 +290,15 @@ PUBLIC ) -# Internal-only target, do not depend on directly. absl_cc_library( NAME throw_delegate HDRS "internal/throw_delegate.h" + "throw_delegate.h" SRCS "internal/throw_delegate.cc" + "throw_delegate.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS
diff --git a/absl/base/call_once.h b/absl/base/call_once.h index 7bfd916..1abac86 100644 --- a/absl/base/call_once.h +++ b/absl/base/call_once.h
@@ -160,6 +160,7 @@ old_control != kOnceRunning && old_control != kOnceWaiter && old_control != kOnceDone) { + // Memory corruption may cause this error. ABSL_RAW_LOG(FATAL, "Unexpected value for control word: 0x%lx", static_cast<unsigned long>(old_control)); // NOLINT }
diff --git a/absl/base/casts.h b/absl/base/casts.h index 38243d8..928f409 100644 --- a/absl/base/casts.h +++ b/absl/base/casts.h
@@ -211,7 +211,7 @@ // Assert only if RTTI is enabled and in debug mode or hardened asserts are // enabled. #ifdef ABSL_INTERNAL_HAS_RTTI -#if !defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) +#if !defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1) // Suppress erroneous nonnull comparison warning on older GCC. #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push
diff --git a/absl/base/casts_test.cc b/absl/base/casts_test.cc index 772225e..dda3ae6 100644 --- a/absl/base/casts_test.cc +++ b/absl/base/casts_test.cc
@@ -92,8 +92,7 @@ // Tests a bad downcast. We have to disguise the badness just enough // that the compiler doesn't warn about it at compile time. BaseForDownCast* base2 = new BaseForDownCast(); -#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || \ - ABSL_OPTION_HARDENED == 2)) +#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1)) EXPECT_DEATH(static_cast<void>(absl::down_cast<DerivedForDownCast*>(base2)), ".*down cast from .*BaseForDownCast.* to " ".*DerivedForDownCast.* failed.*"); @@ -126,8 +125,7 @@ // Tests a bad downcast. We have to disguise the badness just enough // that the compiler doesn't warn about it at compile time. BaseForDownCast& base2 = *new BaseForDownCast(); -#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || \ - ABSL_OPTION_HARDENED == 2)) +#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1)) EXPECT_DEATH(static_cast<void>(absl::down_cast<DerivedForDownCast&>(base2)), ".*down cast from .*BaseForDownCast.* to " ".*DerivedForDownCast.* failed.*"); @@ -140,8 +138,7 @@ BaseForDownCast& base = derived; (void)base; -#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || \ - ABSL_OPTION_HARDENED == 2)) +#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1)) EXPECT_DEATH(static_cast<void>(absl::down_cast<Derived2ForDownCast&>(base)), ".*down cast from .*DerivedForDownCast.* to " ".*Derived2ForDownCast.* failed.*");
diff --git a/absl/base/optimization.h b/absl/base/optimization.h index 04678c4..b561128 100644 --- a/absl/base/optimization.h +++ b/absl/base/optimization.h
@@ -222,7 +222,7 @@ // `ABSL_UNREACHABLE()` is an unreachable statement. A program which reaches // one has undefined behavior, and the compiler may optimize accordingly. -#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG) +#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG) // Abort in hardened mode to avoid dangerous undefined behavior. #define ABSL_UNREACHABLE() \ do { \
diff --git a/absl/base/throw_delegate.cc b/absl/base/throw_delegate.cc new file mode 100644 index 0000000..b960edd --- /dev/null +++ b/absl/base/throw_delegate.cc
@@ -0,0 +1,205 @@ +// 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 +// +// https://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 "absl/base/throw_delegate.h" + +#include <cstdlib> +#include <functional> +#include <new> +#include <stdexcept> + +#include "absl/base/config.h" +#include "absl/base/internal/raw_logging.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +void ThrowStdLogicError(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::logic_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdLogicError(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::logic_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} +void ThrowStdInvalidArgument(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::invalid_argument(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdInvalidArgument(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::invalid_argument(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} + +void ThrowStdDomainError(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::domain_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdDomainError(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::domain_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} + +void ThrowStdLengthError(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::length_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdLengthError(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::length_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} + +void ThrowStdOutOfRange(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::out_of_range(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdOutOfRange(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::out_of_range(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} + +void ThrowStdRuntimeError(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::runtime_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdRuntimeError(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::runtime_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} + +void ThrowStdRangeError(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::range_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdRangeError(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::range_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} + +void ThrowStdOverflowError(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::overflow_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdOverflowError(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::overflow_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} + +void ThrowStdUnderflowError(const std::string& what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::underflow_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); + std::abort(); +#endif +} +void ThrowStdUnderflowError(const char* what_arg) { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::underflow_error(what_arg); +#else + ABSL_RAW_LOG(FATAL, "%s", what_arg); + std::abort(); +#endif +} + +void ThrowStdBadFunctionCall() { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::bad_function_call(); +#else + std::abort(); +#endif +} + +void ThrowStdBadAlloc() { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::bad_alloc(); +#else + std::abort(); +#endif +} + +void ThrowStdBadArrayNewLength() { +#ifdef ABSL_HAVE_EXCEPTIONS + throw std::bad_array_new_length(); +#else + std::abort(); +#endif +} + +ABSL_NAMESPACE_END +} // namespace absl
diff --git a/absl/base/throw_delegate.h b/absl/base/throw_delegate.h new file mode 100644 index 0000000..e89712a --- /dev/null +++ b/absl/base/throw_delegate.h
@@ -0,0 +1,65 @@ +// 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 +// +// https://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. + +#ifndef ABSL_BASE_THROW_DELEGATE_H_ +#define ABSL_BASE_THROW_DELEGATE_H_ + +#include <string> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// Helper functions that allow throwing exceptions consistently from anywhere. +// The main use case is for header-based libraries (eg templates), as they will +// be built by many different targets with their own compiler options. +// In particular, this will allow a safe way to throw exceptions even if the +// caller is compiled with -fno-exceptions. This is intended for implementing +// things like map<>::at(), which the standard documents as throwing an +// exception on error. +// +// Using other techniques like #if tricks could lead to ODR violations. +// +// You shouldn't use it unless you're writing code that you know will be built +// both with and without exceptions and you need to conform to an interface +// that uses exceptions. + +[[noreturn]] void ThrowStdLogicError(const std::string& what_arg); +[[noreturn]] void ThrowStdLogicError(const char* what_arg); +[[noreturn]] void ThrowStdInvalidArgument(const std::string& what_arg); +[[noreturn]] void ThrowStdInvalidArgument(const char* what_arg); +[[noreturn]] void ThrowStdDomainError(const std::string& what_arg); +[[noreturn]] void ThrowStdDomainError(const char* what_arg); +[[noreturn]] void ThrowStdLengthError(const std::string& what_arg); +[[noreturn]] void ThrowStdLengthError(const char* what_arg); +[[noreturn]] void ThrowStdOutOfRange(const std::string& what_arg); +[[noreturn]] void ThrowStdOutOfRange(const char* what_arg); +[[noreturn]] void ThrowStdRuntimeError(const std::string& what_arg); +[[noreturn]] void ThrowStdRuntimeError(const char* what_arg); +[[noreturn]] void ThrowStdRangeError(const std::string& what_arg); +[[noreturn]] void ThrowStdRangeError(const char* what_arg); +[[noreturn]] void ThrowStdOverflowError(const std::string& what_arg); +[[noreturn]] void ThrowStdOverflowError(const char* what_arg); +[[noreturn]] void ThrowStdUnderflowError(const std::string& what_arg); +[[noreturn]] void ThrowStdUnderflowError(const char* what_arg); + +[[noreturn]] void ThrowStdBadFunctionCall(); +[[noreturn]] void ThrowStdBadAlloc(); +[[noreturn]] void ThrowStdBadArrayNewLength(); + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_BASE_THROW_DELEGATE_H_
diff --git a/absl/base/throw_delegate_test.cc b/absl/base/throw_delegate_test.cc index e74362b..3cbc171 100644 --- a/absl/base/throw_delegate_test.cc +++ b/absl/base/throw_delegate_test.cc
@@ -12,28 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "absl/base/internal/throw_delegate.h" +#include "absl/base/throw_delegate.h" #include <functional> #include <new> #include <stdexcept> -#include "absl/base/config.h" #include "gtest/gtest.h" +#include "absl/base/config.h" namespace { -using absl::base_internal::ThrowStdLogicError; -using absl::base_internal::ThrowStdInvalidArgument; -using absl::base_internal::ThrowStdDomainError; -using absl::base_internal::ThrowStdLengthError; -using absl::base_internal::ThrowStdOutOfRange; -using absl::base_internal::ThrowStdRuntimeError; -using absl::base_internal::ThrowStdRangeError; -using absl::base_internal::ThrowStdOverflowError; -using absl::base_internal::ThrowStdUnderflowError; -using absl::base_internal::ThrowStdBadFunctionCall; -using absl::base_internal::ThrowStdBadAlloc; +using absl::ThrowStdBadAlloc; +using absl::ThrowStdBadArrayNewLength; +using absl::ThrowStdBadFunctionCall; +using absl::ThrowStdDomainError; +using absl::ThrowStdInvalidArgument; +using absl::ThrowStdLengthError; +using absl::ThrowStdLogicError; +using absl::ThrowStdOutOfRange; +using absl::ThrowStdOverflowError; +using absl::ThrowStdRangeError; +using absl::ThrowStdRuntimeError; +using absl::ThrowStdUnderflowError; constexpr const char* what_arg = "The quick brown fox jumps over the lazy dog"; @@ -151,25 +152,15 @@ } TEST(ThrowDelegate, ThrowStdBadFunctionCallNoWhat) { -#ifdef ABSL_HAVE_EXCEPTIONS - try { - ThrowStdBadFunctionCall(); - FAIL() << "Didn't throw"; - } catch (const std::bad_function_call&) { - } -#ifdef _LIBCPP_VERSION - catch (const std::exception&) { - // https://reviews.llvm.org/D92397 causes issues with the vtable for - // std::bad_function_call when using libc++ as a shared library. - } -#endif -#else - EXPECT_DEATH_IF_SUPPORTED(ThrowStdBadFunctionCall(), ""); -#endif + ExpectThrowNoWhat<std::bad_function_call>(ThrowStdBadFunctionCall); } TEST(ThrowDelegate, ThrowStdBadAllocNoWhat) { ExpectThrowNoWhat<std::bad_alloc>(ThrowStdBadAlloc); } +TEST(ThrowDelegate, ThrowStdBadArrayNewLength) { + ExpectThrowNoWhat<std::bad_array_new_length>(ThrowStdBadArrayNewLength); +} + } // namespace
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index d47b0e4..c51a19f 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h
@@ -45,10 +45,10 @@ #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/iterator_traits.h" -#include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/optimization.h" #include "absl/base/port.h" +#include "absl/base/throw_delegate.h" #include "absl/container/internal/compressed_tuple.h" #include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/memory/memory.h" @@ -240,7 +240,7 @@ // array, or throws std::out_of_range reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND { if (ABSL_PREDICT_FALSE(i >= size())) { - base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check"); + ThrowStdOutOfRange("FixedArray::at failed bounds check"); } return data()[i]; } @@ -249,7 +249,7 @@ // of the fixed array. const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND { if (ABSL_PREDICT_FALSE(i >= size())) { - base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check"); + ThrowStdOutOfRange("FixedArray::at failed bounds check"); } return data()[i]; }
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index 7ce3353..1677f6a 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h
@@ -181,6 +181,11 @@ // // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; // absl::flat_hash_map<int, std::string> map7(v.begin(), v.end()); + // + // * from_range constructor (C++23) + // + // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; + // absl::flat_hash_map<int, std::string> map8(std::from_range, v); flat_hash_map() {} using Base::Base;
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index 73f28c7..a4efb7d 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc
@@ -35,6 +35,10 @@ #include "absl/meta/type_traits.h" #include "absl/types/any.h" +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#include <ranges> // NOLINT(build/c++20) +#endif + namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { @@ -445,6 +449,36 @@ EXPECT_DEATH_IF_SUPPORTED(insert_conflicting_elems(), crash_message); } +#if defined(__cpp_lib_containers_ranges) && \ + __cpp_lib_containers_ranges >= 202202L +TEST(FlatHashMap, FromRange) { + std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}}; + absl::flat_hash_map<int, int> m(std::from_range, v); + EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6))); +} + +TEST(FlatHashMap, FromRangeWithAllocator) { + std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}}; + absl::flat_hash_map<int, int, + absl::container_internal::hash_default_hash<int>, + absl::container_internal::hash_default_eq<int>, + Alloc<std::pair<const int, int>>> + m(std::from_range, v, 0, Alloc<std::pair<const int, int>>()); + EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6))); +} + +TEST(FlatHashMap, FromRangeWithHasherAndAllocator) { + std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}}; + using TestingHash = absl::container_internal::StatefulTestingHash; + absl::flat_hash_map<int, int, TestingHash, + absl::container_internal::hash_default_eq<int>, + Alloc<std::pair<const int, int>>> + m(std::from_range, v, 0, TestingHash{}, + Alloc<std::pair<const int, int>>()); + EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6))); +} +#endif + } // namespace } // namespace container_internal ABSL_NAMESPACE_END
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h index a469fa0..f802057 100644 --- a/absl/container/flat_hash_set.h +++ b/absl/container/flat_hash_set.h
@@ -177,6 +177,11 @@ // // std::vector<std::string> v = {"a", "b"}; // absl::flat_hash_set<std::string> set7(v.begin(), v.end()); + // + // * from_range constructor (C++23) + // + // std::vector<std::string> v = {"a", "b"}; + // absl::flat_hash_set<std::string> set8(std::from_range, v); flat_hash_set() {} using Base::Base;
diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc index 9b6a6d1..f776f38 100644 --- a/absl/container/flat_hash_set_test.cc +++ b/absl/container/flat_hash_set_test.cc
@@ -38,6 +38,10 @@ #include "absl/memory/memory.h" #include "absl/strings/string_view.h" +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#include <ranges> // NOLINT(build/c++20) +#endif + namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { @@ -395,6 +399,34 @@ false); } +#if defined(__cpp_lib_containers_ranges) && \ + __cpp_lib_containers_ranges >= 202202L +TEST(FlatHashSet, FromRange) { + std::vector<int> v = {1, 2, 3, 4, 5}; + absl::flat_hash_set<int> s(std::from_range, v); + EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); +} + +TEST(FlatHashSet, FromRangeWithAllocator) { + std::vector<int> v = {1, 2, 3, 4, 5}; + absl::flat_hash_set<int, absl::container_internal::hash_default_hash<int>, + absl::container_internal::hash_default_eq<int>, + Alloc<int>> + s(std::from_range, v, 0, Alloc<int>()); + EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); +} + +TEST(FlatHashSet, FromRangeWithHasherAndAllocator) { + std::vector<int> v = {1, 2, 3, 4, 5}; + using TestingHash = absl::container_internal::StatefulTestingHash; + absl::flat_hash_set<int, TestingHash, + absl::container_internal::hash_default_eq<int>, + Alloc<int>> + s(std::from_range, v, 0, TestingHash{}, Alloc<int>()); + EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); +} +#endif + } // namespace } // namespace container_internal ABSL_NAMESPACE_END
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 6b05d92..a9c2526 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h
@@ -48,10 +48,10 @@ #include "absl/algorithm/algorithm.h" #include "absl/base/attributes.h" #include "absl/base/internal/iterator_traits.h" -#include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/optimization.h" #include "absl/base/port.h" +#include "absl/base/throw_delegate.h" #include "absl/container/internal/inlined_vector.h" #include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/memory/memory.h" @@ -382,8 +382,7 @@ // in both debug and non-debug builds, `std::out_of_range` will be thrown. reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND { if (ABSL_PREDICT_FALSE(i >= size())) { - base_internal::ThrowStdOutOfRange( - "`InlinedVector::at(size_type)` failed bounds check"); + ThrowStdOutOfRange("`InlinedVector::at(size_type)` failed bounds check"); } return data()[i]; } @@ -395,7 +394,7 @@ // in both debug and non-debug builds, `std::out_of_range` will be thrown. const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND { if (ABSL_PREDICT_FALSE(i >= size())) { - base_internal::ThrowStdOutOfRange( + ThrowStdOutOfRange( "`InlinedVector::at(size_type) const` failed bounds check"); } return data()[i];
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h index e1649e3..0ccf9d0 100644 --- a/absl/container/internal/btree_container.h +++ b/absl/container/internal/btree_container.h
@@ -22,7 +22,7 @@ #include <utility> #include "absl/base/attributes.h" -#include "absl/base/internal/throw_delegate.h" +#include "absl/base/throw_delegate.h" #include "absl/container/internal/btree.h" // IWYU pragma: export #include "absl/container/internal/common.h" #include "absl/hash/internal/weakly_mixed_integer.h" @@ -651,16 +651,14 @@ template <typename K = key_type> mapped_type &at(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND { auto it = this->find(key); - if (it == this->end()) - base_internal::ThrowStdOutOfRange("absl::btree_map::at"); + if (it == this->end()) ThrowStdOutOfRange("absl::btree_map::at"); return it->second; } template <typename K = key_type> const mapped_type &at(const key_arg<K> &key) const ABSL_ATTRIBUTE_LIFETIME_BOUND { auto it = this->find(key); - if (it == this->end()) - base_internal::ThrowStdOutOfRange("absl::btree_map::at"); + if (it == this->end()) ThrowStdOutOfRange("absl::btree_map::at"); return it->second; }
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h index 9338f16..20b622b 100644 --- a/absl/container/internal/raw_hash_map.h +++ b/absl/container/internal/raw_hash_map.h
@@ -21,7 +21,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" -#include "absl/base/internal/throw_delegate.h" +#include "absl/base/throw_delegate.h" #include "absl/container/internal/common_policy_traits.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export @@ -290,8 +290,7 @@ MappedReference<P> at(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { auto it = this->find(key); if (it == this->end()) { - base_internal::ThrowStdOutOfRange( - "absl::container_internal::raw_hash_map<>::at"); + ThrowStdOutOfRange("absl::container_internal::raw_hash_map<>::at"); } return Policy::value(&*it); } @@ -301,8 +300,7 @@ ABSL_ATTRIBUTE_LIFETIME_BOUND { auto it = this->find(key); if (it == this->end()) { - base_internal::ThrowStdOutOfRange( - "absl::container_internal::raw_hash_map<>::at"); + ThrowStdOutOfRange("absl::container_internal::raw_hash_map<>::at"); } return Policy::value(&*it); }
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index d307e2d..a123ebd 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h
@@ -221,6 +221,10 @@ #include "absl/numeric/bits.h" #include "absl/utility/utility.h" +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#include <ranges> // NOLINT(build/c++20) +#endif + namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { @@ -2149,6 +2153,28 @@ const allocator_type& alloc) : raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {} +#if defined(__cpp_lib_containers_ranges) && \ + __cpp_lib_containers_ranges >= 202202L + template <typename R> + raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count = 0, + const hasher& hash = hasher(), const key_equal& eq = key_equal(), + const allocator_type& alloc = allocator_type()) + : raw_hash_set(std::begin(rg), std::end(rg), bucket_count, hash, eq, + alloc) {} + + template <typename R> + raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count, + const allocator_type& alloc) + : raw_hash_set(std::from_range, std::forward<R>(rg), bucket_count, + hasher(), key_equal(), alloc) {} + + template <typename R> + raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count, + const hasher& hash, const allocator_type& alloc) + : raw_hash_set(std::from_range, std::forward<R>(rg), bucket_count, hash, + key_equal(), alloc) {} +#endif + template <class InputIter> raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc) : raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {}
diff --git a/absl/container/linked_hash_map.h b/absl/container/linked_hash_map.h index e42a1f7..61720d6 100644 --- a/absl/container/linked_hash_map.h +++ b/absl/container/linked_hash_map.h
@@ -43,8 +43,8 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" -#include "absl/base/internal/throw_delegate.h" #include "absl/base/optimization.h" +#include "absl/base/throw_delegate.h" #include "absl/container/flat_hash_set.h" #include "absl/container/internal/common.h" @@ -377,7 +377,7 @@ mapped_type& at(const key_arg<K>& key) { auto it = find(key); if (ABSL_PREDICT_FALSE(it == end())) { - absl::base_internal::ThrowStdOutOfRange("absl::linked_hash_map::at"); + ThrowStdOutOfRange("absl::linked_hash_map::at"); } return it->second; }
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index 580a044..3ceef32 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h
@@ -177,6 +177,11 @@ // // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; // absl::node_hash_map<int, std::string> map7(v.begin(), v.end()); + // + // * from_range constructor (C++23) + // + // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; + // absl::node_hash_map<int, std::string> map8(std::from_range, v); node_hash_map() {} using Base::Base;
diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc index c67d81f..6e92bbe 100644 --- a/absl/container/node_hash_map_test.cc +++ b/absl/container/node_hash_map_test.cc
@@ -32,6 +32,10 @@ #include "absl/container/internal/unordered_map_members_test.h" #include "absl/container/internal/unordered_map_modifiers_test.h" +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#include <ranges> // NOLINT(build/c++20) +#endif + namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { @@ -342,6 +346,36 @@ t.m[0] = RecursiveType{}; } +#if defined(__cpp_lib_containers_ranges) && \ + __cpp_lib_containers_ranges >= 202202L +TEST(NodeHashMap, FromRange) { + std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}}; + absl::node_hash_map<int, int> m(std::from_range, v); + EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6))); +} + +TEST(NodeHashMap, FromRangeWithAllocator) { + std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}}; + absl::node_hash_map<int, int, + absl::container_internal::hash_default_hash<int>, + absl::container_internal::hash_default_eq<int>, + Alloc<std::pair<const int, int>>> + m(std::from_range, v, 0, Alloc<std::pair<const int, int>>()); + EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6))); +} + +TEST(NodeHashMap, FromRangeWithHasherAndAllocator) { + std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}}; + using TestingHash = absl::container_internal::StatefulTestingHash; + absl::node_hash_map<int, int, TestingHash, + absl::container_internal::hash_default_eq<int>, + Alloc<std::pair<const int, int>>> + m(std::from_range, v, 0, TestingHash{}, + Alloc<std::pair<const int, int>>()); + EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6))); +} +#endif + } // namespace } // namespace container_internal ABSL_NAMESPACE_END
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h index f69c6ab..17aa763 100644 --- a/absl/container/node_hash_set.h +++ b/absl/container/node_hash_set.h
@@ -171,6 +171,11 @@ // // std::vector<std::string> v = {"a", "b"}; // absl::node_hash_set<std::string> set7(v.begin(), v.end()); + // + // * from_range constructor (C++23) + // + // std::vector<std::string> v = {"a", "b"}; + // absl::node_hash_set<std::string> set8(std::from_range, v); node_hash_set() {} using Base::Base;
diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc index e1f5bd9..b29d0ca 100644 --- a/absl/container/node_hash_set_test.cc +++ b/absl/container/node_hash_set_test.cc
@@ -31,6 +31,10 @@ #include "absl/container/internal/unordered_set_modifiers_test.h" #include "absl/memory/memory.h" +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#include <ranges> // NOLINT(build/c++20) +#endif + namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { @@ -182,6 +186,34 @@ } } +#if defined(__cpp_lib_containers_ranges) && \ + __cpp_lib_containers_ranges >= 202202L +TEST(NodeHashSet, FromRange) { + std::vector<int> v = {1, 2, 3, 4, 5}; + absl::node_hash_set<int> s(std::from_range, v); + EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); +} + +TEST(NodeHashSet, FromRangeWithAllocator) { + std::vector<int> v = {1, 2, 3, 4, 5}; + absl::node_hash_set<int, absl::container_internal::hash_default_hash<int>, + absl::container_internal::hash_default_eq<int>, + Alloc<int>> + s(std::from_range, v, 0, Alloc<int>()); + EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); +} + +TEST(NodeHashSet, FromRangeWithHasherAndAllocator) { + std::vector<int> v = {1, 2, 3, 4, 5}; + using TestingHash = absl::container_internal::StatefulTestingHash; + absl::node_hash_set<int, TestingHash, + absl::container_internal::hash_default_eq<int>, + Alloc<int>> + s(std::from_range, v, 0, TestingHash{}, Alloc<int>()); + EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); +} +#endif + } // namespace } // namespace container_internal ABSL_NAMESPACE_END
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index 89e0470..7395ab7 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc
@@ -762,10 +762,8 @@ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( V(Private{1}), V(Private{-1}), V(Private{2}), V("ABC"), V("BCD")))); -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ struct S {}; EXPECT_FALSE(is_hashable<absl::variant<S>>::value); -#endif } TEST(HashValueTest, ReferenceWrapper) { @@ -811,7 +809,6 @@ EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value); } -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ TEST(IsHashableTest, PoisonHash) { struct X {}; EXPECT_FALSE((is_hashable<X>::value)); @@ -826,7 +823,6 @@ EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value); #endif } -#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ // Hashable types // @@ -962,13 +958,11 @@ } void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) { -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ // is_hashable is false if we don't support any of the hooks. using type = CustomHashType<>; EXPECT_FALSE(is_hashable<type>()); EXPECT_FALSE(is_hashable<const type>()); EXPECT_FALSE(is_hashable<const type&>()); -#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ } template <InvokeTag Tag, typename... T>
diff --git a/absl/hash/internal/hash.cc b/absl/hash/internal/hash.cc index 74b6d57..43cb561 100644 --- a/absl/hash/internal/hash.cc +++ b/absl/hash/internal/hash.cc
@@ -78,6 +78,9 @@ return _mm_sub_epi64(a, b); } +// Bits of the second argument to Encrypt128/Decrypt128 are XORed with the +// first argument after encryption/decryption. + inline Vector128 Encrypt128(Vector128 data, Vector128 key) { return _mm_aesenc_si128(data, key); } @@ -86,6 +89,28 @@ return _mm_aesdec_si128(data, key); } +// We use each value as the first argument to shuffle all the bits around. We do +// not add any salt to the state or loaded data, instead we vary instructions +// used to mix bits Encrypt128/Decrypt128 and Add128/Sub128. On x86, +// Add128/Sub128 are combined to one instruction with data loading like +// `vpaddq xmm1, xmm0, xmmword ptr [rdi]`. + +inline Vector128 MixA(Vector128 a, Vector128 state) { + return Decrypt128(Add128(state, a), state); +} + +inline Vector128 MixB(Vector128 b, Vector128 state) { + return Decrypt128(Sub128(state, b), state); +} + +inline Vector128 MixC(Vector128 c, Vector128 state) { + return Encrypt128(Add128(state, c), state); +} + +inline Vector128 MixD(Vector128 d, Vector128 state) { + return Encrypt128(Sub128(state, d), state); +} + inline uint64_t ExtractLow64(Vector128 v) { return static_cast<uint64_t>(_mm_cvtsi128_si64(v)); } @@ -118,37 +143,41 @@ vaddq_u64(vreinterpretq_u64_u8(a), vreinterpretq_u64_u8(b))); } -inline Vector128 Sub128(Vector128 a, Vector128 b) { - return vreinterpretq_u8_u64( - vsubq_u64(vreinterpretq_u64_u8(a), vreinterpretq_u64_u8(b))); -} - -// Encrypt128 and Decrypt128 are equivalent to x86 versions. -// `vaeseq_u8` and `vaesdq_u8` perform `^ key` before encryption/decryption. -// We need to perform `^ key` after encryption/decryption to improve hash -// quality and match x86 version. +// Bits of the second argument to Decrypt128/Encrypt128 are XORed with the +// state argument BEFORE encryption (in x86 version they are XORed after). inline Vector128 Encrypt128(Vector128 data, Vector128 key) { - return vaesmcq_u8(vaeseq_u8(data, Vector128{})) ^ key; -} - -inline Vector128 Decrypt128(Vector128 data, Vector128 key) { - return vaesimcq_u8(vaesdq_u8(data, Vector128{})) ^ key; -} - -// ArmEncrypt128 and ArmDecrypt128 are ARM specific versions that use ARM -// instructions directly. -// We can only use these versions in the second round of encryption/decryption -// to have good hash quality. - -inline Vector128 ArmEncrypt128(Vector128 data, Vector128 key) { return vaesmcq_u8(vaeseq_u8(data, key)); } -inline Vector128 ArmDecrypt128(Vector128 data, Vector128 key) { +inline Vector128 Decrypt128(Vector128 data, Vector128 key) { return vaesimcq_u8(vaesdq_u8(data, key)); } +// We use decryption for a, b and encryption for c, d. That helps us to avoid +// collisions for trivial byte rotations. Mix4x16Vectors later uses +// encrypted/decrypted pairs differently to ensure that the order of blocks is +// important for the hash value. +// We also avoid using Add128/Sub128 instructions because state is being mixed +// before encryption/decryption. On ARM, there is no fusion of load and add/sub +// instructions so it is more expensive to use them. + +inline Vector128 MixA(Vector128 a, Vector128 state) { + return Decrypt128(a, state); +} + +inline Vector128 MixB(Vector128 b, Vector128 state) { + return Decrypt128(b, state); +} + +inline Vector128 MixC(Vector128 c, Vector128 state) { + return Encrypt128(c, state); +} + +inline Vector128 MixD(Vector128 d, Vector128 state) { + return Encrypt128(d, state); +} + inline uint64_t ExtractLow64(Vector128 v) { return vgetq_lane_u64(vreinterpretq_u64_u8(v), 0); } @@ -158,7 +187,7 @@ } uint64_t Mix4x16Vectors(Vector128 a, Vector128 b, Vector128 c, Vector128 d) { - Vector128 res128 = Add128(ArmEncrypt128(a, c), ArmDecrypt128(b, d)); + Vector128 res128 = Add128(Encrypt128(a, c), Decrypt128(b, d)); uint64_t x64 = ExtractLow64(res128); uint64_t y64 = ExtractHigh64(res128); return x64 ^ y64; @@ -176,16 +205,10 @@ Vector128 c = Load128(last32_ptr); Vector128 d = Load128(last32_ptr + 16); - // Bits of the second argument to Decrypt128/Encrypt128 are XORed with the - // state argument after encryption. We use each value as the first argument to - // shuffle all the bits around. We do not add any salt to the state or loaded - // data, instead we vary instructions used to mix bits Decrypt128/Encrypt128 - // and Add128/Sub128. On x86 Add128/Sub128 are combined to one instruction - // with data loading like `vpaddq xmm1, xmm0, xmmword ptr [rdi]`. - Vector128 na = Decrypt128(Add128(state, a), state); - Vector128 nb = Decrypt128(Sub128(state, b), state); - Vector128 nc = Encrypt128(Add128(state, c), state); - Vector128 nd = Encrypt128(Sub128(state, d), state); + Vector128 na = MixA(a, state); + Vector128 nb = MixB(b, state); + Vector128 nc = MixC(c, state); + Vector128 nd = MixD(d, state); // We perform another round of encryption to mix bits between two halves of // the input. @@ -216,15 +239,15 @@ &state1](const uint8_t* p) ABSL_ATTRIBUTE_ALWAYS_INLINE { Vector128 a = Load128(p); Vector128 b = Load128(p + 16); - state0 = Decrypt128(Add128(state0, a), state0); - state1 = Decrypt128(Sub128(state1, b), state1); + state0 = MixA(a, state0); + state1 = MixB(b, state1); }; auto mix_cd = [&state2, &state3](const uint8_t* p) ABSL_ATTRIBUTE_ALWAYS_INLINE { Vector128 c = Load128(p); Vector128 d = Load128(p + 16); - state2 = Encrypt128(Add128(state2, c), state2); - state3 = Encrypt128(Sub128(state3, d), state3); + state2 = MixC(c, state2); + state3 = MixD(d, state3); }; do {
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index 8b0f94a..ea04f47 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h
@@ -1222,8 +1222,7 @@ } #endif // ABSL_HASH_INTERNAL_HAS_CRC32 -#if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) && \ - ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ +#if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) #define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1 #else #define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0
diff --git a/absl/hash/internal/low_level_hash_test.cc b/absl/hash/internal/low_level_hash_test.cc index 6476462..f1e2d15 100644 --- a/absl/hash/internal/low_level_hash_test.cc +++ b/absl/hash/internal/low_level_hash_test.cc
@@ -405,38 +405,38 @@ }; #elif (defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(__ARM_FEATURE_CRYPTO)) constexpr uint64_t kGolden[kNumGoldenOutputs] = { - 0x248c82373f7f0d24, 0x0a4f8cbf55047086, 0x498dd0a4445ed65f, - 0x6d418b193638ab0f, 0x4112c1ce9142980e, 0x02132db6a189f206, - 0x36e550ca9139ee44, 0xe0a67fdbd8627314, 0x2b9528fe18f65d1d, - 0x037d9cf48ca9fd1c, 0xa87222631332ca06, 0x31f35e09af065022, - 0xacd6f1d29071c8e5, 0x54eb4f229a0d15a4, 0x132c27c6a747e136, - 0x13d7cb427efe7e2f, 0x71a5d21e00f00dcd, 0xdb909cbf1b0fbb64, - 0x4dc943ad8901fa5b, 0xacf4b3d41a46feb5, 0x12a37d19c14ffd65, - 0xdb511011bcdd95b9, 0xd6d75af1c8b86dbd, 0xc65aefdcff941a8e, - 0xbea311ef212c0306, 0xc49861afe7a6888b, 0x598424b541daf528, - 0x4cc264fbb57c4640, 0x1a7376211a5e674a, 0xcb82900ad06bf89b, - 0xd9d6201d685a4971, 0x77ed120a277ce616, 0x9bd5ad973b4d358c, - 0x880850ff91b6b772, 0xf9d24d40448fce38, 0x870b8ee54a31707d, - 0x613130fe647bd169, 0x04a0cc02a81989f3, 0x998adbda0ab3f8fa, - 0x2b28729269102040, 0xbdb9be95e352a6d5, 0xd5e2a55d78bd9fb0, - 0xef609c2b22eb93d6, 0xac23eb02494ae8e0, 0xcb8c5ab08163d2a3, - 0x63f822fc21b42698, 0xe7e8814288c470cc, 0x143b07aae2ccd592, - 0xc5d142f4806e13a3, 0xe695de2a1d8a344b, 0xc8ddc3ed542a5988, - 0x60ec526cc1e5274d, 0x732a04dcf34a7ac9, 0xf1daef52096a872a, - 0x541f04b87b3de158, 0xeb143a708b621f94, 0x0849cd39e156b25f, - 0x36eb0746caa62c5c, 0xbfa14eb3c31f78bf, 0x256637f35dc41f20, - 0x08293113693a58e2, 0x064202395a685840, 0x0593285ee1ed42ea, - 0xdcbf16fd8a44f213, 0xe9f5586745f4f23d, 0x66808a2c18365ae9, - 0xa70496836a5166e1, 0xe9ed7d0f9f572246, 0x024ba6063287d0cb, - 0xa441f6ac287479db, 0x72502c190698ee02, 0xb79705c6ced58c29, - 0x5c03f52968cb1fdc, 0x6f4b7c6bed6cc232, 0xed834775697438d3, - 0x6273b075725ffb6f, 0x60df77a69e9aafb2, 0x84483bf48b989c4e, - 0x37e42a1d35795a31, 0x280dcdb36b853ae5, 0x63309d698f2dd42c, - 0x24e65be2c805ea5b, 0x1db08e0d041efdf9, 0xb94aea8c4648772b, - 0x109f2b81aa4660d2, 0xcae92809feb1a390, 0x0a1cbf9628383b41, - 0xca0bf416706fc5c8, 0x9d4751bd7e638488, 0x343b363d5d96c7c7, - 0x6bacaedde1daf5aa, 0x721ead1618c4e405, 0xcfc19e400cb6dbc6, - 0x7ac0dd9128ec8cc3, 0xb7dd428bb44fc744, + 0xe3de56d839559570, 0x77afbb8906ccf19a, 0xe66e02ad8e92c12f, + 0x36cc6f2fe751bc64, 0xf4d28aea3ed69ade, 0xf246fd6a4ca33ab3, + 0xcae9edaf829a6575, 0x11fa7c88bf4cc73a, 0x98c47bfbae3d8c02, + 0x27545ea34451a56f, 0x14b4c1a27d26d2b2, 0x7613ca9857e7cbe0, + 0x02efc8f12e71bb88, 0x9c1a83672eee7d5b, 0x2b89aa9cfde6d9b3, + 0xabeb2cf68ab463dc, 0xfb3db51d62d71d28, 0x3177cc3e0927e344, + 0xb5798fc1d348beb6, 0x212c471510859095, 0x191df651c270548d, + 0x1b15d6b8e8cc3105, 0xdc51a9e369fbab13, 0xb674fd0372fab5aa, + 0x048aec21666fc8d5, 0x8b15383bc4a7e244, 0xf8945c253a43469f, + 0x513f31e6bf240064, 0xc37c6225063c266f, 0x2a6747f8952ec44c, + 0xa7a0f11d3607f268, 0x9b58d5c889166fb3, 0xb75ca76a67212a39, + 0x9a71a476bf4933f3, 0x3f049a71b475edf7, 0x7a49c8907a278e5e, + 0xf9a78757d9355ac9, 0xbe1bd9d70ee46398, 0x600e24a76a359a39, + 0x235905ade793a5f0, 0x940c36e0df8ec13a, 0x9300c551cb93a286, + 0x5e265b90e4828aba, 0x42dee1626c647735, 0x8cd32910c1f17a8c, + 0x642f44f3f8290fb0, 0xb73ee167c5f8655e, 0x9d05deadb2a47fe4, + 0x03b359dff5351708, 0x19a6427c0ee9c907, 0x0692dc026847e0d9, + 0xe4023ba608b25f1e, 0xf438ad7eea71dfc1, 0x205120c9355d4ac8, + 0xd4cf2cb1f412c846, 0x82d7d98b87ecf53a, 0x2cc779469cc3d690, + 0xf93545883141ce8e, 0x0f794c869b82a28a, 0x014e9fccfe7f7d9e, + 0xb6953652e49e4e0a, 0x68035eabb056e9b6, 0xf1b3a6847e610274, + 0x59dc584137c0cb55, 0xafb36238ad797ec6, 0xb9f331777a030104, + 0x2899a97f98140d3b, 0x0ae342d8d4f80ad0, 0xcfb25544c873fbd1, + 0xcb2498ca84b01a4c, 0x1a50e4a0d8db8406, 0x0afbf05b7c8c146e, + 0x1b45ee2ee670d71b, 0xef9204d9fcc31075, 0x2a5750d2ef558495, + 0x8e151888d0ce024e, 0x26882404dd58bcc9, 0x6c830f947bf2195f, + 0x2ff0c1fa64bf8cfb, 0x8f108f869e11d224, 0x7ce757787a04fd76, + 0xee55da944ebbbd85, 0x43563645bb00dcd0, 0x643848bf73336681, + 0x050f54d0478ffd52, 0xc5c1bff1bc3c008c, 0x48fd0f2729c9402d, + 0x7685b990e3e264af, 0x940dccac3264ed16, 0x688f94ee88c9ba90, + 0xca112c7825f3944b, 0x584cb5ddba130be2, 0xb7ced01f7140dff6, + 0xc10dcbb4e77168e6, 0xb5ea4360351ebaef, }; #else constexpr uint64_t kGolden[kNumGoldenOutputs] = {
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 59eb38b..2c651f2 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h
@@ -211,21 +211,7 @@ using result_of_t = typename type_traits_internal::result_of<F>::type; namespace type_traits_internal { -// In MSVC we can't probe std::hash or stdext::hash because it triggers a -// static_assert instead of failing substitution. Libc++ prior to 4.0 -// also used a static_assert. -// -#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \ - _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11) -#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0 -#else -#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1 -#endif -#if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ -template <typename Key, typename = size_t> -struct IsHashable : std::true_type {}; -#else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ template <typename Key, typename = void> struct IsHashable : std::false_type {}; @@ -235,7 +221,6 @@ absl::enable_if_t<std::is_convertible< decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())), std::size_t>::value>> : std::true_type {}; -#endif // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ struct AssertHashEnabledHelper { private:
diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc index 2f8cbc1..228e527 100644 --- a/absl/strings/escaping.cc +++ b/absl/strings/escaping.cc
@@ -827,7 +827,7 @@ } /* clang-format off */ -constexpr std::array<char, 256> kHexValueLenient = { +constexpr std::array<uint8_t, 256> kHexValueLenient = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -846,7 +846,7 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -constexpr std::array<signed char, 256> kHexValueStrict = { +constexpr std::array<int8_t, 256> kHexValueStrict = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -874,7 +874,7 @@ size_t num) { for (size_t i = 0; i < num; i++) { to[i] = static_cast<char>(kHexValueLenient[from[i * 2] & 0xFF] << 4) + - (kHexValueLenient[from[i * 2 + 1] & 0xFF]); + static_cast<char>(kHexValueLenient[from[i * 2 + 1] & 0xFF]); } } @@ -992,8 +992,10 @@ output, num_bytes, [hex](char* buf, size_t buf_size) { auto hex_p = hex.cbegin(); for (size_t i = 0; i < buf_size; ++i) { - int h1 = absl::kHexValueStrict[static_cast<size_t>(*hex_p++)]; - int h2 = absl::kHexValueStrict[static_cast<size_t>(*hex_p++)]; + int h1 = absl::kHexValueStrict[static_cast<size_t>( + static_cast<uint8_t>(*hex_p++))]; + int h2 = absl::kHexValueStrict[static_cast<size_t>( + static_cast<uint8_t>(*hex_p++))]; if (h1 == -1 || h2 == -1) { return size_t{0}; }
diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc index 4786c88..08618aa 100644 --- a/absl/strings/escaping_test.cc +++ b/absl/strings/escaping_test.cc
@@ -733,6 +733,10 @@ bytes = "abc"; EXPECT_TRUE(absl::HexStringToBytes("", &bytes)); EXPECT_EQ("", bytes); // Results in empty output. + + // Ensure there is no sign extension bug on a signed char. + hex.assign("\xC8" "b", 2); + EXPECT_FALSE(absl::HexStringToBytes(hex, &bytes)); } TEST(HexAndBack, HexStringToBytes_and_BytesToHexString) {
diff --git a/absl/strings/internal/append_and_overwrite.h b/absl/strings/internal/append_and_overwrite.h index 9dec73b..f8d62dc 100644 --- a/absl/strings/internal/append_and_overwrite.h +++ b/absl/strings/internal/append_and_overwrite.h
@@ -16,9 +16,9 @@ #define ABSL_STRINGS_INTERNAL_APPEND_AND_OVERWRITE_H_ #include "absl/base/config.h" -#include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/optimization.h" +#include "absl/base/throw_delegate.h" #include "absl/strings/resize_and_overwrite.h" namespace absl { @@ -46,8 +46,7 @@ void StringAppendAndOverwrite(T& str, typename T::size_type append_n, Op append_op) { if (ABSL_PREDICT_FALSE(append_n > str.max_size() - str.size())) { - absl::base_internal::ThrowStdLengthError( - "absl::strings_internal::StringAppendAndOverwrite"); + ThrowStdLengthError("absl::strings_internal::StringAppendAndOverwrite"); } auto old_size = str.size();
diff --git a/absl/strings/resize_and_overwrite.h b/absl/strings/resize_and_overwrite.h index 04c12d2..102b2bf 100644 --- a/absl/strings/resize_and_overwrite.h +++ b/absl/strings/resize_and_overwrite.h
@@ -53,9 +53,9 @@ #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" -#include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/optimization.h" +#include "absl/base/throw_delegate.h" #if defined(__cpp_lib_string_resize_and_overwrite) && \ __cpp_lib_string_resize_and_overwrite >= 202110L @@ -124,7 +124,7 @@ template <typename T, typename Op> void StringResizeAndOverwriteFallback(T& str, typename T::size_type n, Op op) { if (ABSL_PREDICT_FALSE(n > str.max_size())) { - absl::base_internal::ThrowStdLengthError("absl::StringResizeAndOverwrite"); + ThrowStdLengthError("absl::StringResizeAndOverwrite"); } #ifdef ABSL_HAVE_MEMORY_SANITIZER auto old_size = str.size();
diff --git a/absl/time/clock.h b/absl/time/clock.h index 41d2cf2..2be89a2 100644 --- a/absl/time/clock.h +++ b/absl/time/clock.h
@@ -34,6 +34,9 @@ // Now() // // Returns the current time, expressed as an `absl::Time` absolute time value. +// +// To improve testability, consider injecting an absl::Clock and using +// absl::Clock::TimeNow() instead. absl::Time Now(); // GetCurrentTimeNanos()
diff --git a/absl/time/internal/cctz/src/time_zone_name_win.cc b/absl/time/internal/cctz/src/time_zone_name_win.cc index 2b8724d..07aa8fa 100644 --- a/absl/time/internal/cctz/src/time_zone_name_win.cc +++ b/absl/time/internal/cctz/src/time_zone_name_win.cc
@@ -131,7 +131,7 @@ // Convert wchar_t array (UTF-16) to UTF-8 string std::string Utf16ToUtf8(const wchar_t* ptr, size_t size) { - if (size > std::numeric_limits<int>::max()) { + if (size > static_cast<size_t>(std::numeric_limits<int>::max())) { return std::string(); } const int chars_len = static_cast<int>(size); @@ -140,7 +140,6 @@ std::min<size_t>(result.capacity(), std::numeric_limits<int>::max()), 1); do { result.resize(len); - // TODO: Switch to std::string::data() when we require C++17 or higher. len = static_cast<std::size_t>(::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, ptr, chars_len, &result[0], static_cast<int>(len), nullptr, nullptr));
diff --git a/absl/types/internal/span.h b/absl/types/internal/span.h index cdf3941..9e8e418 100644 --- a/absl/types/internal/span.h +++ b/absl/types/internal/span.h
@@ -23,7 +23,6 @@ #include "absl/algorithm/algorithm.h" #include "absl/base/config.h" -#include "absl/base/internal/throw_delegate.h" #include "absl/meta/type_traits.h" namespace absl {
diff --git a/absl/types/span.h b/absl/types/span.h index 60e1ea8..b9f6b74 100644 --- a/absl/types/span.h +++ b/absl/types/span.h
@@ -64,11 +64,11 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" -#include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/nullability.h" #include "absl/base/optimization.h" #include "absl/base/port.h" // TODO(strel): remove this include +#include "absl/base/throw_delegate.h" #include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/meta/type_traits.h" #include "absl/types/internal/span.h" @@ -345,8 +345,7 @@ constexpr reference at(size_type i) const { return ABSL_PREDICT_TRUE(i < size()) // ? *(data() + i) - : (base_internal::ThrowStdOutOfRange( - "Span::at failed bounds check"), + : (ThrowStdOutOfRange("Span::at failed bounds check"), *(data() + i)); } @@ -465,9 +464,8 @@ // absl::MakeSpan(vec).subspan(4); // {} // absl::MakeSpan(vec).subspan(5); // throws std::out_of_range constexpr Span subspan(size_type pos = 0, size_type len = npos) const { - return (pos <= size()) - ? Span(data() + pos, (std::min)(size() - pos, len)) - : (base_internal::ThrowStdOutOfRange("pos > size()"), Span()); + return (pos <= size()) ? Span(data() + pos, (std::min)(size() - pos, len)) + : (ThrowStdOutOfRange("pos > size()"), Span()); } // Span::first() @@ -482,9 +480,8 @@ // absl::MakeSpan(vec).first(3); // {10, 11, 12} // absl::MakeSpan(vec).first(5); // throws std::out_of_range constexpr Span first(size_type len) const { - return (len <= size()) - ? Span(data(), len) - : (base_internal::ThrowStdOutOfRange("len > size()"), Span()); + return (len <= size()) ? Span(data(), len) + : (ThrowStdOutOfRange("len > size()"), Span()); } // Span::last() @@ -499,9 +496,8 @@ // absl::MakeSpan(vec).last(3); // {11, 12, 13} // absl::MakeSpan(vec).last(5); // throws std::out_of_range constexpr Span last(size_type len) const { - return (len <= size()) - ? Span(size() - len + data(), len) - : (base_internal::ThrowStdOutOfRange("len > size()"), Span()); + return (len <= size()) ? Span(size() - len + data(), len) + : (ThrowStdOutOfRange("len > size()"), Span()); } // Support for absl::Hash.
diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index 0c1ba32..7f36980 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh
@@ -94,6 +94,7 @@ --copt=\"-fno-sanitize-recover=${UBSAN_CHECKS}\" \ --copt=\"-fno-sanitize-blacklist\" \ --copt=-Werror \ + --define=\"absl=1\" \ --enable_bzlmod=true \ --features=external_include_paths \ --keep_going \
diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index 94f9c8a..235971b 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh
@@ -89,6 +89,7 @@ --copt=\"-fsanitize=thread\" \ --copt=\"-fno-sanitize-blacklist\" \ --copt=-Werror \ + --define=\"absl=1\" \ --enable_bzlmod=true \ --features=external_include_paths \ --keep_going \
diff --git a/ci/macos_xcode_bazel.sh b/ci/macos_xcode_bazel.sh index d50f979..1f509bd 100755 --- a/ci/macos_xcode_bazel.sh +++ b/ci/macos_xcode_bazel.sh
@@ -57,6 +57,7 @@ ${BAZEL_BIN} test ... \ --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \ --copt="-Werror" \ + --define="absl=1" \ --cxxopt="-std=c++17" \ --enable_bzlmod=true \ --features=external_include_paths \