diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index 9f43ff9..f01021b 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake
@@ -25,7 +25,7 @@ "base/internal/low_level_alloc.cc" "base/internal/low_level_alloc.h" "base/internal/low_level_scheduling.h" - "base/internal/nullability_impl.h" + "base/internal/nullability_deprecated.h" "base/internal/per_thread_tls.h" "base/internal/poison.cc" "base/internal/poison.h" @@ -162,6 +162,7 @@ "hash/internal/spy_hash_state.h" "hash/internal/low_level_hash.h" "hash/internal/low_level_hash.cc" + "hash/internal/weakly_mixed_integer.h" "log/absl_check.h" "log/absl_log.h" "log/absl_vlog_is_on.h"
diff --git a/MODULE.bazel b/MODULE.bazel index f8f7458..405d2c6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel
@@ -25,13 +25,13 @@ dev_dependency = True) use_repo(cc_configure, "local_config_cc") -bazel_dep(name = "rules_cc", version = "0.0.17") +bazel_dep(name = "rules_cc", version = "0.1.1") bazel_dep(name = "bazel_skylib", version = "1.7.1") -bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "platforms", version = "0.0.11") bazel_dep( name = "google_benchmark", - version = "1.8.5", + version = "1.9.2", dev_dependency = True, ) @@ -39,5 +39,5 @@ # intended to be used by Abseil users depend on GoogleTest. bazel_dep( name = "googletest", - version = "1.16.0", + version = "1.16.0.bcr.1", )
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 2054794..ef97b4e 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel
@@ -82,14 +82,13 @@ cc_library( name = "nullability", - srcs = ["internal/nullability_impl.h"], + srcs = ["internal/nullability_deprecated.h"], hdrs = ["nullability.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":core_headers", - "//absl/meta:type_traits", ], )
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 59a9a95..23942c0 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt
@@ -73,11 +73,10 @@ HDRS "nullability.h" SRCS - "internal/nullability_impl.h" + "internal/nullability_deprecated.h" DEPS absl::config absl::core_headers - absl::type_traits COPTS ${ABSL_DEFAULT_COPTS} )
diff --git a/absl/base/attributes.h b/absl/base/attributes.h index 300a138..d009f6d 100644 --- a/absl/base/attributes.h +++ b/absl/base/attributes.h
@@ -339,9 +339,9 @@ #ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE #ifdef _AIX // __attribute__((section(#name))) on AIX is achieved by using the `.csect` -// psudo op which includes an additional integer as part of its syntax indcating -// alignment. If data fall under different alignments then you might get a -// compilation error indicating a `Section type conflict`. +// pseudo op which includes an additional integer as part of its syntax +// indicating alignment. If data fall under different alignments then you might +// get a compilation error indicating a `Section type conflict`. #define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) #else #define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))
diff --git a/absl/base/internal/nullability_deprecated.h b/absl/base/internal/nullability_deprecated.h new file mode 100644 index 0000000..1174a96 --- /dev/null +++ b/absl/base/internal/nullability_deprecated.h
@@ -0,0 +1,106 @@ +// Copyright 2023 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_INTERNAL_NULLABILITY_DEPRECATED_H_ +#define ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_ + +#include "absl/base/attributes.h" +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace nullability_internal { + +template <typename T> +using NullableImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nullable")]] +#endif +// Don't add the _Nullable attribute in Objective-C compiles. Many Objective-C +// projects enable the `-Wnullable-to-nonnull-conversion warning`, which is +// liable to produce false positives. +#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) + = T _Nullable; +#else + = T; +#endif + +template <typename T> +using NonnullImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nonnull")]] +#endif +#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) + = T _Nonnull; +#else + = T; +#endif + +template <typename T> +using NullabilityUnknownImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nullability_Unspecified")]] +#endif +#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) + = T _Null_unspecified; +#else + = T; +#endif + +} // namespace nullability_internal + +// The following template aliases are deprecated forms of nullability +// annotations. They have some limitations, for example, an incompatibility with +// `auto*` pointers, as `auto` cannot be used in a template argument. +// +// It is important to note that these annotations are not distinct strong +// *types*. They are alias templates defined to be equal to the underlying +// pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a +// pointer of type `T*`. +// +// Prefer the macro style annotations in `absl/base/nullability.h` instead. + +// absl::Nonnull, analogous to absl_nonnull +// +// Example: +// absl::Nonnull<int*> foo; +// Is equivalent to: +// int* absl_nonnull foo; +template <typename T> +using Nonnull [[deprecated("Use `absl_nonnull`.")]] = + nullability_internal::NonnullImpl<T>; + +// absl::Nullable, analogous to absl_nullable +// +// Example: +// absl::Nullable<int*> foo; +// Is equivalent to: +// int* absl_nullable foo; +template <typename T> +using Nullable [[deprecated("Use `absl_nullable`.")]] = + nullability_internal::NullableImpl<T>; + +// absl::NullabilityUnknown, analogous to absl_nullability_unknown +// +// Example: +// absl::NullabilityUnknown<int*> foo; +// Is equivalent to: +// int* absl_nullability_unknown foo; +template <typename T> +using NullabilityUnknown [[deprecated("Use `absl_nullability_unknown`.")]] = + nullability_internal::NullabilityUnknownImpl<T>; + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
diff --git a/absl/base/internal/nullability_impl.h b/absl/base/internal/nullability_impl.h deleted file mode 100644 index b601fc4..0000000 --- a/absl/base/internal/nullability_impl.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2023 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_INTERNAL_NULLABILITY_IMPL_H_ -#define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ - -#include <memory> -#include <type_traits> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace nullability_internal { - -template <typename T> -using NullableImpl -#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) - [[clang::annotate("Nullable")]] -#endif -// Don't add the _Nullable attribute in Objective-C compiles. Many Objective-C -// projects enable the `-Wnullable-to-nonnull-conversion warning`, which is -// liable to produce false positives. -#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) - = T _Nullable; -#else - = T; -#endif - -template <typename T> -using NonnullImpl -#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) - [[clang::annotate("Nonnull")]] -#endif -#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) - = T _Nonnull; -#else - = T; -#endif - -template <typename T> -using NullabilityUnknownImpl -#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) - [[clang::annotate("Nullability_Unspecified")]] -#endif -#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) - = T _Null_unspecified; -#else - = T; -#endif - -} // namespace nullability_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
diff --git a/absl/base/internal/sysinfo_test.cc b/absl/base/internal/sysinfo_test.cc index f305b6c..c2b59aa 100644 --- a/absl/base/internal/sysinfo_test.cc +++ b/absl/base/internal/sysinfo_test.cc
@@ -41,7 +41,7 @@ EXPECT_EQ(GetTID(), GetTID()); // Basic compile and equality test. #ifdef __native_client__ // Native Client has a race condition bug that leads to memory - // exaustion when repeatedly creating and joining threads. + // exhaustion when repeatedly creating and joining threads. // https://bugs.chromium.org/p/nativeclient/issues/detail?id=1027 return; #endif
diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index 965c42d..bfd9887 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h
@@ -88,9 +88,14 @@ #elif defined(__aarch64__) // System timer of ARMv8 runs at a different frequency than the CPU's. -// The frequency is fixed, typically in the range 1-50MHz. It can be -// read at CNTFRQ special register. We assume the OS has set up -// the virtual timer properly. +// +// Frequency is fixed. From Armv8.6-A and Armv9.1-A on, the frequency is 1GHz. +// Pre-Armv8.6-A, the frequency was a system design choice, typically in the +// range of 1MHz to 50MHz. See also: +// https://developer.arm.com/documentation/102379/0101/What-is-the-Generic-Timer- +// +// It can be read at CNTFRQ special register. We assume the OS has set up the +// virtual timer properly. inline int64_t UnscaledCycleClock::Now() { int64_t virtual_timer_value; asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
diff --git a/absl/base/nullability.h b/absl/base/nullability.h index d11da57..3a5d6e8 100644 --- a/absl/base/nullability.h +++ b/absl/base/nullability.h
@@ -86,6 +86,9 @@ // // A non-null function pointer. // void (*absl_nonnull func)(int, double); // +// // A non-null array of `Employee`s as a parameter. +// void func(Employee employees[absl_nonnull]); +// // // A non-null std::unique_ptr to an `Employee`. // // As with `const`, it is possible to place the annotation on either side of // // a named type not ending in `*`, but placing it before the type it @@ -181,7 +184,7 @@ #define ABSL_BASE_NULLABILITY_H_ #include "absl/base/config.h" -#include "absl/base/internal/nullability_impl.h" +#include "absl/base/internal/nullability_deprecated.h" // ABSL_POINTERS_DEFAULT_NONNULL // @@ -312,46 +315,4 @@ #define ABSL_NULLABILITY_COMPATIBLE #endif -namespace absl { -ABSL_NAMESPACE_BEGIN - -// The following template aliases are alternate forms of the macro annotations -// above. They have some limitations, for example, an incompatibility with -// `auto*` pointers, as `auto` cannot be used in a template argument. -// -// It is important to note that these annotations are not distinct strong -// *types*. They are alias templates defined to be equal to the underlying -// pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a -// pointer of type `T*`. - -// absl::Nonnull, analogous to absl_nonnull -// -// Example: -// absl::Nonnull<int*> foo; -// Is equivalent to: -// int* absl_nonnull foo; -template <typename T> -using Nonnull = nullability_internal::NonnullImpl<T>; - -// absl::Nullable, analogous to absl_nullable -// -// Example: -// absl::Nullable<int*> foo; -// Is equivalent to: -// int* absl_nullable foo; -template <typename T> -using Nullable = nullability_internal::NullableImpl<T>; - -// absl::NullabilityUnknown, analogous to absl_nullability_unknown -// -// Example: -// absl::NullabilityUnknown<int*> foo; -// Is equivalent to: -// int* absl_nullability_unknown foo; -template <typename T> -using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>; - -ABSL_NAMESPACE_END -} // namespace absl - #endif // ABSL_BASE_NULLABILITY_H_
diff --git a/absl/base/nullability_test.cc b/absl/base/nullability_test.cc index b4a22e8..bccc388 100644 --- a/absl/base/nullability_test.cc +++ b/absl/base/nullability_test.cc
@@ -20,6 +20,7 @@ #include <utility> #include "gtest/gtest.h" +#include "absl/base/attributes.h" namespace { namespace macro_annotations { @@ -91,6 +92,9 @@ } } // namespace macro_annotations +// Allow testing of the deprecated type alias annotations. +ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING + using ::absl::Nonnull; using ::absl::NullabilityUnknown; using ::absl::Nullable; @@ -197,4 +201,6 @@ EXPECT_TRUE(DidAdlWin((util::MakeAdlWin*)nullptr)); EXPECT_TRUE(DidAdlWin((Nullable<util::MakeAdlWin*>)nullptr)); } + +ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING } // namespace
diff --git a/absl/base/raw_logging_test.cc b/absl/base/raw_logging_test.cc index 03a88ff..f4f3445 100644 --- a/absl/base/raw_logging_test.cc +++ b/absl/base/raw_logging_test.cc
@@ -43,12 +43,27 @@ ABSL_RAW_CHECK(true, "RAW CHECK"); } +TEST(RawLoggingCompilationTest, DebugLog) { + ABSL_RAW_DLOG(INFO, "RAW DLOG: %d", 1); +} + +TEST(RawLoggingCompilationTest, PassingDebugCheck) { + ABSL_RAW_DCHECK(true, "failure message"); +} + // Not all platforms support output from raw log, so we don't verify any // particular output for RAW check failures (expecting the empty string // accomplishes this). This test is primarily a compilation test, but we // are verifying process death when EXPECT_DEATH works for a platform. const char kExpectedDeathOutput[] = ""; +#if !defined(NDEBUG) // if debug build +TEST(RawLoggingDeathTest, FailingDebugCheck) { + EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_DCHECK(1 == 0, "explanation"), + kExpectedDeathOutput); +} +#endif // if debug build + TEST(RawLoggingDeathTest, FailingCheck) { EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_CHECK(1 == 0, "explanation"), kExpectedDeathOutput);
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index 768b8ab..91f930a 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel
@@ -72,6 +72,7 @@ "//absl/base:dynamic_annotations", "//absl/base:iterator_traits_internal", "//absl/base:throw_delegate", + "//absl/hash:weakly_mixed_integer", "//absl/memory", ], ) @@ -148,6 +149,7 @@ "//absl/base:core_headers", "//absl/base:iterator_traits_internal", "//absl/base:throw_delegate", + "//absl/hash:weakly_mixed_integer", "//absl/memory", "//absl/meta:type_traits", ], @@ -740,6 +742,7 @@ "//absl/base:raw_logging_internal", "//absl/functional:function_ref", "//absl/hash", + "//absl/hash:weakly_mixed_integer", "//absl/memory", "//absl/meta:type_traits", "//absl/numeric:bits", @@ -1086,6 +1089,7 @@ "//absl/base:core_headers", "//absl/base:raw_logging_internal", "//absl/base:throw_delegate", + "//absl/hash:weakly_mixed_integer", "//absl/memory", "//absl/meta:type_traits", "//absl/strings",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 66fe405..70f78c4 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt
@@ -41,6 +41,7 @@ absl::strings absl::throw_delegate absl::type_traits + absl::weakly_mixed_integer ) # Internal-only target, do not depend on directly. @@ -134,6 +135,7 @@ absl::iterator_traits_internal absl::throw_delegate absl::memory + absl::weakly_mixed_integer PUBLIC ) @@ -202,6 +204,7 @@ absl::throw_delegate absl::memory absl::type_traits + absl::weakly_mixed_integer PUBLIC ) @@ -790,6 +793,7 @@ absl::prefetch absl::raw_logging_internal absl::utility + absl::weakly_mixed_integer PUBLIC )
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index 8bf8e6c..6c238fc 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h
@@ -50,6 +50,7 @@ #include "absl/base/optimization.h" #include "absl/base/port.h" #include "absl/container/internal/compressed_tuple.h" +#include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/memory/memory.h" namespace absl { @@ -392,7 +393,7 @@ template <typename H> friend H AbslHashValue(H h, const FixedArray& v) { return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()), - v.size()); + hash_internal::WeaklyMixedInteger{v.size()}); } private:
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 318d654..f871b34 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h
@@ -53,6 +53,7 @@ #include "absl/base/optimization.h" #include "absl/base/port.h" #include "absl/container/internal/inlined_vector.h" +#include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/memory/memory.h" #include "absl/meta/type_traits.h" @@ -1008,7 +1009,8 @@ template <typename H, typename T, size_t N, typename A> H AbslHashValue(H h, const absl::InlinedVector<T, N, A>& a) { auto size = a.size(); - return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size); + return H::combine(H::combine_contiguous(std::move(h), a.data(), size), + hash_internal::WeaklyMixedInteger{size}); } ABSL_NAMESPACE_END
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h index 5e2abb2..21f00ae 100644 --- a/absl/container/internal/btree_container.h +++ b/absl/container/internal/btree_container.h
@@ -25,6 +25,7 @@ #include "absl/base/internal/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" #include "absl/memory/memory.h" #include "absl/meta/type_traits.h" @@ -267,7 +268,8 @@ for (const auto &v : b) { h = State::combine(std::move(h), v); } - return State::combine(std::move(h), b.size()); + return State::combine(std::move(h), + hash_internal::WeaklyMixedInteger{b.size()}); } protected:
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc index 6d61872..adba8b1 100644 --- a/absl/container/internal/raw_hash_set.cc +++ b/absl/container/internal/raw_hash_set.cc
@@ -466,7 +466,7 @@ // Initializes control bytes for growing after SOO to the next capacity. // `soo_ctrl` is placed in the position `SooSlotIndex()`. -// `new_hash` is placed in the postion `new_offset`. +// `new_hash` is placed in the position `new_offset`. // The table must be non-empty SOO. ABSL_ATTRIBUTE_ALWAYS_INLINE inline void InitializeThreeElementsControlBytesAfterSoo(ctrl_t soo_ctrl, size_t new_hash,
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 2ca8fba..b22f817 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h
@@ -214,6 +214,7 @@ #include "absl/container/internal/hashtablez_sampler.h" #include "absl/functional/function_ref.h" #include "absl/hash/hash.h" +#include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/memory/memory.h" #include "absl/meta/type_traits.h" #include "absl/numeric/bits.h" @@ -2985,7 +2986,7 @@ H>::type AbslHashValue(H h, const raw_hash_set& s) { return H::combine(H::combine_unordered(std::move(h), s.begin(), s.end()), - s.size()); + hash_internal::WeaklyMixedInteger{s.size()}); } friend void swap(raw_hash_set& a,
diff --git a/absl/container/internal/raw_hash_set_probe_benchmark.cc b/absl/container/internal/raw_hash_set_probe_benchmark.cc index 8f36305..e56648f 100644 --- a/absl/container/internal/raw_hash_set_probe_benchmark.cc +++ b/absl/container/internal/raw_hash_set_probe_benchmark.cc
@@ -245,13 +245,28 @@ } }; -constexpr char kStringFormat[] = "/path/to/file/name-%07d-of-9999999.txt"; +enum class StringSize { kSmall, kMedium, kLarge, kExtraLarge }; +constexpr char kStringFormat[] = "%s/name-%07d-of-9999999.txt"; -template <bool small> +template <StringSize size> struct String { std::string value; static std::string Make(uint32_t v) { - return {small ? absl::StrCat(v) : absl::StrFormat(kStringFormat, v)}; + switch (size) { + case StringSize::kSmall: + return absl::StrCat(v); + case StringSize::kMedium: // < 32 bytes + return absl::StrFormat(kStringFormat, "/path", v); + case StringSize::kLarge: // 33-64 bytes + return absl::StrFormat(kStringFormat, "/path/to/file", v); + case StringSize::kExtraLarge: // > 64 bytes + return absl::StrFormat(kStringFormat, + "/path/to/a/very/long/file/name/so/that/total/" + "length/is/larger/than/64/bytes", + v); + default: + return ""; + } } }; @@ -285,10 +300,9 @@ mutable uintptr_t current = PointerForAlignment<Align>(); }; - -template <bool small> -struct Sequential<String<small>> { - std::string operator()() const { return String<small>::Make(current++); } +template <StringSize size> +struct Sequential<String<size>> { + std::string operator()() const { return String<size>::Make(current++); } mutable uint32_t current = 0; }; @@ -389,10 +403,10 @@ } }; -template <class Dist, bool small> -struct Random<String<small>, Dist> { +template <class Dist, StringSize size> +struct Random<String<size>, Dist> { std::string operator()() const { - return String<small>::Make(Random<uint32_t, Dist>{}()); + return String<size>::Make(Random<uint32_t, Dist>{}()); } }; @@ -421,9 +435,20 @@ return absl::StrCat("PtrIdentity", Align); } -template <bool small> -std::string Name(String<small>*) { - return small ? "StrS" : "StrL"; +template <StringSize size> +std::string Name(String<size>*) { + switch (size) { + case StringSize::kSmall: + return "StrS"; + case StringSize::kMedium: + return "StrM"; + case StringSize::kLarge: + return "StrL"; + case StringSize::kExtraLarge: + return "StrXL"; + default: + return ""; + } } template <class T, class U> @@ -543,12 +568,18 @@ RunForType<PtrIdentity<32>>(results); RunForType<PtrIdentity<64>>(results); RunForType<std::pair<uint32_t, uint32_t>>(results); - RunForType<String<true>>(results); - RunForType<String<false>>(results); - RunForType<std::pair<uint64_t, String<true>>>(results); - RunForType<std::pair<String<true>, uint64_t>>(results); - RunForType<std::pair<uint64_t, String<false>>>(results); - RunForType<std::pair<String<false>, uint64_t>>(results); + RunForType<String<StringSize::kSmall>>(results); + RunForType<String<StringSize::kMedium>>(results); + RunForType<String<StringSize::kLarge>>(results); + RunForType<String<StringSize::kExtraLarge>>(results); + RunForType<std::pair<uint64_t, String<StringSize::kSmall>>>(results); + RunForType<std::pair<String<StringSize::kSmall>, uint64_t>>(results); + RunForType<std::pair<uint64_t, String<StringSize::kMedium>>>(results); + RunForType<std::pair<String<StringSize::kMedium>, uint64_t>>(results); + RunForType<std::pair<uint64_t, String<StringSize::kLarge>>>(results); + RunForType<std::pair<String<StringSize::kLarge>, uint64_t>>(results); + RunForType<std::pair<uint64_t, String<StringSize::kExtraLarge>>>(results); + RunForType<std::pair<String<StringSize::kExtraLarge>, uint64_t>>(results); switch (output()) { case OutputStyle::kRegular:
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index a98ca81..9836c93 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc
@@ -125,12 +125,20 @@ // Some platforms use a special .opd section to store function pointers. const char kOpdSectionName[] = ".opd"; -#if (defined(__powerpc__) && !(_CALL_ELF > 1)) || defined(__ia64) +#if defined(__powerpc64__) && defined(_CALL_ELF) +#if _CALL_ELF <= 1 +#define ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI 1 +#endif +#endif +#if defined(ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI) || defined(__ia64) // Use opd section for function descriptors on these platforms, the function // address is the first word of the descriptor. -enum { kPlatformUsesOPDSections = 1 }; -#else // not PPC or IA64 -enum { kPlatformUsesOPDSections = 0 }; +// +// https://maskray.me/blog/2023-02-26-linker-notes-on-power-isa notes that +// opd sections are used on 64-bit PowerPC with the ELFv1 ABI. +inline constexpr bool kPlatformUsesOPDSections = true; +#else +inline constexpr bool kPlatformUsesOPDSections = false; #endif // This works for PowerPC & IA64 only. A function descriptor consist of two @@ -1451,11 +1459,11 @@ } phoff += phentsize; -#if defined(__powerpc__) && !(_CALL_ELF > 1) - // On the PowerPC ELF v1 ABI, function pointers actually point to function - // descriptors. These descriptors are stored in an .opd section, which is - // mapped read-only. We thus need to look at all readable segments, not - // just the executable ones. +#ifdef ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI + // On the PowerPC 64-bit ELFv1 ABI, function pointers actually point to + // function descriptors. These descriptors are stored in an .opd section, + // which is mapped read-only. We thus need to look at all readable + // segments, not just the executable ones. constexpr int interesting = PF_R; #else constexpr int interesting = PF_X | PF_R; @@ -1762,3 +1770,5 @@ return absl::debugging_internal::GetFileMappingHint(start, end, offset, filename); } + +#undef ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI
diff --git a/absl/functional/function_ref.h b/absl/functional/function_ref.h index 0b8c402..f1d087a 100644 --- a/absl/functional/function_ref.h +++ b/absl/functional/function_ref.h
@@ -82,10 +82,6 @@ // // replaced by an `absl::FunctionRef`: // bool Visitor(absl::FunctionRef<void(my_proto&, absl::string_view)> // callback); -// -// Note: the assignment operator within an `absl::FunctionRef` is intentionally -// deleted to prevent misuse; because the `absl::FunctionRef` does not own the -// underlying type, assignment likely indicates misuse. template <typename R, typename... Args> class FunctionRef<R(Args...)> { private: @@ -121,9 +117,7 @@ ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f); } - // To help prevent subtle lifetime bugs, FunctionRef is not assignable. - // Typically, it should only be used as an argument type. - FunctionRef& operator=(const FunctionRef& rhs) = delete; + FunctionRef& operator=(const FunctionRef& rhs) = default; FunctionRef(const FunctionRef& rhs) = default; // Call the underlying object.
diff --git a/absl/functional/function_ref_test.cc b/absl/functional/function_ref_test.cc index c021113..98d11f7 100644 --- a/absl/functional/function_ref_test.cc +++ b/absl/functional/function_ref_test.cc
@@ -52,6 +52,16 @@ EXPECT_EQ(1337, ref()); } +TEST(FunctionRefTest, CopyAssignment) { + FunctionRef<int()> a = +[]() -> int { + ADD_FAILURE() << "Unexpectedly called"; + return 0; + }; + FunctionRef<int()> b = +[] { return 1337; }; + a = b; + EXPECT_EQ(1337, a()); +} + int NoExceptFunction() noexcept { return 1337; } // TODO(jdennett): Add a test for noexcept member functions.
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel index 30f78d4..b2ffcd0 100644 --- a/absl/hash/BUILD.bazel +++ b/absl/hash/BUILD.bazel
@@ -44,6 +44,7 @@ deps = [ ":city", ":low_level_hash", + ":weakly_mixed_integer", "//absl/base:config", "//absl/base:core_headers", "//absl/base:endian", @@ -151,6 +152,7 @@ visibility = ["//visibility:private"], deps = [ ":hash", + ":weakly_mixed_integer", "//absl/strings", "//absl/strings:str_format", ], @@ -199,6 +201,21 @@ ], ) +cc_library( + name = "weakly_mixed_integer", + hdrs = ["internal/weakly_mixed_integer.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl/container:__pkg__", + "//absl/strings:__pkg__", + "//absl/types:__pkg__", + ], + deps = [ + "//absl/base:config", + ], +) + cc_test( name = "low_level_hash_test", srcs = ["internal/low_level_hash_test.cc"],
diff --git a/absl/hash/CMakeLists.txt b/absl/hash/CMakeLists.txt index cc46aab..6996d93 100644 --- a/absl/hash/CMakeLists.txt +++ b/absl/hash/CMakeLists.txt
@@ -39,6 +39,7 @@ absl::variant absl::utility absl::low_level_hash + absl::weakly_mixed_integer PUBLIC ) @@ -119,6 +120,7 @@ absl::hash absl::strings absl::str_format + absl::weakly_mixed_integer TESTONLY PUBLIC ) @@ -169,6 +171,18 @@ absl::prefetch ) +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + weakly_mixed_integer + HDRS + "internal/weakly_mixed_integer.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config +) + absl_cc_test( NAME low_level_hash_test
diff --git a/absl/hash/hash.h b/absl/hash/hash.h index 479b17b..23f4e9d 100644 --- a/absl/hash/hash.h +++ b/absl/hash/hash.h
@@ -87,6 +87,7 @@ #include "absl/base/config.h" #include "absl/functional/function_ref.h" #include "absl/hash/internal/hash.h" +#include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/meta/type_traits.h" namespace absl { @@ -356,6 +357,12 @@ hash_state.combine_contiguous_(hash_state.state_, first, size); return hash_state; } + + static HashState combine_weakly_mixed_integer( + HashState hash_state, hash_internal::WeaklyMixedInteger value) { + hash_state.combine_weakly_mixed_integer_(hash_state.state_, value); + return hash_state; + } using HashState::HashStateBase::combine_contiguous; private: @@ -371,6 +378,13 @@ state = T::combine_contiguous(std::move(state), first, size); } + template <typename T> + static void CombineWeaklyMixedIntegerImpl( + void* p, hash_internal::WeaklyMixedInteger value) { + T& state = *static_cast<T*>(p); + state = T::combine_weakly_mixed_integer(std::move(state), value); + } + static HashState combine_raw(HashState hash_state, uint64_t value) { hash_state.combine_raw_(hash_state.state_, value); return hash_state; @@ -385,6 +399,7 @@ template <typename T> void Init(T* state) { state_ = state; + combine_weakly_mixed_integer_ = &CombineWeaklyMixedIntegerImpl<T>; combine_contiguous_ = &CombineContiguousImpl<T>; combine_raw_ = &CombineRawImpl<T>; run_combine_unordered_ = &RunCombineUnorderedImpl<T>; @@ -424,6 +439,7 @@ // Do not erase an already erased state. void Init(HashState* state) { state_ = state->state_; + combine_weakly_mixed_integer_ = state->combine_weakly_mixed_integer_; combine_contiguous_ = state->combine_contiguous_; combine_raw_ = state->combine_raw_; run_combine_unordered_ = state->run_combine_unordered_; @@ -435,6 +451,8 @@ } void* state_; + void (*combine_weakly_mixed_integer_)( + void*, absl::hash_internal::WeaklyMixedInteger); void (*combine_contiguous_)(void*, const unsigned char*, size_t); void (*combine_raw_)(void*, uint64_t); HashState (*run_combine_unordered_)(
diff --git a/absl/hash/hash_instantiated_test.cc b/absl/hash/hash_instantiated_test.cc index e65de9c..f0df86f 100644 --- a/absl/hash/hash_instantiated_test.cc +++ b/absl/hash/hash_instantiated_test.cc
@@ -51,7 +51,7 @@ // Dummy type with unordered equality and hashing semantics. This preserves // input order internally, and is used below to ensure we get test coverage -// for equal sequences with different iteraton orders. +// for equal sequences with different iteration orders. template <typename T> class UnorderedSequence { public:
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index b751a16..c3182f1 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc
@@ -191,9 +191,8 @@ // Limit the scope to the bits we would be using for Swisstable. constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1; size_t stuck_bits = (~bits_or | bits_and) & kMask; - // Test that there are at most 2 stuck bits. Sometimes we see stuck_bits - // of 0x3. - EXPECT_LE(absl::popcount(stuck_bits), 2) << "0x" << std::hex << stuck_bits; + // Test that there are at most 3 stuck bits. + EXPECT_LE(absl::popcount(stuck_bits), 3) << "0x" << std::hex << stuck_bits; } } @@ -1224,4 +1223,20 @@ TypeErasedHashStateUser{1, s})); } +struct AutoReturnTypeUser { + int a; + std::string b; + + template <typename H> + friend auto AbslHashValue(H state, const AutoReturnTypeUser& value) { + return H::combine(std::move(state), value.a, value.b); + } +}; + +TEST(HashOf, AutoReturnTypeUser) { + std::string s = "s"; + EXPECT_EQ(absl::HashOf(1, s), + absl::Hash<AutoReturnTypeUser>{}(AutoReturnTypeUser{1, s})); +} + } // namespace
diff --git a/absl/hash/hash_testing.h b/absl/hash/hash_testing.h index 207dfaf..817a40d 100644 --- a/absl/hash/hash_testing.h +++ b/absl/hash/hash_testing.h
@@ -15,7 +15,9 @@ #ifndef ABSL_HASH_HASH_TESTING_H_ #define ABSL_HASH_HASH_TESTING_H_ +#include <cstddef> #include <initializer_list> +#include <string> #include <tuple> #include <type_traits> #include <vector>
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index 3a34bde..c1b1f66 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h
@@ -24,6 +24,8 @@ #include <TargetConditionals.h> #endif +// We include config.h here to make sure that ABSL_INTERNAL_CPLUSPLUS_LANG is +// defined. #include "absl/base/config.h" // For feature testing and determining which headers can be included. @@ -65,7 +67,7 @@ #include "absl/base/port.h" #include "absl/container/fixed_array.h" #include "absl/hash/internal/city.h" -#include "absl/hash/internal/low_level_hash.h" +#include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/meta/type_traits.h" #include "absl/numeric/bits.h" #include "absl/numeric/int128.h" @@ -394,6 +396,11 @@ return H::combine_contiguous(std::move(hash_state), start, sizeof(value)); } +template <typename H> +H hash_weakly_mixed_integer(H hash_state, WeaklyMixedInteger value) { + return H::combine_weakly_mixed_integer(std::move(hash_state), value); +} + // ----------------------------------------------------------------------------- // AbslHashValue for Basic Types // ----------------------------------------------------------------------------- @@ -609,7 +616,7 @@ H AbslHashValue(H hash_state, absl::string_view str) { return H::combine( H::combine_contiguous(std::move(hash_state), str.data(), str.size()), - str.size()); + WeaklyMixedInteger{str.size()}); } // Support std::wstring, std::u16string and std::u32string. @@ -622,7 +629,7 @@ const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) { return H::combine( H::combine_contiguous(std::move(hash_state), str.data(), str.size()), - str.size()); + WeaklyMixedInteger{str.size()}); } #ifdef ABSL_HAVE_STD_STRING_VIEW @@ -635,7 +642,7 @@ H AbslHashValue(H hash_state, std::basic_string_view<Char> str) { return H::combine( H::combine_contiguous(std::move(hash_state), str.data(), str.size()), - str.size()); + WeaklyMixedInteger{str.size()}); } #endif // ABSL_HAVE_STD_STRING_VIEW @@ -685,7 +692,7 @@ for (const auto& t : deque) { hash_state = H::combine(std::move(hash_state), t); } - return H::combine(std::move(hash_state), deque.size()); + return H::combine(std::move(hash_state), WeaklyMixedInteger{deque.size()}); } // AbslHashValue for hashing std::forward_list @@ -697,7 +704,7 @@ hash_state = H::combine(std::move(hash_state), t); ++size; } - return H::combine(std::move(hash_state), size); + return H::combine(std::move(hash_state), WeaklyMixedInteger{size}); } // AbslHashValue for hashing std::list @@ -707,7 +714,7 @@ for (const auto& t : list) { hash_state = H::combine(std::move(hash_state), t); } - return H::combine(std::move(hash_state), list.size()); + return H::combine(std::move(hash_state), WeaklyMixedInteger{list.size()}); } // AbslHashValue for hashing std::vector @@ -721,7 +728,7 @@ AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) { return H::combine(H::combine_contiguous(std::move(hash_state), vector.data(), vector.size()), - vector.size()); + WeaklyMixedInteger{vector.size()}); } // AbslHashValue special cases for hashing std::vector<bool> @@ -742,7 +749,8 @@ unsigned char c = static_cast<unsigned char>(i); hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c)); } - return H::combine(combiner.finalize(std::move(hash_state)), vector.size()); + return H::combine(combiner.finalize(std::move(hash_state)), + WeaklyMixedInteger{vector.size()}); } #else // When not working around the libstdc++ bug above, we still have to contend @@ -758,7 +766,7 @@ AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) { return H::combine(std::move(hash_state), std::hash<std::vector<T, Allocator>>{}(vector), - vector.size()); + WeaklyMixedInteger{vector.size()}); } #endif @@ -775,7 +783,7 @@ for (const auto& t : map) { hash_state = H::combine(std::move(hash_state), t); } - return H::combine(std::move(hash_state), map.size()); + return H::combine(std::move(hash_state), WeaklyMixedInteger{map.size()}); } // AbslHashValue for hashing std::multimap @@ -788,7 +796,7 @@ for (const auto& t : map) { hash_state = H::combine(std::move(hash_state), t); } - return H::combine(std::move(hash_state), map.size()); + return H::combine(std::move(hash_state), WeaklyMixedInteger{map.size()}); } // AbslHashValue for hashing std::set @@ -798,7 +806,7 @@ for (const auto& t : set) { hash_state = H::combine(std::move(hash_state), t); } - return H::combine(std::move(hash_state), set.size()); + return H::combine(std::move(hash_state), WeaklyMixedInteger{set.size()}); } // AbslHashValue for hashing std::multiset @@ -808,7 +816,7 @@ for (const auto& t : set) { hash_state = H::combine(std::move(hash_state), t); } - return H::combine(std::move(hash_state), set.size()); + return H::combine(std::move(hash_state), WeaklyMixedInteger{set.size()}); } // ----------------------------------------------------------------------------- @@ -822,7 +830,7 @@ H hash_state, const std::unordered_set<Key, Hash, KeyEqual, Alloc>& s) { return H::combine( H::combine_unordered(std::move(hash_state), s.begin(), s.end()), - s.size()); + WeaklyMixedInteger{s.size()}); } // AbslHashValue for hashing std::unordered_multiset @@ -833,7 +841,7 @@ const std::unordered_multiset<Key, Hash, KeyEqual, Alloc>& s) { return H::combine( H::combine_unordered(std::move(hash_state), s.begin(), s.end()), - s.size()); + WeaklyMixedInteger{s.size()}); } // AbslHashValue for hashing std::unordered_set @@ -845,7 +853,7 @@ const std::unordered_map<Key, T, Hash, KeyEqual, Alloc>& s) { return H::combine( H::combine_unordered(std::move(hash_state), s.begin(), s.end()), - s.size()); + WeaklyMixedInteger{s.size()}); } // AbslHashValue for hashing std::unordered_multiset @@ -857,7 +865,7 @@ const std::unordered_multimap<Key, T, Hash, KeyEqual, Alloc>& s) { return H::combine( H::combine_unordered(std::move(hash_state), s.begin(), s.end()), - s.size()); + WeaklyMixedInteger{s.size()}); } // ----------------------------------------------------------------------------- @@ -968,11 +976,20 @@ // `false`. struct HashSelect { private: + struct WeaklyMixedIntegerProbe { + template <typename H> + static H Invoke(H state, WeaklyMixedInteger value) { + return hash_internal::hash_weakly_mixed_integer(std::move(state), value); + } + }; + struct State : HashStateBase<State> { static State combine_contiguous(State hash_state, const unsigned char*, size_t); using State::HashStateBase::combine_contiguous; static State combine_raw(State state, uint64_t value); + static State combine_weakly_mixed_integer(State hash_state, + WeaklyMixedInteger value); }; struct UniquelyRepresentedProbe { @@ -1034,6 +1051,7 @@ // disjunction provides short circuiting wrt instantiation. template <typename T> using Apply = absl::disjunction< // + Probe<WeaklyMixedIntegerProbe, T>, // Probe<UniquelyRepresentedProbe, T>, // Probe<HashValueProbe, T>, // Probe<LegacyHashProbe, T>, // @@ -1114,6 +1132,19 @@ MixingHashState() : state_(Seed()) {} friend class MixingHashState::HashStateBase; + template <typename H> + friend H absl::hash_internal::hash_weakly_mixed_integer(H, + WeaklyMixedInteger); + + static MixingHashState combine_weakly_mixed_integer( + MixingHashState hash_state, WeaklyMixedInteger value) { + // Some transformation for the value is needed to make an empty + // string/container change the mixing hash state. + // Seed() is most likely already in a register. + // TODO(b/384509507): experiment with using kMul or last 31 bits of kMul. + // See https://godbolt.org/z/6cM77s3PW for ideas. + return MixingHashState{hash_state.state_ + (Seed() + value.value)}; + } template <typename CombinerT> static MixingHashState RunCombineUnordered(MixingHashState state, @@ -1286,13 +1317,16 @@ } ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t lhs, uint64_t rhs) { + // For 32 bit platforms we are trying to use all 64 lower bits. + if constexpr (sizeof(size_t) < 8) { + uint64_t m = lhs * rhs; + return m ^ (m >> 32); + } // Though the 128-bit product on AArch64 needs two instructions, it is // still a good balance between speed and hash quality. - using MultType = - absl::conditional_t<sizeof(size_t) == 4, uint64_t, uint128>; - MultType m = lhs; + uint128 m = lhs; m *= rhs; - return static_cast<uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2))); + return Uint128High64(m) ^ Uint128Low64(m); } // Slightly lower latency than Mix, but with lower quality. The byte swap @@ -1302,13 +1336,7 @@ const uint64_t n = lhs ^ rhs; // WeakMix doesn't work well on 32-bit platforms so just use Mix. if constexpr (sizeof(size_t) < 8) return Mix(n, kMul); -#ifdef __ARM_ACLE - // gbswap_64 compiles to `rev` on ARM, but `rbit` is better because it - // reverses bits rather than reversing bytes. - return __rbitll(n * kMul); -#else return absl::gbswap_64(n * kMul); -#endif } // An extern to avoid bloat on a direct call to LowLevelHash() with fixed
diff --git a/absl/hash/internal/spy_hash_state.h b/absl/hash/internal/spy_hash_state.h index 92490b1..e403113 100644 --- a/absl/hash/internal/spy_hash_state.h +++ b/absl/hash/internal/spy_hash_state.h
@@ -16,12 +16,14 @@ #define ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_ #include <algorithm> +#include <cstddef> #include <cstdint> #include <ostream> #include <string> #include <vector> #include "absl/hash/hash.h" +#include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/strings/match.h" #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" @@ -167,6 +169,11 @@ return hash_state; } + static SpyHashStateImpl combine_weakly_mixed_integer( + SpyHashStateImpl hash_state, WeaklyMixedInteger value) { + return combine(std::move(hash_state), value.value); + } + using SpyHashStateImpl::HashStateBase::combine_contiguous; template <typename CombinerT>
diff --git a/absl/hash/internal/weakly_mixed_integer.h b/absl/hash/internal/weakly_mixed_integer.h new file mode 100644 index 0000000..5575436 --- /dev/null +++ b/absl/hash/internal/weakly_mixed_integer.h
@@ -0,0 +1,38 @@ +// Copyright 2025 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_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_ +#define ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_ + +#include <cstddef> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace hash_internal { + +// Contains an integer that will be mixed into a hash state more weakly than +// regular integers. It is useful for cases in which an integer is a part of a +// larger object and needs to be mixed as a supplement. E.g., absl::string_view +// and absl::Span are mixing their size wrapped with WeaklyMixedInteger. +struct WeaklyMixedInteger { + size_t value; +}; + +} // namespace hash_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_
diff --git a/absl/random/gaussian_distribution.h b/absl/random/gaussian_distribution.h index ce84d4a..eb75bfe 100644 --- a/absl/random/gaussian_distribution.h +++ b/absl/random/gaussian_distribution.h
@@ -244,7 +244,7 @@ bits); // U(-1, 1) const double x = j * zg_.x[i]; - // Retangular box. Handles >97% of all cases. + // Rectangular box. Handles >97% of all cases. // For any given box, this handles between 75% and 99% of values. // Equivalent to U(01) < (x[i+1] / x[i]), and when i == 0, ~93.5% if (std::abs(x) < zg_.x[i + 1]) {
diff --git a/absl/random/internal/entropy_pool.cc b/absl/random/internal/entropy_pool.cc index 092730d..fa47d0d 100644 --- a/absl/random/internal/entropy_pool.cc +++ b/absl/random/internal/entropy_pool.cc
@@ -44,9 +44,11 @@ // single generator within a RandenPool<T>. It is an internal implementation // detail, and does not aim to conform to [rand.req.urng]. // -// NOTE: There are alignment issues when used on ARM, for instance. -// See the allocation code in PoolAlignedAlloc(). -class RandenPoolEntry { +// At least 32-byte alignment is required for the state_ array on some ARM +// platforms. We also want this aligned to a cacheline to eliminate false +// sharing. +class alignas(std::max(size_t{ABSL_CACHELINE_SIZE}, size_t{32})) + RandenPoolEntry { public: static constexpr size_t kState = RandenTraits::kStateBytes / sizeof(uint32_t); static constexpr size_t kCapacity = @@ -74,7 +76,8 @@ private: // Randen URBG state. - uint32_t state_[kState] ABSL_GUARDED_BY(mu_); // First to satisfy alignment. + // At least 32-byte alignment is required by ARM platform code. + alignas(32) uint32_t state_[kState] ABSL_GUARDED_BY(mu_); SpinLock mu_; const Randen impl_; size_t next_ ABSL_GUARDED_BY(mu_); @@ -148,22 +151,6 @@ #endif } -// Allocate a RandenPoolEntry with at least 32-byte alignment, which is required -// by ARM platform code. -RandenPoolEntry* PoolAlignedAlloc() { - constexpr size_t kAlignment = - ABSL_CACHELINE_SIZE > 32 ? ABSL_CACHELINE_SIZE : 32; - - // Not all the platforms that we build for have std::aligned_alloc, however - // since we never free these objects, we can over allocate and munge the - // pointers to the correct alignment. - uintptr_t x = reinterpret_cast<uintptr_t>( - new char[sizeof(RandenPoolEntry) + kAlignment]); - auto y = x % kAlignment; - void* aligned = reinterpret_cast<void*>(y == 0 ? x : (x + kAlignment - y)); - return new (aligned) RandenPoolEntry(); -} - // Allocate and initialize kPoolSize objects of type RandenPoolEntry. void InitPoolURBG() { static constexpr size_t kSeedSize = @@ -174,7 +161,7 @@ ThrowSeedGenException(); } for (size_t i = 0; i < kPoolSize; i++) { - shared_pools[i] = PoolAlignedAlloc(); + shared_pools[i] = new RandenPoolEntry(); shared_pools[i]->Init( absl::MakeSpan(&seed_material[i * kSeedSize], kSeedSize)); }
diff --git a/absl/status/statusor_test.cc b/absl/status/statusor_test.cc index 8341040..17a3384 100644 --- a/absl/status/statusor_test.cc +++ b/absl/status/statusor_test.cc
@@ -459,7 +459,7 @@ EXPECT_EQ(p, *source); } - // Move asssignment + // Move assignment { const auto p = std::make_shared<int>(17); absl::StatusOr<std::shared_ptr<int>> source(p);
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index ddc115d..3b0aab5 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel
@@ -606,6 +606,7 @@ "//absl/crc:crc32c", "//absl/crc:crc_cord_state", "//absl/functional:function_ref", + "//absl/hash:weakly_mixed_integer", "//absl/meta:type_traits", "//absl/numeric:bits", "//absl/types:compare",
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 40c57f6..ec731d8 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt
@@ -998,6 +998,7 @@ absl::span absl::strings absl::type_traits + absl::weakly_mixed_integer PUBLIC )
diff --git a/absl/strings/cord.h b/absl/strings/cord.h index b50150f..7afa419 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h
@@ -79,6 +79,7 @@ #include "absl/base/optimization.h" #include "absl/crc/internal/crc_cord_state.h" #include "absl/functional/function_ref.h" +#include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/meta/type_traits.h" #include "absl/strings/cord_analysis.h" #include "absl/strings/cord_buffer.h" @@ -1097,7 +1098,8 @@ hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(), chunk.size()); }); - return H::combine(combiner.finalize(std::move(hash_state)), size()); + return H::combine(combiner.finalize(std::move(hash_state)), + hash_internal::WeaklyMixedInteger{size()}); } friend class CrcCord;
diff --git a/absl/strings/internal/charconv_bigint_test.cc b/absl/strings/internal/charconv_bigint_test.cc index a8b9945..7bbf16d 100644 --- a/absl/strings/internal/charconv_bigint_test.cc +++ b/absl/strings/internal/charconv_bigint_test.cc
@@ -176,7 +176,7 @@ TEST(BigUnsigned, MultiplyByOverflow) { { - // Check that multiplcation overflow predictably truncates. + // Check that multiplication overflow predictably truncates. // A big int with all bits on. BigUnsigned<4> all_bits_on("340282366920938463463374607431768211455");
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h index 1d86305..ffa7f11 100644 --- a/absl/strings/str_format.h +++ b/absl/strings/str_format.h
@@ -609,7 +609,7 @@ // // Note that unlike with AbslFormatConvert(), AbslStringify() does not allow // customization of allowed conversion characters. AbslStringify() uses `%v` as -// the underlying conversion specififer. Additionally, AbslStringify() supports +// the underlying conversion specifier. Additionally, AbslStringify() supports // use with absl::StrCat while AbslFormatConvert() does not. // // Example:
diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h index b2b0cf6..5b232f5 100644 --- a/absl/time/internal/cctz/include/cctz/time_zone.h +++ b/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -200,7 +200,7 @@ // version() and description() provide additional information about the // time zone. The content of each of the returned strings is unspecified, // however, when the IANA Time Zone Database is the underlying data source - // the version() string will be in the familar form (e.g, "2018e") or + // the version() string will be in the familiar form (e.g, "2018e") or // empty when unavailable. // // Note: These functions are for informational or testing purposes only.
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc index 4a5ac1b..ba7e149 100644 --- a/absl/time/internal/cctz/src/cctz_benchmark.cc +++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -199,6 +199,7 @@ "America/Ciudad_Juarez", "America/Coral_Harbour", "America/Costa_Rica", + "America/Coyhaique", "America/Creston", "America/Cuiaba", "America/Curacao", @@ -215,7 +216,6 @@ "America/Fort_Nelson", "America/Fortaleza", "America/Glace_Bay", - "America/Godthab", "America/Goose_Bay", "America/Grand_Turk", "America/Grenada",
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 22c0eb6..e1bea28 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -134,6 +134,7 @@ "America/Ciudad_Juarez", "America/Coral_Harbour", "America/Costa_Rica", + "America/Coyhaique", "America/Creston", "America/Cuiaba", "America/Curacao", @@ -150,7 +151,6 @@ "America/Fort_Nelson", "America/Fortaleza", "America/Glace_Bay", - "America/Godthab", "America/Goose_Bay", "America/Grand_Turk", "America/Grenada",
diff --git a/absl/time/internal/cctz/testdata/version b/absl/time/internal/cctz/testdata/version index 0846b7f..ef468ad 100644 --- a/absl/time/internal/cctz/testdata/version +++ b/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@ -2025a +2025b
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Coyhaique b/absl/time/internal/cctz/testdata/zoneinfo/America/Coyhaique new file mode 100644 index 0000000..26354e8 --- /dev/null +++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Coyhaique Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran index 824acb0..6fd31e0 100644 --- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran +++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Iran b/absl/time/internal/cctz/testdata/zoneinfo/Iran index 824acb0..6fd31e0 100644 --- a/absl/time/internal/cctz/testdata/zoneinfo/Iran +++ b/absl/time/internal/cctz/testdata/zoneinfo/Iran Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab index 5ded056..36535bd 100644 --- a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab +++ b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
@@ -124,7 +124,8 @@ CI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan CK -2114-15946 Pacific/Rarotonga CL -3327-07040 America/Santiago most of Chile -CL -5309-07055 America/Punta_Arenas Region of Magallanes +CL -4534-07204 America/Coyhaique Aysén Region +CL -5309-07055 America/Punta_Arenas Magallanes Region CL -2709-10926 Pacific/Easter Easter Island CN +3114+12128 Asia/Shanghai Beijing Time CN +4348+08735 Asia/Urumqi Xinjiang Time
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab b/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab index d2c1e48..093f0a0 100644 --- a/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab +++ b/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab
@@ -104,7 +104,7 @@ XX +4734-05243 America/St_Johns Newfoundland ("NST/NDT") # # -03 -XX -2332-04637 America/Sao_Paulo eastern South America +XX -2332-04637 America/Sao_Paulo eastern and southern South America # # -03/-02 (North America DST) XX +4703-05620 America/Miquelon St Pierre & Miquelon
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index febc9e5..0668a2e 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel
@@ -64,6 +64,7 @@ "//absl/base:core_headers", "//absl/base:nullability", "//absl/base:throw_delegate", + "//absl/hash:weakly_mixed_integer", "//absl/meta:type_traits", ], ) @@ -81,6 +82,7 @@ "//absl/base:exception_testing", "//absl/container:fixed_array", "//absl/container:inlined_vector", + "//absl/hash", "//absl/hash:hash_testing", "//absl/meta:type_traits", "//absl/strings",
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt index f48accf..20a7e90 100644 --- a/absl/types/CMakeLists.txt +++ b/absl/types/CMakeLists.txt
@@ -43,6 +43,7 @@ absl::nullability absl::throw_delegate absl::type_traits + absl::weakly_mixed_integer PUBLIC ) @@ -60,6 +61,7 @@ absl::core_headers absl::exception_testing absl::fixed_array + absl::hash absl::inlined_vector absl::hash_testing absl::strings
diff --git a/absl/types/span.h b/absl/types/span.h index 9d16496..444b2ae 100644 --- a/absl/types/span.h +++ b/absl/types/span.h
@@ -66,7 +66,8 @@ #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/port.h" // TODO(strel): remove this include +#include "absl/hash/internal/weakly_mixed_integer.h" #include "absl/meta/type_traits.h" #include "absl/types/internal/span.h" @@ -498,7 +499,7 @@ template <typename H> friend H AbslHashValue(H h, Span v) { return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()), - v.size()); + hash_internal::WeaklyMixedInteger{v.size()}); } private:
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc index a1a207f..6700b81 100644 --- a/absl/types/span_test.cc +++ b/absl/types/span_test.cc
@@ -30,6 +30,7 @@ #include "absl/base/options.h" #include "absl/container/fixed_array.h" #include "absl/container/inlined_vector.h" +#include "absl/hash/hash.h" #include "absl/hash/hash_testing.h" #include "absl/meta/type_traits.h" #include "absl/strings/str_cat.h" @@ -885,4 +886,16 @@ T(array + 1, 2), T(array + 2, 2)})); } +// std::vector is implicitly convertible to absl::Span. +// There are real life cases where clients rely on this consistency in order to +// implement heterogeneous lookup. +TEST(Span, HashConsistentWithVectorLike) { + EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})), + absl::HashOf(std::vector<int>{1, 2, 3})); + EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})), + absl::HashOf(absl::InlinedVector<int, 2>{1, 2, 3})); + EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})), + absl::HashOf(absl::FixedArray<int>{1, 2, 3})); +} + } // namespace