diff --git a/MODULE.bazel b/MODULE.bazel index bc5f777..f8aed64 100644 --- a/MODULE.bazel +++ b/MODULE.bazel
@@ -25,7 +25,7 @@ dev_dependency = True) use_repo(cc_configure, "local_config_cc") -bazel_dep(name = "rules_cc", version = "0.2.0") +bazel_dep(name = "rules_cc", version = "0.2.9") bazel_dep(name = "bazel_skylib", version = "1.8.1") bazel_dep(name = "platforms", version = "1.0.0")
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index c51dd22..ade1a01 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel
@@ -603,6 +603,22 @@ ) cc_test( + name = "casts_test", + size = "small", + srcs = [ + "casts_test.cc", + ], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base", + ":core_headers", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( name = "no_destructor_test", srcs = ["no_destructor_test.cc"], copts = ABSL_TEST_COPTS,
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 2b27c3e..e257f99 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt
@@ -419,6 +419,19 @@ absl_cc_test( NAME + casts_test + SRCS + "casts_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::core_headers + GTest::gtest_main +) + +absl_cc_test( + NAME errno_saver_test SRCS "internal/errno_saver_test.cc"
diff --git a/absl/base/casts.h b/absl/base/casts.h index fc4ec6a..35f5f93 100644 --- a/absl/base/casts.h +++ b/absl/base/casts.h
@@ -33,6 +33,7 @@ #include <bit> // For std::bit_cast. #endif // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +#include "absl/base/attributes.h" #include "absl/base/macros.h" #include "absl/meta/type_traits.h" @@ -89,9 +90,26 @@ // // Such implicit cast chaining may be useful within template logic. template <typename To> -constexpr To implicit_cast(typename absl::type_identity_t<To> to) { +constexpr std::enable_if_t< + !type_traits_internal::IsView<std::enable_if_t< + !std::is_reference_v<To>, std::remove_cv_t<To>>>::value, + To> +implicit_cast(absl::type_identity_t<To> to) { return to; } +template <typename To> +constexpr std::enable_if_t< + type_traits_internal::IsView<std::enable_if_t<!std::is_reference_v<To>, + std::remove_cv_t<To>>>::value, + To> +implicit_cast(absl::type_identity_t<To> to ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return to; +} +template <typename To> +constexpr std::enable_if_t<std::is_reference_v<To>, To> implicit_cast( + absl::type_identity_t<To> to ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return std::forward<absl::type_identity_t<To>>(to); +} // bit_cast() //
diff --git a/absl/base/casts_test.cc b/absl/base/casts_test.cc new file mode 100644 index 0000000..25f92cc --- /dev/null +++ b/absl/base/casts_test.cc
@@ -0,0 +1,57 @@ +// 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. + +#include "absl/base/casts.h" + +#include <type_traits> +#include <utility> + +#include "gtest/gtest.h" + +namespace { + +struct Base { + explicit Base(int value) : x(value) {} + Base(const Base& other) = delete; + Base& operator=(const Base& other) = delete; + int x; +}; +struct Derived : Base { + explicit Derived(int value) : Base(value) {} +}; + +static_assert( + std::is_same_v< + decltype(absl::implicit_cast<Base&>(std::declval<Derived&>())), Base&>); +static_assert(std::is_same_v<decltype(absl::implicit_cast<const Base&>( + std::declval<Derived>())), + const Base&>); + +TEST(ImplicitCastTest, LValueReference) { + Derived derived(5); + EXPECT_EQ(&absl::implicit_cast<Base&>(derived), &derived); + EXPECT_EQ(&absl::implicit_cast<const Base&>(derived), &derived); +} + +TEST(ImplicitCastTest, RValueReference) { + Derived derived(5); + Base&& base = absl::implicit_cast<Base&&>(std::move(derived)); + EXPECT_EQ(&base, &derived); + + const Derived cderived(6); + const Base&& cbase = absl::implicit_cast<const Base&&>(std::move(cderived)); + EXPECT_EQ(&cbase, &cderived); +} + +} // namespace
diff --git a/absl/base/nullability.h b/absl/base/nullability.h index 2796a36..facc642 100644 --- a/absl/base/nullability.h +++ b/absl/base/nullability.h
@@ -81,7 +81,7 @@ // const Employee* absl_nonnull e; // // // A non-null pointer to a const nullable pointer to an `Employee`. -// Employee* absl_nullable const* absl_nonnull e = nullptr; +// Employee* absl_nullable const* absl_nonnull e; // // // A non-null function pointer. // void (*absl_nonnull func)(int, double);
diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc index 9c2feb3..6ac2e36 100644 --- a/absl/base/spinlock_test_common.cc +++ b/absl/base/spinlock_test_common.cc
@@ -271,16 +271,13 @@ } }; + int num_threads = base_internal::NumCPUs() * 2; SpinLock stack_cooperative_spinlock; SpinLock stack_noncooperative_spinlock(base_internal::SCHEDULE_KERNEL_ONLY); - Helper::DeadlockTest(&stack_cooperative_spinlock, - base_internal::NumCPUs() * 2); - Helper::DeadlockTest(&stack_noncooperative_spinlock, - base_internal::NumCPUs() * 2); - Helper::DeadlockTest(&static_cooperative_spinlock, - base_internal::NumCPUs() * 2); - Helper::DeadlockTest(&static_noncooperative_spinlock, - base_internal::NumCPUs() * 2); + Helper::DeadlockTest(&stack_cooperative_spinlock, num_threads); + Helper::DeadlockTest(&stack_noncooperative_spinlock, num_threads); + Helper::DeadlockTest(&static_cooperative_spinlock, num_threads); + Helper::DeadlockTest(&static_noncooperative_spinlock, num_threads); } TEST(SpinLockTest, IsCooperative) {
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index a1f4f24..7d6fd21 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h
@@ -462,7 +462,9 @@ // // Sets the number of slots in the `flat_hash_map` to the number needed to // accommodate at least `count` total elements without exceeding the current - // maximum load factor, and may rehash the container if needed. + // maximum load factor, and may rehash the container if needed. After this + // returns, it is guaranteed that `count - size()` elements can be inserted + // into the `flat_hash_map` without another rehash. using Base::reserve; // flat_hash_map::at()
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h index 2d25552..95e4533 100644 --- a/absl/container/flat_hash_set.h +++ b/absl/container/flat_hash_set.h
@@ -396,7 +396,9 @@ // // Sets the number of slots in the `flat_hash_set` to the number needed to // accommodate at least `count` total elements without exceeding the current - // maximum load factor, and may rehash the container if needed. + // maximum load factor, and may rehash the container if needed. After this + // returns, it is guaranteed that `count - size()` elements can be inserted + // into the `flat_hash_set` without another rehash. using Base::reserve; // flat_hash_set::contains()
diff --git a/absl/container/internal/raw_hash_set_probe_benchmark.cc b/absl/container/internal/raw_hash_set_probe_benchmark.cc index 458038e..2712160 100644 --- a/absl/container/internal/raw_hash_set_probe_benchmark.cc +++ b/absl/container/internal/raw_hash_set_probe_benchmark.cc
@@ -15,8 +15,14 @@ // Generates probe length statistics for many combinations of key types and key // distributions, all using the default hash function for swisstable. +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <limits> #include <memory> #include <regex> // NOLINT +#include <string> +#include <utility> #include <vector> #include "absl/base/no_destructor.h" @@ -227,24 +233,6 @@ return reinterpret_cast<Ptr<Align>*>(v); } -struct IntIdentity { - uint64_t i; - friend bool operator==(IntIdentity a, IntIdentity b) { return a.i == b.i; } - IntIdentity operator++(int) { return IntIdentity{i++}; } -}; - -template <int Align> -struct PtrIdentity { - explicit PtrIdentity(uintptr_t val = PointerForAlignment<Align>()) : i(val) {} - uintptr_t i; - friend bool operator==(PtrIdentity a, PtrIdentity b) { return a.i == b.i; } - PtrIdentity operator++(int) { - PtrIdentity p(i); - i += Align; - return p; - } -}; - enum class StringSize { kSmall, kMedium, kLarge, kExtraLarge }; constexpr char kStringFormat[] = "%s/name-%07d-of-9999999.txt"; @@ -270,20 +258,6 @@ } }; -template <> -struct DefaultHash<IntIdentity> { - struct type { - size_t operator()(IntIdentity t) const { return t.i; } - }; -}; - -template <int Align> -struct DefaultHash<PtrIdentity<Align>> { - struct type { - size_t operator()(PtrIdentity<Align> t) const { return t.i; } - }; -}; - template <class T> struct Sequential { T operator()() const { return current++; } @@ -389,20 +363,6 @@ } }; -template <class Dist> -struct Random<IntIdentity, Dist> { - IntIdentity operator()() const { - return IntIdentity{Random<uint64_t, Dist>{}()}; - } -}; - -template <class Dist, int Align> -struct Random<PtrIdentity<Align>, Dist> { - PtrIdentity<Align> operator()() const { - return PtrIdentity<Align>{Random<uintptr_t, Dist>{}() * Align}; - } -}; - template <class Dist, StringSize size> struct Random<String<size>, Dist> { std::string operator()() const { @@ -423,18 +383,12 @@ std::string Name(uint32_t*) { return "u32"; } std::string Name(uint64_t*) { return "u64"; } -std::string Name(IntIdentity*) { return "IntIdentity"; } template <int Align> std::string Name(Ptr<Align>**) { return absl::StrCat("Ptr", Align); } -template <int Align> -std::string Name(PtrIdentity<Align>*) { - return absl::StrCat("PtrIdentity", Align); -} - template <StringSize size> std::string Name(String<size>*) { switch (size) { @@ -558,15 +512,10 @@ std::vector<Result> results; RunForType<uint64_t>(results); - RunForType<IntIdentity>(results); RunForType<Ptr<8>*>(results); RunForType<Ptr<16>*>(results); RunForType<Ptr<32>*>(results); RunForType<Ptr<64>*>(results); - RunForType<PtrIdentity<8>>(results); - RunForType<PtrIdentity<16>>(results); - RunForType<PtrIdentity<32>>(results); - RunForType<PtrIdentity<64>>(results); RunForType<std::pair<uint32_t, uint32_t>>(results); RunForType<String<StringSize::kSmall>>(results); RunForType<String<StringSize::kMedium>>(results);
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index 46faa89..b24db36 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h
@@ -455,7 +455,9 @@ // // Sets the number of slots in the `node_hash_map` to the number needed to // accommodate at least `count` total elements without exceeding the current - // maximum load factor, and may rehash the container if needed. + // maximum load factor, and may rehash the container if needed. After this + // returns, it is guaranteed that `count - size()` elements can be inserted + // into the `node_hash_map` without another rehash. using Base::reserve; // node_hash_map::at()
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h index 9eef870..508248c 100644 --- a/absl/container/node_hash_set.h +++ b/absl/container/node_hash_set.h
@@ -390,7 +390,9 @@ // // Sets the number of slots in the `node_hash_set` to the number needed to // accommodate at least `count` total elements without exceeding the current - // maximum load factor, and may rehash the container if needed. + // maximum load factor, and may rehash the container if needed. After this + // returns, it is guaranteed that `count - size()` elements can be inserted + // into the `node_hash_set` without another rehash. using Base::reserve; // node_hash_set::contains()
diff --git a/absl/crc/internal/non_temporal_arm_intrinsics.h b/absl/crc/internal/non_temporal_arm_intrinsics.h index 9e5ccfc..a0d2f08 100644 --- a/absl/crc/internal/non_temporal_arm_intrinsics.h +++ b/absl/crc/internal/non_temporal_arm_intrinsics.h
@@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #ifndef ABSL_CRC_INTERNAL_NON_TEMPORAL_ARM_INTRINSICS_H_ #define ABSL_CRC_INTERNAL_NON_TEMPORAL_ARM_INTRINSICS_H_ @@ -21,7 +23,7 @@ #include <arm_neon.h> typedef int64x2_t __m128i; /* 128-bit vector containing integers */ -#define vreinterpretq_m128i_s32(x) vreinterpretq_s64_s32(x) +#define vreinterpretq_m128i_s64(x) (x) #define vreinterpretq_s64_m128i(x) (x) // Guarantees that every preceding store is globally visible before any @@ -44,7 +46,7 @@ // https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx static inline __attribute__((always_inline)) __m128i _mm_loadu_si128( const __m128i *p) { - return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *)p)); + return vreinterpretq_m128i_s64(vld1q_s64((const int64_t*)p)); } // Stores the data in a to the address p without polluting the caches. If the
diff --git a/absl/debugging/internal/stacktrace_emscripten-inl.inc b/absl/debugging/internal/stacktrace_emscripten-inl.inc index 2f39c70..9f87006 100644 --- a/absl/debugging/internal/stacktrace_emscripten-inl.inc +++ b/absl/debugging/internal/stacktrace_emscripten-inl.inc
@@ -52,13 +52,6 @@ // Waiting until static initializers run seems to be late enough. // This file is included into stacktrace.cc so this will only run once. ABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() { - // Check if we can even create stacktraces. If not, bail early and leave - // disable_stacktraces set as-is. - // clang-format off - if (!EM_ASM_INT({ return (typeof wasmOffsetConverter !== 'undefined'); })) { - return 0; - } - // clang-format on disable_stacktraces.store(false, std::memory_order_relaxed); return 0; }();
diff --git a/absl/debugging/symbolize_emscripten.inc b/absl/debugging/symbolize_emscripten.inc index f6da0ac..5756325 100644 --- a/absl/debugging/symbolize_emscripten.inc +++ b/absl/debugging/symbolize_emscripten.inc
@@ -26,33 +26,20 @@ extern "C" { const char* emscripten_pc_get_function(const void* pc); +void* emscripten_stack_snapshot(); } -// clang-format off -EM_JS(bool, HaveOffsetConverter, (), - { return typeof wasmOffsetConverter !== 'undefined'; }); -// clang-format on - namespace absl { ABSL_NAMESPACE_BEGIN -void InitializeSymbolizer(const char*) { - if (!HaveOffsetConverter()) { - ABSL_RAW_LOG(INFO, - "Symbolization unavailable. Rebuild with -sWASM=1 " - "and -sUSE_OFFSET_CONVERTER=1."); - } -} +void InitializeSymbolizer(const char*) {} bool Symbolize(const void* pc, char* out, int out_size) { - // Check if we have the offset converter necessary for pc_get_function. - // Without it, the program will abort(). - if (!HaveOffsetConverter()) { - return false; - } if (pc == nullptr || out_size <= 0) { return false; } + // Need to capture a snapshot first. + emscripten_stack_snapshot(); const char* func_name = emscripten_pc_get_function(pc); if (func_name == nullptr) { return false;
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc index 69b0a26..2dd5da5 100644 --- a/absl/debugging/symbolize_test.cc +++ b/absl/debugging/symbolize_test.cc
@@ -107,8 +107,6 @@ #endif #if !defined(__EMSCRIPTEN__) -static void *GetPCFromFnPtr(void *ptr) { return ptr; } - // Used below to hopefully inhibit some compiler/linker optimizations // that may remove kHpageTextPadding, kPadding0, and kPadding1 from // the binary. @@ -119,12 +117,6 @@ const char kHpageTextPadding[kHpageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE( .text) = ""; -#else -static void *GetPCFromFnPtr(void *ptr) { - return EM_ASM_PTR( - { return wasmOffsetConverter.convert(wasmTable.get($0).name, 0); }, ptr); -} - #endif // !defined(__EMSCRIPTEN__) static char try_symbolize_buffer[4096]; @@ -174,12 +166,10 @@ TEST(Symbolize, Cached) { // Compilers should give us pointers to them. - EXPECT_STREQ("nonstatic_func", - TrySymbolize(GetPCFromFnPtr((void *)(&nonstatic_func)))); + EXPECT_STREQ("nonstatic_func", TrySymbolize((void*)(&nonstatic_func))); // The name of an internal linkage symbol is not specified; allow either a // mangled or an unmangled name here. - const char *static_func_symbol = - TrySymbolize(GetPCFromFnPtr((void *)(&static_func))); + const char* static_func_symbol = TrySymbolize((void*)(&static_func)); EXPECT_TRUE(strcmp("static_func", static_func_symbol) == 0 || strcmp("static_func()", static_func_symbol) == 0); @@ -189,50 +179,38 @@ TEST(Symbolize, Truncation) { constexpr char kNonStaticFunc[] = "nonstatic_func"; EXPECT_STREQ("nonstatic_func", - TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)), + TrySymbolizeWithLimit((void*)(&nonstatic_func), strlen(kNonStaticFunc) + 1)); EXPECT_STREQ("nonstatic_...", - TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)), + TrySymbolizeWithLimit((void*)(&nonstatic_func), strlen(kNonStaticFunc) + 0)); EXPECT_STREQ("nonstatic...", - TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)), + TrySymbolizeWithLimit((void*)(&nonstatic_func), strlen(kNonStaticFunc) - 1)); - EXPECT_STREQ("n...", TrySymbolizeWithLimit( - GetPCFromFnPtr((void *)(&nonstatic_func)), 5)); - EXPECT_STREQ("...", TrySymbolizeWithLimit( - GetPCFromFnPtr((void *)(&nonstatic_func)), 4)); - EXPECT_STREQ("..", TrySymbolizeWithLimit( - GetPCFromFnPtr((void *)(&nonstatic_func)), 3)); - EXPECT_STREQ( - ".", TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)), 2)); - EXPECT_STREQ( - "", TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)), 1)); - EXPECT_EQ(nullptr, TrySymbolizeWithLimit( - GetPCFromFnPtr((void *)(&nonstatic_func)), 0)); + EXPECT_STREQ("n...", TrySymbolizeWithLimit((void*)(&nonstatic_func), 5)); + EXPECT_STREQ("...", TrySymbolizeWithLimit((void*)(&nonstatic_func), 4)); + EXPECT_STREQ("..", TrySymbolizeWithLimit((void*)(&nonstatic_func), 3)); + EXPECT_STREQ(".", TrySymbolizeWithLimit((void*)(&nonstatic_func), 2)); + EXPECT_STREQ("", TrySymbolizeWithLimit((void*)(&nonstatic_func), 1)); + EXPECT_EQ(nullptr, TrySymbolizeWithLimit((void*)(&nonstatic_func), 0)); } TEST(Symbolize, SymbolizeWithDemangling) { Foo::func(100); #ifdef __EMSCRIPTEN__ // Emscripten's online symbolizer is more precise with arguments. - EXPECT_STREQ("Foo::func(int)", - TrySymbolize(GetPCFromFnPtr((void *)(&Foo::func)))); + EXPECT_STREQ("Foo::func(int)", TrySymbolize((void*)(&Foo::func))); #else - EXPECT_STREQ("Foo::func()", - TrySymbolize(GetPCFromFnPtr((void *)(&Foo::func)))); + EXPECT_STREQ("Foo::func()", TrySymbolize((void*)(&Foo::func))); #endif } TEST(Symbolize, SymbolizeSplitTextSections) { - EXPECT_STREQ("unlikely_func()", - TrySymbolize(GetPCFromFnPtr((void *)(&unlikely_func)))); - EXPECT_STREQ("hot_func()", TrySymbolize(GetPCFromFnPtr((void *)(&hot_func)))); - EXPECT_STREQ("startup_func()", - TrySymbolize(GetPCFromFnPtr((void *)(&startup_func)))); - EXPECT_STREQ("exit_func()", - TrySymbolize(GetPCFromFnPtr((void *)(&exit_func)))); - EXPECT_STREQ("regular_func()", - TrySymbolize(GetPCFromFnPtr((void *)(®ular_func)))); + EXPECT_STREQ("unlikely_func()", TrySymbolize((void*)(&unlikely_func))); + EXPECT_STREQ("hot_func()", TrySymbolize((void*)(&hot_func))); + EXPECT_STREQ("startup_func()", TrySymbolize((void*)(&startup_func))); + EXPECT_STREQ("exit_func()", TrySymbolize((void*)(&exit_func))); + EXPECT_STREQ("regular_func()", TrySymbolize((void*)(®ular_func))); } // Tests that verify that Symbolize stack footprint is within some limit. @@ -630,5 +608,12 @@ #endif #endif +#if !defined(__EMSCRIPTEN__) + // All of these test cases rely on symbolizing function pointers. + // On most platforms, function pointers directly map to PC. + // In WebAssembly, function pointers are indices into the function table + // and there is no longer a mapping from function index back into the + // file offset for symbolization. return RUN_ALL_TESTS(); +#endif // !defined(__EMSCRIPTEN__) }
diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc index 589890f..eaeefb9 100644 --- a/absl/debugging/symbolize_win32.inc +++ b/absl/debugging/symbolize_win32.inc
@@ -15,7 +15,6 @@ // See "Retrieving Symbol Information by Address": // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx -#include <ntstatus.h> #include <windows.h> #include <winternl.h> @@ -58,10 +57,9 @@ // NTSTATUS (0xC0000004), which can happen when a module load occurs during // the SymInitialize call. In this case, we should try calling SymInitialize // again. + constexpr DWORD kStatusInfoLengthMismatch = DWORD{0xC0000004}; syminitialize_error = GetLastError(); - // Both NTSTATUS and DWORD are 32-bit numbers, which makes the cast safe. - if (syminitialize_error != - static_cast<DWORD>(STATUS_INFO_LENGTH_MISMATCH)) { + if (syminitialize_error != kStatusInfoLengthMismatch) { break; } }
diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index daef4e3..e2c4c82 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h
@@ -58,7 +58,7 @@ virtual ~FlagStateInterface(); // Restores the flag originated this object to the saved state. - virtual void Restore() const = 0; + virtual void Restore() && = 0; }; } // namespace flags_internal
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index b05e1bd..8e89425 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc
@@ -26,6 +26,7 @@ #include <memory> #include <string> #include <typeinfo> +#include <utility> #include <vector> #include "absl/base/attributes.h" @@ -139,8 +140,8 @@ friend class FlagImpl; // Restores the flag to the saved state. - void Restore() const override { - if (!flag_impl_.RestoreState(*this)) return; + void Restore() && override { + if (!std::move(flag_impl_).RestoreState(*this)) return; ABSL_INTERNAL_LOG(INFO, absl::StrCat("Restore saved value of ", flag_impl_.Name(),
diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index 845099e..fb64a65 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc
@@ -19,6 +19,7 @@ #include <atomic> #include <string> +#include <utility> #include "absl/base/config.h" #include "absl/base/no_destructor.h" @@ -320,9 +321,9 @@ } // Restores the saved flag states into the flag registry. - void RestoreToRegistry() { + void RestoreToRegistry() && { for (const auto& flag_state : backup_registry_) { - flag_state->Restore(); + std::move(*flag_state).Restore(); } } @@ -340,7 +341,7 @@ FlagSaver::~FlagSaver() { if (!impl_) return; - impl_->RestoreToRegistry(); + std::move(*impl_).RestoreToRegistry(); delete impl_; }
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index a928296..d0a0e55 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc
@@ -1242,6 +1242,9 @@ // Test for collisions in short strings if PrecombineLengthMix is low quality. TEST(PrecombineLengthMix, ShortStringCollision) { +#if defined(__wasm__) + GTEST_SKIP() << "Fails flakily on wasm due to no ASLR and 32-bit size_t."; +#endif std::string s1 = "00"; std::string s2 = "000"; constexpr char kMinChar = 0;
diff --git a/absl/log/internal/log_impl.h b/absl/log/internal/log_impl.h index a67f2f3..2fe73de 100644 --- a/absl/log/internal/log_impl.h +++ b/absl/log/internal/log_impl.h
@@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #ifndef ABSL_LOG_INTERNAL_LOG_IMPL_H_ #define ABSL_LOG_INTERNAL_LOG_IMPL_H_ @@ -23,260 +25,256 @@ // ABSL_LOG() #define ABSL_LOG_INTERNAL_LOG_IMPL(severity) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() // ABSL_PLOG() -#define ABSL_LOG_INTERNAL_PLOG_IMPL(severity) \ - ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ +#define ABSL_LOG_INTERNAL_PLOG_IMPL(severity) \ + ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() // ABSL_DLOG() #ifndef NDEBUG #define ABSL_LOG_INTERNAL_DLOG_IMPL(severity) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #else #define ABSL_LOG_INTERNAL_DLOG_IMPL(severity) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #endif // The `switch` ensures that this expansion is the beginning of a statement (as // opposed to an expression). The use of both `case 0` and `default` is to // suppress a compiler warning. -#define ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level) \ - switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ - case 0: \ - default: \ - ABSL_LOG_INTERNAL_LOG_IF_IMPL( \ - _INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ - .WithVerbosity(absl_logging_internal_verbose_level) +#define ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level) \ + switch (const int absl_log_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_LOG_IF_IMPL( \ + _INFO, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level)) \ + .WithVerbosity(absl_log_internal_verbose_level) #ifndef NDEBUG -#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \ - switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ - case 0: \ - default: \ - ABSL_LOG_INTERNAL_DLOG_IF_IMPL( \ - _INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ - .WithVerbosity(absl_logging_internal_verbose_level) +#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \ + switch (const int absl_log_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_DLOG_IF_IMPL( \ + _INFO, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level)) \ + .WithVerbosity(absl_log_internal_verbose_level) #else -#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \ - switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ - case 0: \ - default: \ - ABSL_LOG_INTERNAL_DLOG_IF_IMPL( \ - _INFO, false && ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ - .WithVerbosity(absl_logging_internal_verbose_level) +#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \ + switch (const int absl_log_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_DLOG_IF_IMPL( \ + _INFO, false && ABSL_VLOG_IS_ON(absl_log_internal_verbose_level)) \ + .WithVerbosity(absl_log_internal_verbose_level) #endif #define ABSL_LOG_INTERNAL_LOG_IF_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_PLOG_IF_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() #ifndef NDEBUG #define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #else #define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false && (condition)) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #endif // ABSL_LOG_EVERY_N #define ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(severity, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() // ABSL_LOG_FIRST_N #define ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(severity, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() // ABSL_LOG_EVERY_POW_2 #define ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(severity) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() // ABSL_LOG_EVERY_N_SEC #define ABSL_LOG_INTERNAL_LOG_EVERY_N_SEC_IMPL(severity, n_seconds) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryNSec, n_seconds) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_PLOG_EVERY_N_IMPL(severity, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() #define ABSL_LOG_INTERNAL_PLOG_FIRST_N_IMPL(severity, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() #define ABSL_LOG_INTERNAL_PLOG_EVERY_POW_2_IMPL(severity) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() #define ABSL_LOG_INTERNAL_PLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryNSec, n_seconds) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() #ifndef NDEBUG #define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \ - (EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + (EveryN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \ - (FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + (FirstN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \ - (EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + (EveryPow2) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \ - (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + (EveryNSec, n_seconds) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #else // def NDEBUG #define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \ - (EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + (EveryN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \ - (FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + (FirstN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \ - (EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + (EveryPow2) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \ - (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + (EveryNSec, n_seconds) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #endif // def NDEBUG -#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(verbose_level, n) \ - switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ - case 0: \ - default: \ - ABSL_LOG_INTERNAL_CONDITION_INFO( \ - STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ - (EveryN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ - absl_logging_internal_verbose_level) +#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(verbose_level, n) \ + switch (const int absl_log_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level)) \ + (EveryN, n) ABSL_LOG_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_log_internal_verbose_level) -#define ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(verbose_level, n) \ - switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ - case 0: \ - default: \ - ABSL_LOG_INTERNAL_CONDITION_INFO( \ - STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ - (FirstN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ - absl_logging_internal_verbose_level) +#define ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(verbose_level, n) \ + switch (const int absl_log_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level)) \ + (FirstN, n) ABSL_LOG_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_log_internal_verbose_level) -#define ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(verbose_level) \ - switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ - case 0: \ - default: \ - ABSL_LOG_INTERNAL_CONDITION_INFO( \ - STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ - (EveryPow2) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ - absl_logging_internal_verbose_level) +#define ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(verbose_level) \ + switch (const int absl_log_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level)) \ + (EveryPow2) ABSL_LOG_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_log_internal_verbose_level) -#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(verbose_level, n_seconds) \ - switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ - case 0: \ - default: \ - ABSL_LOG_INTERNAL_CONDITION_INFO( \ - STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ - (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream() \ - .WithVerbosity(absl_logging_internal_verbose_level) +#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(verbose_level, n_seconds) \ + switch (const int absl_log_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level)) \ + (EveryNSec, n_seconds) ABSL_LOG_INTERNAL_LOG_INFO.InternalStream() \ + .WithVerbosity(absl_log_internal_verbose_level) #define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_LOG_IF_FIRST_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_LOG_IF_EVERY_POW_2_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() -#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_SEC_IMPL(severity, condition, \ - n_seconds) \ - ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \ - n_seconds) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() +#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_SEC_IMPL(severity, condition, \ + n_seconds) \ + ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)( \ + EveryNSec, n_seconds) ABSL_LOG_INTERNAL_LOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() #define ABSL_LOG_INTERNAL_PLOG_IF_FIRST_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() #define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_POW_2_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ + ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ .WithPerror() -#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \ - n_seconds) \ - ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \ - n_seconds) \ - ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \ - .WithPerror() +#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \ + n_seconds) \ + ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)( \ + EveryNSec, n_seconds) ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \ + .WithPerror() #ifndef NDEBUG #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \ n_seconds) \ - ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \ - n_seconds) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)( \ + EveryNSec, n_seconds) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #else // def NDEBUG #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \ - EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + EveryN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \ - FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + FirstN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \ - EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + EveryPow2) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \ n_seconds) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \ - EveryNSec, n_seconds) \ - ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() + EveryNSec, n_seconds) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream() #endif // def NDEBUG #endif // ABSL_LOG_INTERNAL_LOG_IMPL_H_
diff --git a/absl/log/internal/strip.h b/absl/log/internal/strip.h index 60ef878..6fd857b 100644 --- a/absl/log/internal/strip.h +++ b/absl/log/internal/strip.h
@@ -26,57 +26,56 @@ #include "absl/log/internal/log_message.h" #include "absl/log/internal/nullstream.h" -// `ABSL_LOGGING_INTERNAL_LOG_*` evaluates to a temporary `LogMessage` object or +// `ABSL_LOG_INTERNAL_LOG_*` evaluates to a temporary `LogMessage` object or // to a related object with a compatible API but different behavior. This set // of defines comes in three flavors: vanilla, plus two variants that strip some // logging in subtly different ways for subtly different reasons (see below). #if defined(STRIP_LOG) && STRIP_LOG -#define ABSL_LOGGING_INTERNAL_LOG_INFO ::absl::log_internal::NullStream() -#define ABSL_LOGGING_INTERNAL_LOG_WARNING ::absl::log_internal::NullStream() -#define ABSL_LOGGING_INTERNAL_LOG_ERROR ::absl::log_internal::NullStream() -#define ABSL_LOGGING_INTERNAL_LOG_FATAL ::absl::log_internal::NullStreamFatal() -#define ABSL_LOGGING_INTERNAL_LOG_QFATAL ::absl::log_internal::NullStreamFatal() -#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \ +#define ABSL_LOG_INTERNAL_LOG_INFO ::absl::log_internal::NullStream() +#define ABSL_LOG_INTERNAL_LOG_WARNING ::absl::log_internal::NullStream() +#define ABSL_LOG_INTERNAL_LOG_ERROR ::absl::log_internal::NullStream() +#define ABSL_LOG_INTERNAL_LOG_FATAL ::absl::log_internal::NullStreamFatal() +#define ABSL_LOG_INTERNAL_LOG_QFATAL ::absl::log_internal::NullStreamFatal() +#define ABSL_LOG_INTERNAL_LOG_DFATAL \ ::absl::log_internal::NullStreamMaybeFatal(::absl::kLogDebugFatal) -#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \ +#define ABSL_LOG_INTERNAL_LOG_LEVEL(severity) \ ::absl::log_internal::NullStreamMaybeFatal(absl_log_internal_severity) // Fatal `DLOG`s expand a little differently to avoid being `[[noreturn]]`. -#define ABSL_LOGGING_INTERNAL_DLOG_FATAL \ +#define ABSL_LOG_INTERNAL_DLOG_FATAL \ ::absl::log_internal::NullStreamMaybeFatal(::absl::LogSeverity::kFatal) -#define ABSL_LOGGING_INTERNAL_DLOG_QFATAL \ +#define ABSL_LOG_INTERNAL_DLOG_QFATAL \ ::absl::log_internal::NullStreamMaybeFatal(::absl::LogSeverity::kFatal) -#define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOGGING_INTERNAL_LOG_FATAL -#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \ - ABSL_LOGGING_INTERNAL_LOG_QFATAL +#define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOG_INTERNAL_LOG_FATAL +#define ABSL_LOG_INTERNAL_QCHECK(failure_message) ABSL_LOG_INTERNAL_LOG_QFATAL #else // !defined(STRIP_LOG) || !STRIP_LOG -#define ABSL_LOGGING_INTERNAL_LOG_INFO \ - ::absl::log_internal::LogMessage( \ +#define ABSL_LOG_INTERNAL_LOG_INFO \ + ::absl::log_internal::LogMessage( \ __FILE__, __LINE__, ::absl::log_internal::LogMessage::InfoTag{}) -#define ABSL_LOGGING_INTERNAL_LOG_WARNING \ - ::absl::log_internal::LogMessage( \ +#define ABSL_LOG_INTERNAL_LOG_WARNING \ + ::absl::log_internal::LogMessage( \ __FILE__, __LINE__, ::absl::log_internal::LogMessage::WarningTag{}) -#define ABSL_LOGGING_INTERNAL_LOG_ERROR \ - ::absl::log_internal::LogMessage( \ +#define ABSL_LOG_INTERNAL_LOG_ERROR \ + ::absl::log_internal::LogMessage( \ __FILE__, __LINE__, ::absl::log_internal::LogMessage::ErrorTag{}) -#define ABSL_LOGGING_INTERNAL_LOG_FATAL \ +#define ABSL_LOG_INTERNAL_LOG_FATAL \ ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__) -#define ABSL_LOGGING_INTERNAL_LOG_QFATAL \ +#define ABSL_LOG_INTERNAL_LOG_QFATAL \ ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__) -#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \ +#define ABSL_LOG_INTERNAL_LOG_DFATAL \ ::absl::log_internal::LogMessage(__FILE__, __LINE__, ::absl::kLogDebugFatal) -#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \ +#define ABSL_LOG_INTERNAL_LOG_LEVEL(severity) \ ::absl::log_internal::LogMessage(__FILE__, __LINE__, \ absl_log_internal_severity) // Fatal `DLOG`s expand a little differently to avoid being `[[noreturn]]`. -#define ABSL_LOGGING_INTERNAL_DLOG_FATAL \ +#define ABSL_LOG_INTERNAL_DLOG_FATAL \ ::absl::log_internal::LogMessageDebugFatal(__FILE__, __LINE__) -#define ABSL_LOGGING_INTERNAL_DLOG_QFATAL \ +#define ABSL_LOG_INTERNAL_DLOG_QFATAL \ ::absl::log_internal::LogMessageQuietlyDebugFatal(__FILE__, __LINE__) // These special cases dispatch to special-case constructors that allow us to @@ -89,12 +88,12 @@ #endif // !defined(STRIP_LOG) || !STRIP_LOG // This part of a non-fatal `DLOG`s expands the same as `LOG`. -#define ABSL_LOGGING_INTERNAL_DLOG_INFO ABSL_LOGGING_INTERNAL_LOG_INFO -#define ABSL_LOGGING_INTERNAL_DLOG_WARNING ABSL_LOGGING_INTERNAL_LOG_WARNING -#define ABSL_LOGGING_INTERNAL_DLOG_ERROR ABSL_LOGGING_INTERNAL_LOG_ERROR -#define ABSL_LOGGING_INTERNAL_DLOG_DFATAL ABSL_LOGGING_INTERNAL_LOG_DFATAL -#define ABSL_LOGGING_INTERNAL_DLOG_LEVEL ABSL_LOGGING_INTERNAL_LOG_LEVEL +#define ABSL_LOG_INTERNAL_DLOG_INFO ABSL_LOG_INTERNAL_LOG_INFO +#define ABSL_LOG_INTERNAL_DLOG_WARNING ABSL_LOG_INTERNAL_LOG_WARNING +#define ABSL_LOG_INTERNAL_DLOG_ERROR ABSL_LOG_INTERNAL_LOG_ERROR +#define ABSL_LOG_INTERNAL_DLOG_DFATAL ABSL_LOG_INTERNAL_LOG_DFATAL +#define ABSL_LOG_INTERNAL_DLOG_LEVEL ABSL_LOG_INTERNAL_LOG_LEVEL -#define ABSL_LOGGING_INTERNAL_LOG_DO_NOT_SUBMIT ABSL_LOGGING_INTERNAL_LOG_ERROR +#define ABSL_LOG_INTERNAL_LOG_DO_NOT_SUBMIT ABSL_LOG_INTERNAL_LOG_ERROR #endif // ABSL_LOG_INTERNAL_STRIP_H_
diff --git a/absl/log/internal/vlog_config.cc b/absl/log/internal/vlog_config.cc index f70069f..97665a5 100644 --- a/absl/log/internal/vlog_config.cc +++ b/absl/log/internal/vlog_config.cc
@@ -159,10 +159,10 @@ // If there are any slashes in the pattern, try to match the full // name. if (FNMatch(info.module_pattern, stem)) { - return info.vlog_level == kUseFlag ? current_global_v : info.vlog_level; + return info.vlog_level; } } else if (FNMatch(info.module_pattern, stem_basename)) { - return info.vlog_level == kUseFlag ? current_global_v : info.vlog_level; + return info.vlog_level; } }
diff --git a/absl/log/internal/vlog_config.h b/absl/log/internal/vlog_config.h index 84e817a..da020f8 100644 --- a/absl/log/internal/vlog_config.h +++ b/absl/log/internal/vlog_config.h
@@ -48,7 +48,6 @@ int RegisterAndInitialize(VLogSite* absl_nonnull v); void UpdateVLogSites(); -constexpr int kUseFlag = (std::numeric_limits<int16_t>::min)(); // Represents a unique callsite for a `VLOG()` or `VLOG_IS_ON()` call. //
diff --git a/absl/profiling/hashtable.cc b/absl/profiling/hashtable.cc index bfec0d5..407c6b4 100644 --- a/absl/profiling/hashtable.cc +++ b/absl/profiling/hashtable.cc
@@ -42,6 +42,8 @@ namespace debugging_internal { +static void DroppedHashtableSample() {} + StatusOr<std::string> MarshalHashtableProfile( container_internal::HashtablezSampler& sampler, Time now) { static constexpr absl::string_view kDropFrames = @@ -111,10 +113,18 @@ MakeSpan(info.stack, info.depth), labels); }); - // TODO(b/262310142): Make this more structured data. - StringId comment_id = - builder.InternString(StrCat("dropped_samples: ", dropped)); - builder.set_comment_id(comment_id); + if (dropped > 0) { + // If we dropped samples, we don't have information for them, including + // their sizes. The non-zero weight allows it to be noticed in the profile + // and examined more closely. + // + // We compensate for the fixup done by AddSample by adjusting the address + // here. + const void* kFakeStack[] = { + absl::bit_cast<void*>( + reinterpret_cast<uintptr_t>(&DroppedHashtableSample)+1)}; + builder.AddSample(static_cast<int64_t>(dropped), kFakeStack, {}); + } builder.AddCurrentMappings(); return std::move(builder).Emit(); }
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h index 45b90f3..35a9f9b 100644 --- a/absl/status/internal/status_internal.h +++ b/absl/status/internal/status_internal.h
@@ -38,9 +38,11 @@ // TODO(b/176172494): ABSL_MUST_USE_RESULT should expand to the more strict // [[nodiscard]]. For now, just use [[nodiscard]] directly when it is available. #if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) -class [[nodiscard]] ABSL_ATTRIBUTE_TRIVIAL_ABI Status; +class [[nodiscard]] ABSL_ATTRIBUTE_TRIVIAL_ABI + Status; #else -class ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_TRIVIAL_ABI Status; +class ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_TRIVIAL_ABI + Status; #endif ABSL_NAMESPACE_END } // namespace absl
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h index b664104..8a4e2f5 100644 --- a/absl/status/internal/statusor_internal.h +++ b/absl/status/internal/statusor_internal.h
@@ -29,7 +29,8 @@ ABSL_NAMESPACE_BEGIN template <typename T> -class ABSL_MUST_USE_RESULT StatusOr; +class ABSL_MUST_USE_RESULT + StatusOr; namespace internal_statusor {
diff --git a/absl/status/statusor.h b/absl/status/statusor.h index 56309af..52294ee 100644 --- a/absl/status/statusor.h +++ b/absl/status/statusor.h
@@ -45,8 +45,8 @@ #include <utility> #include "absl/base/attributes.h" -#include "absl/base/nullability.h" #include "absl/base/call_once.h" +#include "absl/base/nullability.h" #include "absl/meta/type_traits.h" #include "absl/status/internal/statusor_internal.h" #include "absl/status/status.h"
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index bcf0c38..1ecc069 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel
@@ -102,6 +102,7 @@ deps = [ ":charset", ":internal", + ":resize_and_overwrite", ":string_view", "//absl/base", "//absl/base:config", @@ -150,6 +151,7 @@ deps = [ "//absl/base:config", "//absl/base:core_headers", + "//absl/base:dynamic_annotations", "//absl/base:throw_delegate", ], ) @@ -161,6 +163,7 @@ linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":resize_and_overwrite", + "//absl/base:dynamic_annotations", "//absl/log:absl_check", "@googletest//:gtest", "@googletest//:gtest_main", @@ -627,6 +630,7 @@ ":cordz_update_scope", ":cordz_update_tracker", ":internal", + ":resize_and_overwrite", ":strings", "//absl/base:config", "//absl/base:core_headers", @@ -679,6 +683,7 @@ "//absl/base", "//absl/base:config", "//absl/base:core_headers", + "//absl/base:no_destructor", "//absl/base:raw_logging_internal", "//absl/container:inlined_vector", "//absl/debugging:stacktrace",
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 764d5cd..da44ef7 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt
@@ -77,6 +77,7 @@ DEPS absl::string_view absl::strings_internal + absl::strings_resize_and_overwrite absl::base absl::bits absl::charset @@ -151,6 +152,7 @@ DEPS absl::config absl::core_headers + absl::dynamic_annotations absl::throw_delegate ) @@ -164,6 +166,7 @@ DEPS absl::strings_resize_and_overwrite absl::absl_check + absl::dynamic_annotations GTest::gmock_main ) @@ -871,6 +874,7 @@ absl::cordz_statistics absl::cordz_update_tracker absl::core_headers + absl::no_destructor absl::inlined_vector absl::span absl::raw_logging_internal @@ -1026,6 +1030,7 @@ absl::raw_logging_internal absl::span absl::strings + absl::strings_resize_and_overwrite absl::type_traits absl::weakly_mixed_integer PUBLIC
diff --git a/absl/strings/ascii.h b/absl/strings/ascii.h index ca0747e..6a75b1f 100644 --- a/absl/strings/ascii.h +++ b/absl/strings/ascii.h
@@ -61,6 +61,7 @@ #include "absl/base/config.h" #include "absl/base/nullability.h" #include "absl/strings/internal/resize_uninitialized.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/string_view.h" namespace absl { @@ -190,8 +191,10 @@ // Creates a lowercase string from a given absl::string_view. [[nodiscard]] inline std::string AsciiStrToLower(absl::string_view s) { std::string result; - strings_internal::STLStringResizeUninitialized(&result, s.size()); - ascii_internal::AsciiStrToLower(&result[0], s.data(), s.size()); + StringResizeAndOverwrite(result, s.size(), [s](char* buf, size_t buf_size) { + ascii_internal::AsciiStrToLower(buf, s.data(), s.size()); + return buf_size; + }); return result; } @@ -219,8 +222,10 @@ // Creates an uppercase string from a given absl::string_view. [[nodiscard]] inline std::string AsciiStrToUpper(absl::string_view s) { std::string result; - strings_internal::STLStringResizeUninitialized(&result, s.size()); - ascii_internal::AsciiStrToUpper(&result[0], s.data(), s.size()); + StringResizeAndOverwrite(result, s.size(), [s](char* buf, size_t buf_size) { + ascii_internal::AsciiStrToUpper(buf, s.data(), s.size()); + return buf_size; + }); return result; }
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index a7e0994..91fcf91 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc
@@ -52,6 +52,7 @@ #include "absl/strings/internal/cordz_update_tracker.h" #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/match.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/strings/strip.h" @@ -1055,8 +1056,11 @@ if (!src.contents_.is_tree()) { src.contents_.CopyTo(dst); } else { - absl::strings_internal::STLStringResizeUninitialized(dst, src.size()); - src.CopyToArraySlowPath(&(*dst)[0]); + StringResizeAndOverwrite(*dst, src.size(), + [&src](char* buf, size_t buf_size) { + src.CopyToArraySlowPath(buf); + return buf_size; + }); } }
diff --git a/absl/strings/internal/cordz_info.cc b/absl/strings/internal/cordz_info.cc index a916c0c..38fb473 100644 --- a/absl/strings/internal/cordz_info.cc +++ b/absl/strings/internal/cordz_info.cc
@@ -17,7 +17,8 @@ #include <cstdint> #include "absl/base/config.h" -#include "absl/base/internal/spinlock.h" +#include "absl/base/const_init.h" +#include "absl/base/no_destructor.h" #include "absl/container/inlined_vector.h" #include "absl/debugging/stacktrace.h" #include "absl/strings/internal/cord_internal.h" @@ -34,8 +35,6 @@ ABSL_NAMESPACE_BEGIN namespace cord_internal { -ABSL_CONST_INIT CordzInfo::List CordzInfo::global_list_{absl::kConstInit}; - namespace { // CordRepAnalyzer performs the analysis of a cord. @@ -221,24 +220,32 @@ } // namespace +CordzInfo::List* CordzInfo::GlobalList() { + static absl::NoDestructor<CordzInfo::List> list; + return list.get(); +} + CordzInfo* CordzInfo::Head(const CordzSnapshot& snapshot) { ABSL_ASSERT(snapshot.is_snapshot()); - // We can do an 'unsafe' load of 'head', as we are guaranteed that the - // instance it points to is kept alive by the provided CordzSnapshot, so we - // can simply return the current value using an acquire load. + // We obtain the lock here as we must synchronize the first call into the list + // with any concurrent 'Untrack()` operation to avoid any read in the list to + // reorder before the observation of the thread 'untracking a cord' of the + // delete queue being empty or not. After this all next observations are safe + // as we have established all subsequent untracks will be queued for delete. // We do enforce in DEBUG builds that the 'head' value is present in the - // delete queue: ODR violations may lead to 'snapshot' and 'global_list_' + // delete queue: ODR violations may lead to 'snapshot' and 'global_list' // being in different libraries / modules. - CordzInfo* head = global_list_.head.load(std::memory_order_acquire); - ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(head)); - return head; + auto global_list = GlobalList(); + absl::MutexLock l(global_list->mutex); + ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(global_list->head)); + return global_list->head; } CordzInfo* CordzInfo::Next(const CordzSnapshot& snapshot) const { ABSL_ASSERT(snapshot.is_snapshot()); - // Similar to the 'Head()' function, we do not need a mutex here. + // We do not need a lock here. See also comments in Head(). CordzInfo* next = ci_next_.load(std::memory_order_acquire); ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(this)); ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(next)); @@ -327,22 +334,21 @@ } void CordzInfo::Track() { - SpinLockHolder l(list_->mutex); - - CordzInfo* const head = list_->head.load(std::memory_order_acquire); + absl::MutexLock l(list_->mutex); + CordzInfo* const head = list_->head; if (head != nullptr) { head->ci_prev_.store(this, std::memory_order_release); } ci_next_.store(head, std::memory_order_release); - list_->head.store(this, std::memory_order_release); + list_->head = this; } void CordzInfo::Untrack() { ODRCheck(); { - SpinLockHolder l(list_->mutex); + absl::MutexLock l(list_->mutex); - CordzInfo* const head = list_->head.load(std::memory_order_acquire); + CordzInfo* const head = list_->head; CordzInfo* const next = ci_next_.load(std::memory_order_acquire); CordzInfo* const prev = ci_prev_.load(std::memory_order_acquire); @@ -356,7 +362,7 @@ prev->ci_next_.store(next, std::memory_order_release); } else { ABSL_ASSERT(head == this); - list_->head.store(next, std::memory_order_release); + list_->head = next; } }
diff --git a/absl/strings/internal/cordz_info.h b/absl/strings/internal/cordz_info.h index 578aa59..ccbe414 100644 --- a/absl/strings/internal/cordz_info.h +++ b/absl/strings/internal/cordz_info.h
@@ -20,8 +20,8 @@ #include <functional> #include "absl/base/config.h" +#include "absl/base/const_init.h" #include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/spinlock.h" #include "absl/base/thread_annotations.h" #include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cordz_functions.h" @@ -121,12 +121,10 @@ CordzInfo& operator=(const CordzInfo&) = delete; // Retrieves the oldest existing CordzInfo. - static CordzInfo* Head(const CordzSnapshot& snapshot) - ABSL_NO_THREAD_SAFETY_ANALYSIS; + static CordzInfo* Head(const CordzSnapshot& snapshot); // Retrieves the next oldest existing CordzInfo older than 'this' instance. - CordzInfo* Next(const CordzSnapshot& snapshot) const - ABSL_NO_THREAD_SAFETY_ANALYSIS; + CordzInfo* Next(const CordzSnapshot& snapshot) const; // Locks this instance for the update identified by `method`. // Increases the count for `method` in `update_tracker`. @@ -185,18 +183,15 @@ int64_t sampling_stride() const { return sampling_stride_; } private: - using SpinLock = absl::base_internal::SpinLock; - using SpinLockHolder = ::absl::base_internal::SpinLockHolder; - // Global cordz info list. CordzInfo stores a pointer to the global list // instance to harden against ODR violations. struct List { - constexpr explicit List(absl::ConstInitType) {} - - SpinLock mutex; - std::atomic<CordzInfo*> head ABSL_GUARDED_BY(mutex){nullptr}; + absl::Mutex mutex; + CordzInfo* head ABSL_GUARDED_BY(mutex){nullptr}; }; + static List* GlobalList(); + static constexpr size_t kMaxStackDepth = 64; explicit CordzInfo(CordRep* rep, const CordzInfo* src, @@ -221,7 +216,7 @@ void ODRCheck() const { #ifndef NDEBUG - ABSL_RAW_CHECK(list_ == &global_list_, "ODR violation in Cord"); + ABSL_RAW_CHECK(list_ == GlobalList(), "ODR violation in Cord"); #endif } @@ -231,12 +226,11 @@ static void MaybeTrackCordImpl(InlineData& cord, const InlineData& src, MethodIdentifier method); - ABSL_CONST_INIT static List global_list_; - List* const list_ = &global_list_; + List* const list_ = GlobalList(); // ci_prev_ and ci_next_ require the global list mutex to be held. // Unfortunately we can't use thread annotations such that the thread safety - // analysis understands that list_ and global_list_ are one and the same. + // analysis understands that list_ and GlobalList() are one and the same. std::atomic<CordzInfo*> ci_prev_{nullptr}; std::atomic<CordzInfo*> ci_next_{nullptr};
diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h index 31fcf6d..5f9df0e 100644 --- a/absl/strings/internal/str_join_internal.h +++ b/absl/strings/internal/str_join_internal.h
@@ -47,6 +47,7 @@ #include "absl/base/internal/raw_logging.h" #include "absl/strings/internal/ostringstream.h" #include "absl/strings/internal/resize_uninitialized.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" @@ -249,23 +250,25 @@ constexpr uint64_t kMaxSize = uint64_t{(std::numeric_limits<size_t>::max)()}; ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow"); - STLStringResizeUninitialized(&result, static_cast<size_t>(result_size)); - // Joins strings - char* result_buf = &*result.begin(); - - memcpy(result_buf, start_value.data(), start_value.size()); - result_buf += start_value.size(); - for (Iterator it = start; ++it != end;) { - memcpy(result_buf, s.data(), s.size()); - result_buf += s.size(); - auto&& value = *it; - memcpy(result_buf, value.data(), value.size()); - result_buf += value.size(); - } + StringResizeAndOverwrite( + result, static_cast<size_t>(result_size), + [&start, &end, &start_value, s](char* result_buf, + size_t result_buf_size) { + // Joins strings + memcpy(result_buf, start_value.data(), start_value.size()); + result_buf += start_value.size(); + for (Iterator it = start; ++it != end;) { + memcpy(result_buf, s.data(), s.size()); + result_buf += s.size(); + auto&& value = *it; + memcpy(result_buf, value.data(), value.size()); + result_buf += value.size(); + } + return result_buf_size; + }); } } - return result; }
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc index a83fd2c..01caf78 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc
@@ -81,11 +81,15 @@ bool SimpleAtod(absl::string_view str, double* absl_nonnull out) { *out = 0.0; str = StripAsciiWhitespace(str); + if (str.empty()) { + // absl::from_chars doesn't accept empty strings. + return false; + } // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one // is present, skip it, while avoiding accepting "+-0" as valid. - if (!str.empty() && str[0] == '+') { + if (str[0] == '+') { str.remove_prefix(1); - if (!str.empty() && str[0] == '-') { + if (str.empty() || str[0] == '-') { return false; } }
diff --git a/absl/strings/resize_and_overwrite.h b/absl/strings/resize_and_overwrite.h index 7d07640..b3bd06e 100644 --- a/absl/strings/resize_and_overwrite.h +++ b/absl/strings/resize_and_overwrite.h
@@ -52,6 +52,7 @@ #include <utility> #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" @@ -125,12 +126,18 @@ if (ABSL_PREDICT_FALSE(n > str.max_size())) { absl::base_internal::ThrowStdLengthError("absl::StringResizeAndOverwrite"); } - // The callback is allowed to write an arbitrary value to buf+n, but it is - // undefined behavior to write anything other than T::value_type{} to - // str.data()[n]. Therefore the initial resize uses an extra byte. - str.resize(n + 1); +#ifdef ABSL_HAVE_MEMORY_SANITIZER + auto old_size = str.size(); +#endif + str.resize(n); +#ifdef ABSL_HAVE_MEMORY_SANITIZER + if (old_size < n) { + ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(str.data() + old_size, n - old_size); + } +#endif auto new_size = std::move(op)(str.data(), n); ABSL_HARDENING_ASSERT(new_size >= 0 && new_size <= n); + ABSL_HARDENING_ASSERT(str.data()[n] == typename T::value_type{}); str.erase(static_cast<typename T::size_type>(new_size)); } @@ -138,9 +145,16 @@ // Resizes `str` to contain at most `n` characters, using the user-provided // operation `op` to modify the possibly indeterminate contents. `op` must -// return the finalized length of `str`. Note that `op` is allowed write to -// `data()[n]`, which facilitiates interoperation with functions that write a -// trailing NUL. +// return the finalized length of `str`. +// +// Invalidates all iterators, pointers, and references into `str`, regardless +// of whether reallocation occurs. +// +// `op(value_type* buf, size_t buf_size)` is allowed to write `value_type{}` to +// `buf[buf_size]`, which facilitiates interoperation with functions that write +// a trailing NUL. Please note that this requirement is more strict than +// `basic_string::resize_and_overwrite()`, which allows writing an abitrary +// value to `buf[buf_size]`. template <typename T, typename Op> void StringResizeAndOverwrite(T& str, typename T::size_type n, Op op) { #ifdef ABSL_INTERNAL_HAS_RESIZE_AND_OVERWRITE @@ -162,6 +176,10 @@ strings_internal::StringResizeAndOverwriteFallback(str, n, op); } #endif +#if defined(ABSL_HAVE_MEMORY_SANITIZER) + auto shadow = __msan_test_shadow(str.data(), str.size()); + ABSL_ASSERT(shadow == -1); +#endif } ABSL_NAMESPACE_END
diff --git a/absl/strings/resize_and_overwrite_test.cc b/absl/strings/resize_and_overwrite_test.cc index ad4cca9..8adad2c 100644 --- a/absl/strings/resize_and_overwrite_test.cc +++ b/absl/strings/resize_and_overwrite_test.cc
@@ -19,6 +19,7 @@ #include <string> #include "gtest/gtest.h" +#include "absl/base/dynamic_annotations.h" #include "absl/log/absl_check.h" namespace { @@ -45,7 +46,7 @@ // Truncate case. p[param.final_size - 1] = 'b'; } - p[param.final_size] = 'c'; // Should be overwritten with '\0'; + p[param.final_size] = '\0'; return param.final_size; }); @@ -76,7 +77,7 @@ // Truncate case. p[param.final_size - 1] = 'b'; } - p[param.final_size] = 'c'; // Should be overwritten with '\0'; + p[param.final_size] = '\0'; return param.final_size; }); @@ -94,6 +95,39 @@ EXPECT_EQ(s.c_str()[param.final_size], '\0'); } +#ifdef ABSL_HAVE_MEMORY_SANITIZER +constexpr bool kMSan = true; +#else +constexpr bool kMSan = false; +#endif + +TEST_P(StringResizeAndOverwriteTest, Initialized) { + if (!kMSan) { + GTEST_SKIP() << "Skipping test without MSan."; + } + + const auto& param = GetParam(); + std::string s(param.initial_size, 'a'); + + auto op = [&]() { + absl::StringResizeAndOverwrite(s, param.requested_capacity, + [&](char*, size_t) { + // Fail to initialize the buffer in full. + return param.final_size; + }); + }; + + if (param.initial_size < param.final_size) { +#ifndef NDEBUG + EXPECT_DEATH_IF_SUPPORTED(op(), "shadow == -1"); +#endif + } else { + // The string is fully initialized from the initial constructor, or we skip + // the check in optimized builds. + op(); + } +} + // clang-format off INSTANTIATE_TEST_SUITE_P(StringResizeAndOverwriteTestSuite, StringResizeAndOverwriteTest,
diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc index 1f3cfbf..99b3a1e 100644 --- a/absl/strings/str_cat.cc +++ b/absl/strings/str_cat.cc
@@ -27,6 +27,7 @@ #include "absl/base/internal/raw_logging.h" #include "absl/base/nullability.h" #include "absl/strings/internal/resize_uninitialized.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/string_view.h" namespace absl { @@ -67,13 +68,14 @@ const uint64_t result_size = static_cast<uint64_t>(a.size()) + static_cast<uint64_t>(b.size()); ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow"); - absl::strings_internal::STLStringResizeUninitialized( - &result, static_cast<size_t>(result_size)); - char* const begin = &result[0]; - char* out = begin; - out = Append(out, a); - out = Append(out, b); - assert(out == begin + result.size()); + absl::StringResizeAndOverwrite(result, static_cast<size_t>(result_size), + [&a, &b](char* const begin, size_t buf_size) { + char* out = begin; + out = Append(out, a); + out = Append(out, b); + assert(out == begin + buf_size); + return buf_size; + }); return result; } @@ -86,14 +88,16 @@ static_cast<uint64_t>(b.size()) + static_cast<uint64_t>(c.size()); ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow"); - strings_internal::STLStringResizeUninitialized( - &result, static_cast<size_t>(result_size)); - char* const begin = &result[0]; - char* out = begin; - out = Append(out, a); - out = Append(out, b); - out = Append(out, c); - assert(out == begin + result.size()); + absl::StringResizeAndOverwrite( + result, static_cast<size_t>(result_size), + [&a, &b, &c](char* const begin, size_t buf_size) { + char* out = begin; + out = Append(out, a); + out = Append(out, b); + out = Append(out, c); + assert(out == begin + buf_size); + return buf_size; + }); return result; } @@ -103,20 +107,21 @@ // Use uint64_t to prevent size_t overflow. We assume it is not possible for // in memory strings to overflow a uint64_t. constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()}; - const uint64_t result_size = static_cast<uint64_t>(a.size()) + - static_cast<uint64_t>(b.size()) + - static_cast<uint64_t>(c.size()) + - static_cast<uint64_t>(d.size()); + const uint64_t result_size = + static_cast<uint64_t>(a.size()) + static_cast<uint64_t>(b.size()) + + static_cast<uint64_t>(c.size()) + static_cast<uint64_t>(d.size()); ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow"); - strings_internal::STLStringResizeUninitialized( - &result, static_cast<size_t>(result_size)); - char* const begin = &result[0]; - char* out = begin; - out = Append(out, a); - out = Append(out, b); - out = Append(out, c); - out = Append(out, d); - assert(out == begin + result.size()); + absl::StringResizeAndOverwrite( + result, static_cast<size_t>(result_size), + [&a, &b, &c, &d](char* const begin, size_t buf_size) { + char* out = begin; + out = Append(out, a); + out = Append(out, b); + out = Append(out, c); + out = Append(out, d); + assert(out == begin + buf_size); + return buf_size; + }); return result; } @@ -133,19 +138,19 @@ total_size += piece.size(); } ABSL_INTERNAL_CHECK(total_size <= kMaxSize, "size_t overflow"); - strings_internal::STLStringResizeUninitialized( - &result, static_cast<size_t>(total_size)); - - char* const begin = &result[0]; - char* out = begin; - for (absl::string_view piece : pieces) { - const size_t this_size = piece.size(); - if (this_size != 0) { - memcpy(out, piece.data(), this_size); - out += this_size; - } - } - assert(out == begin + result.size()); + absl::StringResizeAndOverwrite(result, static_cast<size_t>(total_size), + [&pieces](char* const begin, size_t buf_size) { + char* out = begin; + for (absl::string_view piece : pieces) { + const size_t this_size = piece.size(); + if (this_size != 0) { + memcpy(out, piece.data(), this_size); + out += this_size; + } + } + assert(out == begin + buf_size); + return buf_size; + }); return result; }
diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h index 84db0f6..48eb6f9 100644 --- a/absl/strings/str_cat.h +++ b/absl/strings/str_cat.h
@@ -109,6 +109,7 @@ #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/stringify_sink.h" #include "absl/strings/numbers.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/string_view.h" #if !defined(ABSL_USES_STD_STRING_VIEW) @@ -471,23 +472,27 @@ // with 22 bytes (including NULL at the end). constexpr size_t kMaxDigits10 = 22; std::string result; - strings_internal::STLStringResizeUninitialized(&result, kMaxDigits10); - char* start = &result[0]; - // note: this can be optimized to not write last zero. - char* end = numbers_internal::FastIntToBuffer(i, start); - auto size = static_cast<size_t>(end - start); - assert((size < result.size()) && - "StrCat(Integer) does not fit into kMaxDigits10"); - result.erase(size); + StringResizeAndOverwrite( + result, kMaxDigits10, [i](char* start, size_t buf_size) { + // Note: This can be optimized to not write last zero. + char* end = numbers_internal::FastIntToBuffer(i, start); + auto size = static_cast<size_t>(end - start); + ABSL_ASSERT(size < buf_size); + return size; + }); return result; } + template <typename Float> std::string FloatToString(Float f) { std::string result; - strings_internal::STLStringResizeUninitialized( - &result, numbers_internal::kSixDigitsToBufferSize); - char* start = &result[0]; - result.erase(numbers_internal::SixDigitsToBuffer(f, start)); + StringResizeAndOverwrite(result, numbers_internal::kSixDigitsToBufferSize, + [f](char* start, size_t buf_size) { + size_t size = + numbers_internal::SixDigitsToBuffer(f, start); + ABSL_ASSERT(size < buf_size); + return size; + }); return result; }
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index aaaf60b..2f0a0fd 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h
@@ -39,10 +39,10 @@ #include <type_traits> #include "absl/base/attributes.h" -#include "absl/base/nullability.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" @@ -66,6 +66,32 @@ #define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp #endif // ABSL_HAVE_BUILTIN(__builtin_memcmp) +// If `std::ranges` is available, mark `string_view` as satisfying the +// `view` and `borrowed_range` concepts, just like `std::string_view`. +#ifdef __has_include +#if __has_include(<version>) +#include <version> +#endif +#endif + +#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L +#include <ranges> // NOLINT(build/c++20) + +namespace absl { +ABSL_NAMESPACE_BEGIN +class string_view; +ABSL_NAMESPACE_END +} // namespace absl + +template <> +// NOLINTNEXTLINE(build/c++20) +inline constexpr bool std::ranges::enable_view<absl::string_view> = true; +template <> +// NOLINTNEXTLINE(build/c++20) +inline constexpr bool std::ranges::enable_borrowed_range<absl::string_view> = + true; +#endif + namespace absl { ABSL_NAMESPACE_BEGIN
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc index c5d15c7..390173f 100644 --- a/absl/strings/string_view_test.cc +++ b/absl/strings/string_view_test.cc
@@ -35,6 +35,16 @@ #include "absl/base/config.h" #include "absl/meta/type_traits.h" +#ifdef __has_include +#if __has_include(<version>) +#include <version> // NOLINT(misc-include-cleaner) +#endif +#endif + +#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L +#include <ranges> // NOLINT(build/c++20) +#endif + #if defined(ABSL_USES_STD_STRING_VIEW) || defined(__ANDROID__) // We don't control the death messaging when using std::string_view. // Android assert messages only go to system log, so death tests cannot inspect @@ -56,6 +66,15 @@ absl::string_view, std::string>::value, "lifetimebound assignment not detected"); +#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L +// NOLINTNEXTLINE(build/c++20) +static_assert(std::ranges::enable_view<absl::string_view>, + "std::ranges::view not enabled"); +// NOLINTNEXTLINE(build/c++20) +static_assert(std::ranges::enable_borrowed_range<absl::string_view>, + "std::ranges::borrowed_range not enabled"); +#endif + // A minimal allocator that uses malloc(). template <typename T> struct Mallocator {
diff --git a/absl/time/duration_benchmark.cc b/absl/time/duration_benchmark.cc index fdb26bb..e2dd4d2 100644 --- a/absl/time/duration_benchmark.cc +++ b/absl/time/duration_benchmark.cc
@@ -359,6 +359,150 @@ BENCHMARK(BM_Duration_ToInt64Hours); // +// ToDoubleXYZ +// +void BM_Duration_ToDoubleNanoseconds(benchmark::State& state) { + absl::Duration d = absl::Seconds(100000); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d); + double result = absl::ToDoubleNanoseconds(d); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK(BM_Duration_ToDoubleNanoseconds); + +void BM_Duration_ToDoubleMicroseconds(benchmark::State& state) { + absl::Duration d = absl::Seconds(100000); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d); + double result = absl::ToDoubleMicroseconds(d); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK(BM_Duration_ToDoubleMicroseconds); + +void BM_Duration_ToDoubleMilliseconds(benchmark::State& state) { + absl::Duration d = absl::Seconds(100000); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d); + double result = absl::ToDoubleMilliseconds(d); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK(BM_Duration_ToDoubleMilliseconds); + +void BM_Duration_ToDoubleSeconds(benchmark::State& state) { + absl::Duration d = absl::Seconds(100000); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d); + double result = absl::ToDoubleSeconds(d); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK(BM_Duration_ToDoubleSeconds); + +void BM_Duration_ToDoubleMinutes(benchmark::State& state) { + absl::Duration d = absl::Seconds(100000); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d); + double result = absl::ToDoubleMinutes(d); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK(BM_Duration_ToDoubleMinutes); + +void BM_Duration_ToDoubleHours(benchmark::State& state) { + absl::Duration d = absl::Seconds(100000); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d); + double result = absl::ToDoubleHours(d); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK(BM_Duration_ToDoubleHours); + +// +// ToDoubleXYZ Latency +// +void BM_Duration_ToDoubleNanoseconds_Latency(benchmark::State& state) { + absl::Duration d1 = absl::Seconds(100000); + absl::Duration d2 = absl::Seconds(100000); + double result = 1; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d1); + benchmark::DoNotOptimize(d2); + benchmark::DoNotOptimize(result); + result = absl::ToDoubleNanoseconds(result < 0 ? d1 : d2); + } +} +BENCHMARK(BM_Duration_ToDoubleNanoseconds_Latency); + +void BM_Duration_ToDoubleMicroseconds_Latency(benchmark::State& state) { + absl::Duration d1 = absl::Seconds(100000); + absl::Duration d2 = absl::Seconds(100000); + double result = 1; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d1); + benchmark::DoNotOptimize(d2); + benchmark::DoNotOptimize(result); + result = absl::ToDoubleMicroseconds(result < 0 ? d1 : d2); + } +} +BENCHMARK(BM_Duration_ToDoubleMicroseconds_Latency); + +void BM_Duration_ToDoubleMilliseconds_Latency(benchmark::State& state) { + absl::Duration d1 = absl::Seconds(100000); + absl::Duration d2 = absl::Seconds(100000); + double result = 1; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d1); + benchmark::DoNotOptimize(d2); + benchmark::DoNotOptimize(result); + result = absl::ToDoubleMilliseconds(result < 0 ? d1 : d2); + } +} +BENCHMARK(BM_Duration_ToDoubleMilliseconds_Latency); + +void BM_Duration_ToDoubleSeconds_Latency(benchmark::State& state) { + absl::Duration d1 = absl::Seconds(100000); + absl::Duration d2 = absl::Seconds(100000); + double result = 1; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d1); + benchmark::DoNotOptimize(d2); + benchmark::DoNotOptimize(result); + result = absl::ToDoubleSeconds(result < 0 ? d1 : d2); + } +} +BENCHMARK(BM_Duration_ToDoubleSeconds_Latency); + +void BM_Duration_ToDoubleMinutes_Latency(benchmark::State& state) { + absl::Duration d1 = absl::Seconds(100000); + absl::Duration d2 = absl::Seconds(100000); + double result = 1; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d1); + benchmark::DoNotOptimize(d2); + benchmark::DoNotOptimize(result); + result = absl::ToDoubleMinutes(result < 0 ? d1 : d2); + } +} +BENCHMARK(BM_Duration_ToDoubleMinutes_Latency); + +void BM_Duration_ToDoubleHours_Latency(benchmark::State& state) { + absl::Duration d1 = absl::Seconds(100000); + absl::Duration d2 = absl::Seconds(100000); + double result = 1; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(d1); + benchmark::DoNotOptimize(d2); + benchmark::DoNotOptimize(result); + result = absl::ToDoubleHours(result < 0 ? d1 : d2); + } +} +BENCHMARK(BM_Duration_ToDoubleHours_Latency); + +// // To/FromTimespec //
diff --git a/absl/types/compare.h b/absl/types/compare.h index 3cf4a91..edf1039 100644 --- a/absl/types/compare.h +++ b/absl/types/compare.h
@@ -120,8 +120,7 @@ // A no-op expansion that can be followed by a semicolon at class level. #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "") -#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \ - static const type name +#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static const type name #define ABSL_COMPARE_INLINE_INIT(type, name, init) \ inline constexpr type type::name(init) @@ -190,28 +189,28 @@ ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered); // Comparisons - friend constexpr bool operator==( - partial_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator==(partial_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.is_ordered() && v.value_ == 0; } - friend constexpr bool operator!=( - partial_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator!=(partial_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return !v.is_ordered() || v.value_ != 0; } - friend constexpr bool operator<( - partial_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator<(partial_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.is_ordered() && v.value_ < 0; } - friend constexpr bool operator<=( - partial_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator<=(partial_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.is_ordered() && v.value_ <= 0; } - friend constexpr bool operator>( - partial_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator>(partial_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.is_ordered() && v.value_ > 0; } - friend constexpr bool operator>=( - partial_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator>=(partial_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.is_ordered() && v.value_ >= 0; } friend constexpr bool operator==(compare_internal::OnlyLiteralZero, @@ -278,28 +277,28 @@ : partial_ordering::greater); } // Comparisons - friend constexpr bool operator==( - weak_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator==(weak_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ == 0; } - friend constexpr bool operator!=( - weak_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator!=(weak_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ != 0; } - friend constexpr bool operator<( - weak_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator<(weak_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ < 0; } - friend constexpr bool operator<=( - weak_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator<=(weak_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ <= 0; } - friend constexpr bool operator>( - weak_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator>(weak_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ > 0; } - friend constexpr bool operator>=( - weak_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator>=(weak_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ >= 0; } friend constexpr bool operator==(compare_internal::OnlyLiteralZero, @@ -370,28 +369,28 @@ : (value_ < 0 ? weak_ordering::less : weak_ordering::greater); } // Comparisons - friend constexpr bool operator==( - strong_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator==(strong_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ == 0; } - friend constexpr bool operator!=( - strong_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator!=(strong_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ != 0; } - friend constexpr bool operator<( - strong_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator<(strong_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ < 0; } - friend constexpr bool operator<=( - strong_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator<=(strong_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ <= 0; } - friend constexpr bool operator>( - strong_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator>(strong_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ > 0; } - friend constexpr bool operator>=( - strong_ordering v, compare_internal::OnlyLiteralZero) noexcept { + friend constexpr bool operator>=(strong_ordering v, + compare_internal::OnlyLiteralZero) noexcept { return v.value_ >= 0; } friend constexpr bool operator==(compare_internal::OnlyLiteralZero, @@ -451,14 +450,16 @@ // SFINAE prevents implicit conversions to bool (such as from int). template <typename BoolT, absl::enable_if_t<std::is_same<bool, BoolT>::value, int> = 0> -constexpr bool compare_result_as_less_than(const BoolT r) { return r; } +constexpr bool compare_result_as_less_than(const BoolT r) { + return r; +} constexpr bool compare_result_as_less_than(const absl::weak_ordering r) { return r < 0; } template <typename Compare, typename K, typename LK> -constexpr bool do_less_than_comparison(const Compare &compare, const K &x, - const LK &y) { +constexpr bool do_less_than_comparison(const Compare& compare, const K& x, + const LK& y) { return compare_result_as_less_than(compare(x, y)); } @@ -468,34 +469,34 @@ template <typename Int, absl::enable_if_t<std::is_same<int, Int>::value, int> = 0> constexpr absl::weak_ordering compare_result_as_ordering(const Int c) { - return c < 0 ? absl::weak_ordering::less - : c == 0 ? absl::weak_ordering::equivalent - : absl::weak_ordering::greater; + return c < 0 ? absl::weak_ordering::less + : c == 0 ? absl::weak_ordering::equivalent + : absl::weak_ordering::greater; } constexpr absl::weak_ordering compare_result_as_ordering( const absl::weak_ordering c) { return c; } -template < - typename Compare, typename K, typename LK, - absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare( - const K &, const LK &)>>::value, - int> = 0> -constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, - const K &x, const LK &y) { +template <typename Compare, typename K, typename LK, + absl::enable_if_t< + !std::is_same< + bool, absl::result_of_t<Compare(const K&, const LK&)>>::value, + int> = 0> +constexpr absl::weak_ordering do_three_way_comparison(const Compare& compare, + const K& x, const LK& y) { return compare_result_as_ordering(compare(x, y)); } -template < - typename Compare, typename K, typename LK, - absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare( - const K &, const LK &)>>::value, - int> = 0> -constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, - const K &x, const LK &y) { - return compare(x, y) ? absl::weak_ordering::less - : compare(y, x) ? absl::weak_ordering::greater - : absl::weak_ordering::equivalent; +template <typename Compare, typename K, typename LK, + absl::enable_if_t< + std::is_same< + bool, absl::result_of_t<Compare(const K&, const LK&)>>::value, + int> = 0> +constexpr absl::weak_ordering do_three_way_comparison(const Compare& compare, + const K& x, const LK& y) { + return compare(x, y) ? absl::weak_ordering::less + : compare(y, x) ? absl::weak_ordering::greater + : absl::weak_ordering::equivalent; } } // namespace compare_internal
diff --git a/absl/types/compare_test.cc b/absl/types/compare_test.cc index 455cdbb..352c9f1 100644 --- a/absl/types/compare_test.cc +++ b/absl/types/compare_test.cc
@@ -160,9 +160,9 @@ struct WeakOrderingLess { template <typename T> absl::weak_ordering operator()(const T& a, const T& b) const { - return a < b ? absl::weak_ordering::less - : a == b ? absl::weak_ordering::equivalent - : absl::weak_ordering::greater; + return a < b ? absl::weak_ordering::less + : a == b ? absl::weak_ordering::equivalent + : absl::weak_ordering::greater; } };
diff --git a/absl/types/internal/span.h b/absl/types/internal/span.h index 1039f61..cdf3941 100644 --- a/absl/types/internal/span.h +++ b/absl/types/internal/span.h
@@ -121,6 +121,7 @@ using ConstData = decltype(span_internal::GetData(std::declval<const Container&>())); using MutData = decltype(span_internal::GetData(std::declval<Container&>())); + public: static constexpr bool value = std::is_same<ConstData, MutData>::value; };
diff --git a/absl/types/optional.h b/absl/types/optional.h index 65bba64..5b68a5b 100644 --- a/absl/types/optional.h +++ b/absl/types/optional.h
@@ -31,10 +31,10 @@ namespace absl { ABSL_NAMESPACE_BEGIN using std::bad_optional_access; -using std::optional; using std::make_optional; -using std::nullopt_t; using std::nullopt; +using std::nullopt_t; +using std::optional; ABSL_NAMESPACE_END } // namespace absl
diff --git a/absl/types/span.h b/absl/types/span.h index 016376e..d2cf627 100644 --- a/absl/types/span.h +++ b/absl/types/span.h
@@ -91,10 +91,10 @@ #if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L #include <ranges> // NOLINT(build/c++20) template <typename T> - // NOLINTNEXTLINE(build/c++20) +// NOLINTNEXTLINE(build/c++20) inline constexpr bool std::ranges::enable_view<absl::Span<T>> = true; template <typename T> - // NOLINTNEXTLINE(build/c++20) +// NOLINTNEXTLINE(build/c++20) inline constexpr bool std::ranges::enable_borrowed_range<absl::Span<T>> = true; #endif