diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 53bac42..ea4db17 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel
@@ -768,6 +768,20 @@ ) cc_test( + name = "cpu_detect_test", + size = "small", + srcs = ["internal/cpu_detect_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":cpu_detect", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( name = "low_level_alloc_test", size = "medium", srcs = ["internal/low_level_alloc_test.cc"],
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 8d5cf66..2a20d74 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt
@@ -637,6 +637,19 @@ absl_cc_test( NAME + cpu_detect_test + SRCS + "internal/cpu_detect_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base_cpu_detect + absl::config + GTest::gtest_main +) + +absl_cc_test( + NAME low_level_alloc_test SRCS "internal/low_level_alloc_test.cc"
diff --git a/absl/base/internal/cpu_detect.cc b/absl/base/internal/cpu_detect.cc index c08637c..5275888 100644 --- a/absl/base/internal/cpu_detect.cc +++ b/absl/base/internal/cpu_detect.cc
@@ -253,6 +253,16 @@ bool SupportsArmCRC32PMULL() { return false; } +bool SupportsBmi2() { + int cpu_info[4]; + __cpuid(cpu_info, 0); + if (cpu_info[0] < 7) { + return false; + } + __cpuidex(cpu_info, 7, 0); + return (cpu_info[1] & (1 << 8)) != 0; +} + #elif defined(__aarch64__) && defined(__linux__) #ifndef HWCAP_CPUID @@ -322,6 +332,8 @@ #endif } +bool SupportsBmi2() { return false; } + #elif defined(__aarch64__) && defined(__APPLE__) CpuType GetCpuType() { return CpuType::kUnknown; } @@ -365,12 +377,16 @@ return true; } +bool SupportsBmi2() { return false; } + #else CpuType GetCpuType() { return CpuType::kUnknown; } bool SupportsArmCRC32PMULL() { return false; } +bool SupportsBmi2() { return false; } + #endif // Returns how many hardware contexts per CPU exist. Note: AMD CPUs prior to Zen
diff --git a/absl/base/internal/cpu_detect.h b/absl/base/internal/cpu_detect.h index 5ea76ec..43c7c38 100644 --- a/absl/base/internal/cpu_detect.h +++ b/absl/base/internal/cpu_detect.h
@@ -63,6 +63,9 @@ // tuning. bool SupportsArmCRC32PMULL(); +// Returns whether the host CPU supports BMI2 instructions. +bool SupportsBmi2(); + // Returns whether the host CPU supports simultaneous multithreading (SMT) and // if it is enabled. bool IsSMTEnabled();
diff --git a/absl/base/internal/cpu_detect_test.cc b/absl/base/internal/cpu_detect_test.cc new file mode 100644 index 0000000..80b8b87 --- /dev/null +++ b/absl/base/internal/cpu_detect_test.cc
@@ -0,0 +1,43 @@ +// Copyright 2026 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/internal/cpu_detect.h" + +#include "gtest/gtest.h" +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace base_internal { +namespace { + +TEST(CpuDetectTest, SupportsBmi2) { +#if defined(__x86_64__) || defined(_M_X64) +#if ABSL_HAVE_BUILTIN(__builtin_cpu_supports) && defined(__linux__) + EXPECT_EQ(SupportsBmi2(), __builtin_cpu_supports("bmi2") != 0); +#else + // If __builtin_cpu_supports is not available, we just verify it doesn't + // crash. + (void)SupportsBmi2(); +#endif +#else + // On non-x86, SupportsBmi2() must return false. + EXPECT_FALSE(SupportsBmi2()); +#endif +} + +} // namespace +} // namespace base_internal +ABSL_NAMESPACE_END +} // namespace absl
diff --git a/absl/container/linked_hash_map.h b/absl/container/linked_hash_map.h index 61720d6..efc9686 100644 --- a/absl/container/linked_hash_map.h +++ b/absl/container/linked_hash_map.h
@@ -219,14 +219,15 @@ alloc) {} linked_hash_map(const linked_hash_map& other) - : linked_hash_map(other.bucket_count(), other.hash_function(), - other.key_eq(), other.get_allocator()) { + : linked_hash_map(0, other.hash_function(), other.key_eq(), + other.get_allocator()) { + reserve(other.size()); CopyFrom(other); } linked_hash_map(const linked_hash_map& other, const allocator_type& alloc) - : linked_hash_map(other.bucket_count(), other.hash_function(), - other.key_eq(), alloc) { + : linked_hash_map(0, other.hash_function(), other.key_eq(), alloc) { + reserve(other.size()); CopyFrom(other); } @@ -250,8 +251,9 @@ linked_hash_map& operator=(const linked_hash_map& other) { if (this != &other) { // Make a new set, with other's hash/eq/alloc. - set_ = SetType(other.bucket_count(), other.set_.hash_function(), - other.set_.key_eq(), other.get_allocator()); + set_ = SetType(0, other.set_.hash_function(), other.set_.key_eq(), + other.get_allocator()); + set_.reserve(other.size()); // Copy the list, with other's allocator. list_ = ListType(other.get_allocator()); CopyFrom(other); @@ -272,6 +274,7 @@ linked_hash_map& operator=(std::initializer_list<value_type> values) { clear(); + reserve(values.size()); insert(values.begin(), values.end()); return *this; }
diff --git a/absl/container/linked_hash_set.h b/absl/container/linked_hash_set.h index fe207c8..ae7819b 100644 --- a/absl/container/linked_hash_set.h +++ b/absl/container/linked_hash_set.h
@@ -209,14 +209,15 @@ alloc) {} linked_hash_set(const linked_hash_set& other) - : linked_hash_set(other.bucket_count(), other.hash_function(), - other.key_eq(), other.get_allocator()) { + : linked_hash_set(0, other.hash_function(), other.key_eq(), + other.get_allocator()) { + reserve(other.size()); CopyFrom(other); } linked_hash_set(const linked_hash_set& other, const allocator_type& alloc) - : linked_hash_set(other.bucket_count(), other.hash_function(), - other.key_eq(), alloc) { + : linked_hash_set(0, other.hash_function(), other.key_eq(), alloc) { + reserve(other.size()); CopyFrom(other); } @@ -240,8 +241,9 @@ linked_hash_set& operator=(const linked_hash_set& other) { if (this != &other) { // Make a new set, with other's hash/eq/alloc. - set_ = SetType(other.bucket_count(), other.set_.hash_function(), + set_ = SetType(0, other.set_.hash_function(), other.set_.key_eq(), other.get_allocator()); + set_.reserve(other.size()); // Copy the list, with other's allocator. list_ = ListType(other.get_allocator()); CopyFrom(other); @@ -261,6 +263,7 @@ linked_hash_set& operator=(std::initializer_list<key_type> values) { clear(); + reserve(values.size()); insert(values.begin(), values.end()); return *this; }
diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel index 5e85523..d61eef6 100644 --- a/absl/functional/BUILD.bazel +++ b/absl/functional/BUILD.bazel
@@ -53,7 +53,9 @@ cc_test( name = "any_invocable_test", srcs = [ - "any_invocable_test.cc", + "any_invocable_test.h", + "any_invocable_test_inst1.cc", + "any_invocable_test_inst2.cc", "internal/any_invocable.h", ], copts = ABSL_TEST_COPTS,
diff --git a/absl/functional/CMakeLists.txt b/absl/functional/CMakeLists.txt index 362c149..03a7596 100644 --- a/absl/functional/CMakeLists.txt +++ b/absl/functional/CMakeLists.txt
@@ -36,8 +36,9 @@ NAME any_invocable_test SRCS - "any_invocable_test.cc" - "internal/any_invocable.h" + "any_invocable_test.h" + "any_invocable_test_inst1.cc" + "any_invocable_test_inst2.cc" COPTS ${ABSL_TEST_COPTS} DEPS
diff --git a/absl/functional/any_invocable_test.cc b/absl/functional/any_invocable_test.h similarity index 91% rename from absl/functional/any_invocable_test.cc rename to absl/functional/any_invocable_test.h index 1ad6d7b..868ac88 100644 --- a/absl/functional/any_invocable_test.cc +++ b/absl/functional/any_invocable_test.h
@@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +// To prevent compiler memory exhaustion (OOM / Killed signal terminates +// cc1plus) during parallel builds with GCC, the test suite instantiations have +// been split into two separate compilation units: any_invocable_test_inst1.cc +// and any_invocable_test_inst2.cc. The test definitions remain here in this +// header. + +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + +#ifndef ABSL_FUNCTIONAL_ANY_INVOCABLE_TEST_H_ +#define ABSL_FUNCTIONAL_ANY_INVOCABLE_TEST_H_ + #include "absl/functional/any_invocable.h" #include <cstddef> @@ -33,7 +44,7 @@ "These tests assume that the small object storage is at least " "the size of a pointer."); -namespace { +namespace absl_any_invocable_test { // A dummy type we use when passing qualifiers to metafunctions struct _ {}; @@ -283,11 +294,15 @@ }; // Actual non-member functions rather than function objects -Int add_function(Int&& a, int b, int c) noexcept { return a.value + b + c; } +inline Int add_function(Int&& a, int b, int c) noexcept { + return a.value + b + c; +} -Int mult_function(Int&& a, int b, int c) noexcept { return a.value * b * c; } +inline Int mult_function(Int&& a, int b, int c) noexcept { + return a.value * b * c; +} -Int square_function(Int const&& a) noexcept { return a.value * a.value; } +inline Int square_function(Int const&& a) noexcept { return a.value * a.value; } template <class Sig> using AnyInvocable = absl::AnyInvocable<Sig>; @@ -1525,24 +1540,6 @@ MoveConstructionFromNonEmpty, ComparisonWithNullptrEmpty, ComparisonWithNullptrNonempty, ResultType); -INSTANTIATE_TYPED_TEST_SUITE_P( - NonRvalueCallMayThrow, AnyInvTestBasic, - TestParameterListNonRvalueQualifiersCallMayThrow); -INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestBasic, - TestParameterListRvalueQualifiersCallMayThrow); - -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestBasic, - TestParameterListRemoteMovable); -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestBasic, - TestParameterListRemoteNonMovable); - -INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestBasic, TestParameterListLocal); - -INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestBasic, - TestParameterListNonRvalueQualifiersNothrowCall); -INSTANTIATE_TYPED_TEST_SUITE_P(CallNothrowRvalue, AnyInvTestBasic, - TestParameterListRvalueQualifiersNothrowCall); - // Tests for functions that take two operands. REGISTER_TYPED_TEST_SUITE_P( AnyInvTestCombinatoric, MoveAssignEmptyEmptyLhsRhs, @@ -1562,25 +1559,6 @@ SwapEmptyLhsNonemptyRhs, SwapNonemptyLhsEmptyRhs, SwapNonemptyLhsNonemptyRhs); -INSTANTIATE_TYPED_TEST_SUITE_P( - NonRvalueCallMayThrow, AnyInvTestCombinatoric, - TestParameterListNonRvalueQualifiersCallMayThrow); -INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestCombinatoric, - TestParameterListRvalueQualifiersCallMayThrow); - -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestCombinatoric, - TestParameterListRemoteMovable); -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestCombinatoric, - TestParameterListRemoteNonMovable); - -INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestCombinatoric, - TestParameterListLocal); - -INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestCombinatoric, - TestParameterListNonRvalueQualifiersNothrowCall); -INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestCombinatoric, - TestParameterListRvalueQualifiersNothrowCall); - REGISTER_TYPED_TEST_SUITE_P(AnyInvTestMovable, ConversionConstructionUserDefinedType, ConversionConstructionVoidCovariance, @@ -1588,71 +1566,20 @@ ConversionAssignUserDefinedTypeNonemptyLhs, ConversionAssignVoidCovariance); -INSTANTIATE_TYPED_TEST_SUITE_P( - NonRvalueCallMayThrow, AnyInvTestMovable, - TestParameterListNonRvalueQualifiersCallMayThrow); -INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestMovable, - TestParameterListRvalueQualifiersCallMayThrow); - -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestMovable, - TestParameterListRemoteMovable); - -INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestMovable, - TestParameterListLocal); - -INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestMovable, - TestParameterListNonRvalueQualifiersNothrowCall); -INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestMovable, - TestParameterListRvalueQualifiersNothrowCall); - REGISTER_TYPED_TEST_SUITE_P(AnyInvTestNoexceptFalse, ConversionConstructionConstraints, ConversionAssignConstraints); -INSTANTIATE_TYPED_TEST_SUITE_P( - NonRvalueCallMayThrow, AnyInvTestNoexceptFalse, - TestParameterListNonRvalueQualifiersCallMayThrow); -INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestNoexceptFalse, - TestParameterListRvalueQualifiersCallMayThrow); - -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestNoexceptFalse, - TestParameterListRemoteMovable); -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestNoexceptFalse, - TestParameterListRemoteNonMovable); - -INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestNoexceptFalse, - TestParameterListLocal); - REGISTER_TYPED_TEST_SUITE_P(AnyInvTestNoexceptTrue, ConversionConstructionConstraints, ConversionAssignConstraints); -INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestNoexceptTrue, - TestParameterListNonRvalueQualifiersNothrowCall); -INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestNoexceptTrue, - TestParameterListRvalueQualifiersNothrowCall); - REGISTER_TYPED_TEST_SUITE_P(AnyInvTestNonRvalue, ConversionConstructionReferenceWrapper, NonMoveableResultType, ConversionAssignReferenceWrapperEmptyLhs, ConversionAssignReferenceWrapperNonemptyLhs); -INSTANTIATE_TYPED_TEST_SUITE_P( - NonRvalueCallMayThrow, AnyInvTestNonRvalue, - TestParameterListNonRvalueQualifiersCallMayThrow); - -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestNonRvalue, - TestParameterListRemoteMovable); -INSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestNonRvalue, - TestParameterListRemoteNonMovable); - -INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestNonRvalue, - TestParameterListLocal); - -INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestNonRvalue, - TestParameterListNonRvalueQualifiersNothrowCall); - REGISTER_TYPED_TEST_SUITE_P(AnyInvTestRvalue, ConversionConstructionReferenceWrapper, NonMoveableResultType, @@ -1660,16 +1587,12 @@ NonConstCrashesOnSecondCall, QualifierIndependentObjectLifetime); -INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestRvalue, - TestParameterListRvalueQualifiersCallMayThrow); - -INSTANTIATE_TYPED_TEST_SUITE_P(CallNothrowRvalue, AnyInvTestRvalue, - TestParameterListRvalueQualifiersNothrowCall); - // Minimal SFINAE testing for platforms where we can't run the tests, but we can // build binaries for. static_assert(std::is_convertible_v<void (*)(), absl::AnyInvocable<void() &&>>, ""); static_assert(!std::is_convertible_v<void*, absl::AnyInvocable<void() &&>>, ""); -} // namespace +} // namespace absl_any_invocable_test + +#endif // ABSL_FUNCTIONAL_ANY_INVOCABLE_TEST_H_
diff --git a/absl/functional/any_invocable_test_inst1.cc b/absl/functional/any_invocable_test_inst1.cc new file mode 100644 index 0000000..a15722a --- /dev/null +++ b/absl/functional/any_invocable_test_inst1.cc
@@ -0,0 +1,117 @@ +// Copyright 2022 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. + +// To prevent compiler memory exhaustion (OOM / Killed signal terminates +// cc1plus) during parallel builds with GCC, the test suite instantiations have +// been split into two separate compilation units: any_invocable_test_inst1.cc +// and any_invocable_test_inst2.cc. + +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + +#include "absl/functional/any_invocable_test.h" + +namespace absl_any_invocable_test { + +INSTANTIATE_TYPED_TEST_SUITE_P( + NonRvalueCallMayThrow, AnyInvTestBasic, + TestParameterListNonRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestBasic, + TestParameterListRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestBasic, + TestParameterListRemoteNonMovable); + +INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestBasic, TestParameterListLocal); + +INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestBasic, + TestParameterListNonRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P(CallNothrowRvalue, AnyInvTestBasic, + TestParameterListRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P( + NonRvalueCallMayThrow, AnyInvTestCombinatoric, + TestParameterListNonRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestCombinatoric, + TestParameterListRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestCombinatoric, + TestParameterListRemoteNonMovable); + +INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestCombinatoric, + TestParameterListLocal); + +INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestCombinatoric, + TestParameterListNonRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestCombinatoric, + TestParameterListRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P( + NonRvalueCallMayThrow, AnyInvTestMovable, + TestParameterListNonRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestMovable, + TestParameterListRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestMovable, + TestParameterListLocal); + +INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestMovable, + TestParameterListNonRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestMovable, + TestParameterListRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P( + NonRvalueCallMayThrow, AnyInvTestNoexceptFalse, + TestParameterListNonRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestNoexceptFalse, + TestParameterListRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestNoexceptFalse, + TestParameterListRemoteNonMovable); + +INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestNoexceptFalse, + TestParameterListLocal); + +INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestNoexceptTrue, + TestParameterListNonRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestNoexceptTrue, + TestParameterListRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P( + NonRvalueCallMayThrow, AnyInvTestNonRvalue, + TestParameterListNonRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestNonRvalue, + TestParameterListRemoteNonMovable); + +INSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestNonRvalue, + TestParameterListLocal); + +INSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestNonRvalue, + TestParameterListNonRvalueQualifiersNothrowCall); + +INSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestRvalue, + TestParameterListRvalueQualifiersCallMayThrow); + +INSTANTIATE_TYPED_TEST_SUITE_P(CallNothrowRvalue, AnyInvTestRvalue, + TestParameterListRvalueQualifiersNothrowCall); + +} // namespace absl_any_invocable_test
diff --git a/absl/functional/any_invocable_test_inst2.cc b/absl/functional/any_invocable_test_inst2.cc new file mode 100644 index 0000000..366e1d2 --- /dev/null +++ b/absl/functional/any_invocable_test_inst2.cc
@@ -0,0 +1,41 @@ +// Copyright 2022 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. + +// To prevent compiler memory exhaustion (OOM / Killed signal terminates +// cc1plus) during parallel builds with GCC, the test suite instantiations have +// been split into two separate compilation units: any_invocable_test_inst1.cc +// and any_invocable_test_inst2.cc. + +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + +#include "absl/functional/any_invocable_test.h" + +namespace absl_any_invocable_test { + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestBasic, + TestParameterListRemoteMovable); + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestCombinatoric, + TestParameterListRemoteMovable); + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestMovable, + TestParameterListRemoteMovable); + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestNoexceptFalse, + TestParameterListRemoteMovable); + +INSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestNonRvalue, + TestParameterListRemoteMovable); + +} // namespace absl_any_invocable_test
diff --git a/absl/log/internal/test_helpers.cc b/absl/log/internal/test_helpers.cc index bfcc967..63e9deb 100644 --- a/absl/log/internal/test_helpers.cc +++ b/absl/log/internal/test_helpers.cc
@@ -18,6 +18,10 @@ #include <zircon/syscalls.h> #endif +#if defined(ABSL_HAVE_ALARM) +#include <signal.h> +#endif + #include "gtest/gtest.h" #include "absl/base/config.h" #include "absl/base/log_severity.h"
diff --git a/absl/log/stripping_test.cc b/absl/log/stripping_test.cc index 271fae1..20231b9 100644 --- a/absl/log/stripping_test.cc +++ b/absl/log/stripping_test.cc
@@ -33,7 +33,7 @@ #include <stdio.h> -#if defined(__MACH__) +#if defined(__APPLE__) #include <mach-o/dyld.h> #elif defined(_WIN32) #include <Windows.h> @@ -191,7 +191,7 @@ absl::FPrintF(stderr, "Failed to open /pkg/bin/<binary name>: %s\n", err); } return fp; -#elif defined(__MACH__) +#elif defined(__APPLE__) uint32_t size = 0; int ret = _NSGetExecutablePath(nullptr, &size); if (ret != -1) {
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index def78d5..6b96d0c 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel
@@ -1259,6 +1259,7 @@ ":pow10_helper", ":strings", "//absl/base:config", + "//absl/cleanup", "//absl/log", "//absl/numeric:int128", "//absl/random", @@ -1619,6 +1620,7 @@ ":strings", "//absl/base:config", "//absl/base:core_headers", + "//absl/cleanup", "//absl/container:flat_hash_map", "//absl/log", "//absl/status",
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index e6b5da3..ca07c3e 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt
@@ -470,6 +470,7 @@ COPTS ${ABSL_TEST_COPTS} DEPS + absl::cleanup absl::config absl::core_headers absl::int128 @@ -1314,6 +1315,7 @@ ${ABSL_TEST_COPTS} DEPS absl::base + absl::cleanup absl::config absl::flat_hash_map absl::generic_printer_internal
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index f2912d1..584a3c6 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc
@@ -71,12 +71,10 @@ using ::absl::cord_internal::CordRepSubstring; using ::absl::cord_internal::CordzUpdateTracker; using ::absl::cord_internal::InlineData; +using ::absl::cord_internal::kMaxBytesToCopy; using ::absl::cord_internal::kMaxFlatLength; using ::absl::cord_internal::kMinFlatLength; -using ::absl::cord_internal::kInlinedVectorSize; -using ::absl::cord_internal::kMaxBytesToCopy; - static void DumpNode(CordRep* absl_nonnull nonnull_rep, bool include_data, std::ostream* absl_nonnull os, int indent = 0); static bool VerifyNode(CordRep* absl_nonnull root,
diff --git a/absl/strings/cord.h b/absl/strings/cord.h index 22193b7..c5b2ec4 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h
@@ -100,6 +100,10 @@ #include "absl/types/optional.h" #include "absl/types/span.h" +namespace strings { +class CordReader; +} // namespace strings + namespace absl { ABSL_NAMESPACE_BEGIN class Cord; @@ -858,6 +862,7 @@ // public API call causing the cord to be created. explicit Cord(absl::string_view src, MethodIdentifier method); + friend class ::strings::CordReader; friend class CordTestPeer; friend bool operator==(const Cord& lhs, const Cord& rhs); friend bool operator==(const Cord& lhs, absl::string_view rhs); @@ -1119,11 +1124,6 @@ void CopyToArrayImpl(char* absl_nonnull dst) const; }; -ABSL_NAMESPACE_END -} // namespace absl - -namespace absl { -ABSL_NAMESPACE_BEGIN // allow a Cord to be logged extern std::ostream& operator<<(std::ostream& out, const Cord& cord);
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc index 56db8f4..d748ff0 100644 --- a/absl/strings/cord_test.cc +++ b/absl/strings/cord_test.cc
@@ -246,8 +246,6 @@ ABSL_NAMESPACE_END } // namespace absl - - // The CordTest fixture runs all tests with and without expected CRCs being set // on the subject Cords. class CordTest : public testing::TestWithParam<bool /*useCrc*/> {
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h index 6637561..27a8b9f 100644 --- a/absl/strings/internal/cord_internal.h +++ b/absl/strings/internal/cord_internal.h
@@ -70,17 +70,6 @@ } enum Constants { - // The inlined size to use with absl::InlinedVector. - // - // Note: The InlinedVectors in this file (and in cord.h) do not need to use - // the same value for their inlined size. The fact that they do is historical. - // It may be desirable for each to use a different inlined size optimized for - // that InlinedVector's usage. - // - // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for - // the inlined vector size (47 exists for backward compatibility). - kInlinedVectorSize = 47, - // Prefer copying blocks of at most this size, otherwise reference count. kMaxBytesToCopy = 511 };
diff --git a/absl/strings/internal/generic_printer.cc b/absl/strings/internal/generic_printer.cc index 16ca228..6535e1c 100644 --- a/absl/strings/internal/generic_printer.cc +++ b/absl/strings/internal/generic_printer.cc
@@ -22,6 +22,7 @@ #include "absl/base/config.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" +#include "absl/strings/numbers.h" #include "absl/strings/str_format.h" namespace absl { @@ -50,18 +51,28 @@ // ensure that values are precise, but rather that they are wide enough to // represent distinct values. go/c++17std/numeric.limits.members.html std::ostream& PrintPreciseFP(std::ostream& os, float v) { + // TryShorten formats with absl::StrFormat(), which is locale-independent and + // always emits a '.' radix. Use absl::SimpleAtof() for locale-independent + // parsing. return os << TryShorten(v, [](const char* buf) { - char* unused; - return std::strtof(buf, &unused); + float out = 0; + static_cast<void>(absl::SimpleAtof(buf, &out)); + return out; }) << "f"; } std::ostream& PrintPreciseFP(std::ostream& os, double v) { + // TryShorten formats with absl::StrFormat(), which is locale-independent and + // always emits a '.' radix. Use absl::SimpleAtod() for locale-independent + // parsing. return os << TryShorten(v, [](const char* buf) { - char* unused; - return std::strtod(buf, &unused); + double out = 0; + static_cast<void>(absl::SimpleAtod(buf, &out)); + return out; }); } std::ostream& PrintPreciseFP(std::ostream& os, long double v) { + // No locale-independent long double parser is available, so this path keeps + // std::strtold and remains locale-sensitive. return os << TryShorten(v, [](const char* buf) { char* unused; return std::strtold(buf, &unused);
diff --git a/absl/strings/internal/generic_printer_test.cc b/absl/strings/internal/generic_printer_test.cc index f5b737b..071bf76 100644 --- a/absl/strings/internal/generic_printer_test.cc +++ b/absl/strings/internal/generic_printer_test.cc
@@ -15,6 +15,7 @@ #include "absl/strings/internal/generic_printer.h" #include <array> +#include <clocale> #include <cstdint> #include <limits> #include <map> @@ -32,6 +33,7 @@ #include "gtest/gtest.h" #include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/cleanup/cleanup.h" #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/status/statusor.h" @@ -231,6 +233,32 @@ EXPECT_THAT(GenericPrintToString(0.L), EndsWith("L")); } +TEST(GenericPrinterTest, PreciseFPUnderCommaRadixLocale) { + // The values are formatted with locale-independent absl::StrFormat (a '.' + // radix), so the round-trip shortening must not depend on LC_NUMERIC. Under a + // comma-radix locale a locale-sensitive reader stops at the '.', which used + // to defeat the shortened output. + const char* saved = std::setlocale(LC_NUMERIC, nullptr); + std::string saved_locale = saved ? saved : "C"; + absl::Cleanup restore = [&] { + std::setlocale(LC_NUMERIC, saved_locale.c_str()); + }; + + bool set = false; + for (const char* name : {"de_DE.UTF-8", "fr_FR.UTF-8", "de_DE", "fr_FR"}) { + if (std::setlocale(LC_NUMERIC, name) != nullptr) { + set = true; + break; + } + } + if (!set) { + GTEST_SKIP() << "No comma-radix locale available on this system."; + } + + EXPECT_EQ("1.1f", GenericPrintToString(1.1f)); + EXPECT_EQ("1.1", GenericPrintToString(1.1)); +} + TEST(GenericPrinterTest, StreamableLvalue) { generic_logging_test::Streamable x{234}; EXPECT_EQ("Streamable{234}", GenericPrintToString(x));
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc index f0a8f00..479c07e 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc
@@ -21,6 +21,7 @@ #include <array> #include <cassert> #include <cfloat> // for DBL_DIG and FLT_DIG +#include <clocale> // for localeconv #include <cmath> // for HUGE_VAL #include <cstdint> #include <cstdio> @@ -448,6 +449,30 @@ ABSL_ASSERT(snprintf_result > 0 && snprintf_result < numbers_internal::kFastToBufferSize); } + + // snprintf() writes the radix character chosen by the global C locale's + // LC_NUMERIC category, so a process that has called setlocale() can end up + // with a separator other than '.' here. The rest of Abseil's float formatting + // (RoundTripFloatToBuffer, SixDigitsToBuffer) is locale- independent and + // SimpleAtod() only accepts '.', so rewrite the radix back to '.' to keep + // absl::HighPrecision(double) locale-independent and round-trippable through + // SimpleAtod(). + // TODO: b/526633099 - Once all supported compilers ship std::to_chars with + // floating-point support, use it here for inherent locale independence. + const char* radix = localeconv()->decimal_point; + // Skip an empty decimal_point (some minimal environments leave it ""), which + // would otherwise match the beginning of the buffer and corrupt it. + if (radix[0] != '\0' && std::strcmp(radix, ".") != 0) { + if (char* p = std::strstr(buffer, radix)) { + const size_t radix_len = std::strlen(radix); + *p = '.'; + // A multibyte radix (rare, but possible in some locales) leaves trailing + // bytes behind; collapse them so the output is a single '.'. + if (radix_len > 1) { + std::memmove(p + 1, p + radix_len, std::strlen(p + radix_len) + 1); + } + } + } return buffer; }
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index dd57a88..6f0cde8 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc
@@ -22,6 +22,7 @@ #include <cfloat> #include <cinttypes> #include <climits> +#include <clocale> #include <cmath> #include <cstddef> #include <cstdint> @@ -39,6 +40,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/cleanup/cleanup.h" #include "absl/log/log.h" #include "absl/numeric/int128.h" #include "absl/random/random.h" @@ -1717,6 +1719,37 @@ fenv_t fp_env_; }; +TEST(SimpleDtoa, HighPrecisionIsLocaleIndependent) { + // absl::HighPrecision(double) routes through RoundTripDoubleToBuffer(), which + // used to leak the global C locale's radix character (e.g. ',' under de_DE) + // into its output. HighPrecision() promises a value that SimpleAtod() reads + // back exactly, and SimpleAtod() only accepts '.', so the radix must stay '.' + // regardless of the active locale. + std::string old_locale = setlocale(LC_NUMERIC, nullptr); + auto restore_locale = + absl::MakeCleanup([&] { setlocale(LC_NUMERIC, old_locale.c_str()); }); + const char* comma_locales[] = {"de_DE.UTF-8", "de_DE", "fr_FR.UTF-8", "fr_FR", + "nl_NL.UTF-8"}; + bool changed = false; + for (const char* loc : comma_locales) { + if (setlocale(LC_NUMERIC, loc) != nullptr) { + changed = true; + break; + } + } + if (!changed) { + GTEST_SKIP() << "No comma-radix locale available on this system."; + } + EXPECT_EQ(absl::StrCat(absl::HighPrecision(0.5)), "0.5"); + EXPECT_EQ(absl::StrCat(absl::HighPrecision(-1.25)), "-1.25"); + EXPECT_EQ(absl::StrCat(absl::HighPrecision(3.14159265358979)), + "3.14159265358979"); + double parsed = 0; + EXPECT_TRUE( + absl::SimpleAtod(absl::StrCat(absl::HighPrecision(0.1)), &parsed)); + EXPECT_EQ(parsed, 0.1); +} + // Run the given runnable functor for "cases" test cases, chosen over the // available range of float. pi and e and 1/e are seeded, and then all // available integer powers of 2 and 10 are multiplied against them. In