diff --git a/absl/base/config.h b/absl/base/config.h index 7514b86..f3cafbd 100644 --- a/absl/base/config.h +++ b/absl/base/config.h
@@ -530,13 +530,12 @@ // ABSL_HAVE_STD_STRING_VIEW // -// Checks whether C++17 std::string_view is available. +// Deprecated: always defined to 1. +// std::string_view was added in C++17, which means all versions of C++ +// supported by Abseil have it. #ifdef ABSL_HAVE_STD_STRING_VIEW #error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set." -#elif defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L -#define ABSL_HAVE_STD_STRING_VIEW 1 -#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ - ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L +#else #define ABSL_HAVE_STD_STRING_VIEW 1 #endif @@ -561,13 +560,10 @@ // Indicates whether absl::string_view is an alias for std::string_view. #if !defined(ABSL_OPTION_USE_STD_STRING_VIEW) #error options.h is misconfigured. -#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \ - (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ - !defined(ABSL_HAVE_STD_STRING_VIEW)) +#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 #undef ABSL_USES_STD_STRING_VIEW #elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \ - (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ - defined(ABSL_HAVE_STD_STRING_VIEW)) + ABSL_OPTION_USE_STD_STRING_VIEW == 2 #define ABSL_USES_STD_STRING_VIEW 1 #else #error options.h is misconfigured.
diff --git a/absl/container/internal/hash_function_defaults.h b/absl/container/internal/hash_function_defaults.h index 0f07bcf..c2a757b 100644 --- a/absl/container/internal/hash_function_defaults.h +++ b/absl/container/internal/hash_function_defaults.h
@@ -49,6 +49,7 @@ #include <functional> #include <memory> #include <string> +#include <string_view> #include <type_traits> #include "absl/base/config.h" @@ -58,10 +59,6 @@ #include "absl/strings/cord.h" #include "absl/strings/string_view.h" -#ifdef ABSL_HAVE_STD_STRING_VIEW -#include <string_view> -#endif - namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { @@ -113,8 +110,6 @@ template <> struct HashEq<absl::Cord> : StringHashEq {}; -#ifdef ABSL_HAVE_STD_STRING_VIEW - template <typename TChar> struct BasicStringHash { using is_transparent = void; @@ -153,8 +148,6 @@ template <> struct HashEq<std::u32string_view> : BasicStringHashEq<char32_t> {}; -#endif // ABSL_HAVE_STD_STRING_VIEW - // Supports heterogeneous lookup for pointers and smart pointers. template <class T> struct HashEq<T*> {
diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc index 912d119..9a39b07 100644 --- a/absl/container/internal/hash_function_defaults_test.cc +++ b/absl/container/internal/hash_function_defaults_test.cc
@@ -16,6 +16,7 @@ #include <cstddef> #include <functional> +#include <string_view> #include <type_traits> #include <utility> @@ -28,10 +29,6 @@ #include "absl/strings/cord_test_helpers.h" #include "absl/strings/string_view.h" -#ifdef ABSL_HAVE_STD_STRING_VIEW -#include <string_view> -#endif - namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { @@ -118,9 +115,6 @@ } TEST(BasicStringViewTest, WStringEqWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_eq<std::wstring> eq; EXPECT_TRUE(eq(L"a", L"a")); EXPECT_TRUE(eq(L"a", std::wstring_view(L"a"))); @@ -128,13 +122,9 @@ EXPECT_FALSE(eq(L"a", L"b")); EXPECT_FALSE(eq(L"a", std::wstring_view(L"b"))); EXPECT_FALSE(eq(L"a", std::wstring(L"b"))); -#endif } TEST(BasicStringViewTest, WStringViewEqWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_eq<std::wstring_view> eq; EXPECT_TRUE(eq(L"a", L"a")); EXPECT_TRUE(eq(L"a", std::wstring_view(L"a"))); @@ -142,13 +132,9 @@ EXPECT_FALSE(eq(L"a", L"b")); EXPECT_FALSE(eq(L"a", std::wstring_view(L"b"))); EXPECT_FALSE(eq(L"a", std::wstring(L"b"))); -#endif } TEST(BasicStringViewTest, U16StringEqWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_eq<std::u16string> eq; EXPECT_TRUE(eq(u"a", u"a")); EXPECT_TRUE(eq(u"a", std::u16string_view(u"a"))); @@ -156,13 +142,9 @@ EXPECT_FALSE(eq(u"a", u"b")); EXPECT_FALSE(eq(u"a", std::u16string_view(u"b"))); EXPECT_FALSE(eq(u"a", std::u16string(u"b"))); -#endif } TEST(BasicStringViewTest, U16StringViewEqWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_eq<std::u16string_view> eq; EXPECT_TRUE(eq(u"a", u"a")); EXPECT_TRUE(eq(u"a", std::u16string_view(u"a"))); @@ -170,13 +152,9 @@ EXPECT_FALSE(eq(u"a", u"b")); EXPECT_FALSE(eq(u"a", std::u16string_view(u"b"))); EXPECT_FALSE(eq(u"a", std::u16string(u"b"))); -#endif } TEST(BasicStringViewTest, U32StringEqWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_eq<std::u32string> eq; EXPECT_TRUE(eq(U"a", U"a")); EXPECT_TRUE(eq(U"a", std::u32string_view(U"a"))); @@ -184,13 +162,9 @@ EXPECT_FALSE(eq(U"a", U"b")); EXPECT_FALSE(eq(U"a", std::u32string_view(U"b"))); EXPECT_FALSE(eq(U"a", std::u32string(U"b"))); -#endif } TEST(BasicStringViewTest, U32StringViewEqWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_eq<std::u32string_view> eq; EXPECT_TRUE(eq(U"a", U"a")); EXPECT_TRUE(eq(U"a", std::u32string_view(U"a"))); @@ -198,85 +172,60 @@ EXPECT_FALSE(eq(U"a", U"b")); EXPECT_FALSE(eq(U"a", std::u32string_view(U"b"))); EXPECT_FALSE(eq(U"a", std::u32string(U"b"))); -#endif } TEST(BasicStringViewTest, WStringHashWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_hash<std::wstring> hash; auto h = hash(L"a"); EXPECT_EQ(h, hash(std::wstring_view(L"a"))); EXPECT_EQ(h, hash(std::wstring(L"a"))); EXPECT_NE(h, hash(std::wstring_view(L"b"))); EXPECT_NE(h, hash(std::wstring(L"b"))); -#endif } TEST(BasicStringViewTest, WStringViewHashWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_hash<std::wstring_view> hash; auto h = hash(L"a"); EXPECT_EQ(h, hash(std::wstring_view(L"a"))); EXPECT_EQ(h, hash(std::wstring(L"a"))); EXPECT_NE(h, hash(std::wstring_view(L"b"))); EXPECT_NE(h, hash(std::wstring(L"b"))); -#endif } TEST(BasicStringViewTest, U16StringHashWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_hash<std::u16string> hash; auto h = hash(u"a"); EXPECT_EQ(h, hash(std::u16string_view(u"a"))); EXPECT_EQ(h, hash(std::u16string(u"a"))); EXPECT_NE(h, hash(std::u16string_view(u"b"))); EXPECT_NE(h, hash(std::u16string(u"b"))); -#endif } TEST(BasicStringViewTest, U16StringViewHashWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_hash<std::u16string_view> hash; auto h = hash(u"a"); EXPECT_EQ(h, hash(std::u16string_view(u"a"))); EXPECT_EQ(h, hash(std::u16string(u"a"))); EXPECT_NE(h, hash(std::u16string_view(u"b"))); EXPECT_NE(h, hash(std::u16string(u"b"))); -#endif } TEST(BasicStringViewTest, U32StringHashWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_hash<std::u32string> hash; auto h = hash(U"a"); EXPECT_EQ(h, hash(std::u32string_view(U"a"))); EXPECT_EQ(h, hash(std::u32string(U"a"))); EXPECT_NE(h, hash(std::u32string_view(U"b"))); EXPECT_NE(h, hash(std::u32string(U"b"))); -#endif } TEST(BasicStringViewTest, U32StringViewHashWorks) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else hash_default_hash<std::u32string_view> hash; auto h = hash(U"a"); EXPECT_EQ(h, hash(std::u32string_view(U"a"))); EXPECT_EQ(h, hash(std::u32string(U"a"))); EXPECT_NE(h, hash(std::u32string_view(U"b"))); EXPECT_NE(h, hash(std::u32string(U"b"))); -#endif } struct NoDeleter {
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc index f19e87b..339e662 100644 --- a/absl/container/internal/raw_hash_set.cc +++ b/absl/container/internal/raw_hash_set.cc
@@ -295,9 +295,14 @@ ABSL_UNREACHABLE(); } -size_t DropDeletesWithoutResizeAndPrepareInsert(CommonFields& common, - const PolicyFunctions& policy, - size_t new_hash) { +void PrepareInsertCommon(CommonFields& common) { + common.increment_size(); + common.maybe_increment_generation_on_insert(); +} + +size_t DropDeletesWithoutResizeAndPrepareInsert( + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t new_hash) { void* set = &common; void* slot_array = common.slot_array(); const size_t capacity = common.capacity(); @@ -399,7 +404,7 @@ PrepareInsertCommon(common); ResetGrowthLeft(common); FindInfo find_info = find_first_non_full(common, new_hash); - SetCtrlInLargeTable(common, find_info.offset, H2(new_hash), policy.slot_size); + SetCtrlInLargeTable(common, find_info.offset, H2(new_hash), slot_size); common.infoz().RecordInsert(new_hash, find_info.probe_length); common.infoz().RecordRehash(total_probe_length); return find_info.offset; @@ -555,8 +560,9 @@ SetCtrlInLargeTable(c, index, ctrl_t::kDeleted, slot_size); } -void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy, - void* alloc, bool reuse, bool soo_enabled) { +void ClearBackingArray(CommonFields& c, + const PolicyFunctions& __restrict policy, void* alloc, + bool reuse, bool soo_enabled) { if (reuse) { c.set_size_to_zero(); ABSL_SWISSTABLE_ASSERT(!soo_enabled || c.capacity() > SooCapacity()); @@ -587,10 +593,9 @@ // This function is used for reserving or rehashing non-empty tables. // This use case is rare so the function is type erased. // Returns the total probe length. -size_t FindNewPositionsAndTransferSlots(CommonFields& common, - const PolicyFunctions& policy, - ctrl_t* old_ctrl, void* old_slots, - size_t old_capacity) { +size_t FindNewPositionsAndTransferSlots( + CommonFields& common, const PolicyFunctions& __restrict policy, + ctrl_t* old_ctrl, void* old_slots, size_t old_capacity) { void* new_slots = common.slot_array(); const void* hash_fn = policy.hash_fn(common); const size_t slot_size = policy.slot_size; @@ -614,7 +619,8 @@ } template <ResizeNonSooMode kMode> -void ResizeNonSooImpl(CommonFields& common, const PolicyFunctions& policy, +void ResizeNonSooImpl(CommonFields& common, + const PolicyFunctions& __restrict policy, size_t new_capacity, HashtablezInfoHandle infoz) { ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity)); ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity()); @@ -667,7 +673,7 @@ } void ResizeEmptyNonAllocatedTableImpl(CommonFields& common, - const PolicyFunctions& policy, + const PolicyFunctions& __restrict policy, size_t new_capacity, bool force_infoz) { ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity)); ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity()); @@ -690,10 +696,9 @@ // After transferring the slot, sets control and slots in CommonFields. // It is rare to resize an SOO table with one element to a large size. // Requires: `c` contains SOO data. -void InsertOldSooSlotAndInitializeControlBytes(CommonFields& c, - const PolicyFunctions& policy, - size_t hash, ctrl_t* new_ctrl, - void* new_slots) { +void InsertOldSooSlotAndInitializeControlBytes( + CommonFields& c, const PolicyFunctions& __restrict policy, size_t hash, + ctrl_t* new_ctrl, void* new_slots) { ABSL_SWISSTABLE_ASSERT(c.size() == policy.soo_capacity()); ABSL_SWISSTABLE_ASSERT(policy.soo_enabled); size_t new_capacity = c.capacity(); @@ -728,7 +733,8 @@ ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity()); } -void ResizeFullSooTable(CommonFields& common, const PolicyFunctions& policy, +void ResizeFullSooTable(CommonFields& common, + const PolicyFunctions& __restrict policy, size_t new_capacity, ResizeFullSooTableSamplingMode sampling_mode) { AssertFullSoo(common, policy); @@ -912,8 +918,8 @@ // Returns the total probe length. template <typename ProbedItem> ABSL_ATTRIBUTE_NOINLINE size_t DecodeAndInsertImpl( - CommonFields& c, const PolicyFunctions& policy, const ProbedItem* start, - const ProbedItem* end, void* old_slots) { + CommonFields& c, const PolicyFunctions& __restrict policy, + const ProbedItem* start, const ProbedItem* end, void* old_slots) { const size_t new_capacity = c.capacity(); void* new_slots = c.slot_array(); @@ -949,9 +955,9 @@ // We marked them in control bytes as kSentinel. // Hash recomputation and full probing is done here. // This use case should be extremely rare. -ABSL_ATTRIBUTE_NOINLINE size_t -ProcessProbedMarkedElements(CommonFields& c, const PolicyFunctions& policy, - ctrl_t* old_ctrl, void* old_slots, size_t start) { +ABSL_ATTRIBUTE_NOINLINE size_t ProcessProbedMarkedElements( + CommonFields& c, const PolicyFunctions& __restrict policy, ctrl_t* old_ctrl, + void* old_slots, size_t start) { size_t old_capacity = PreviousCapacity(c.capacity()); const size_t slot_size = policy.slot_size; void* new_slots = c.slot_array(); @@ -1029,7 +1035,7 @@ // Finds new position for each element and transfers it to the new slots. // Returns the total probe length. size_t DecodeAndInsertToTable(CommonFields& common, - const PolicyFunctions& policy, + const PolicyFunctions& __restrict policy, void* old_slots) const { if (pos_ == buffer_) { return 0; @@ -1103,7 +1109,7 @@ // Finds new position for each element and transfers it to the new slots. // Returns the total probe length. ABSL_ATTRIBUTE_NOINLINE size_t DecodeAndInsertToTableOverflow( - CommonFields& common, const PolicyFunctions& policy, + CommonFields& common, const PolicyFunctions& __restrict policy, void* old_slots) const { ABSL_SWISSTABLE_ASSERT(local_buffer_full_ && "must not be called when local buffer is not full"); @@ -1136,7 +1142,8 @@ // Different encoder is used depending on the capacity of the table. // Returns total probe length. template <typename Encoder> -size_t GrowToNextCapacity(CommonFields& common, const PolicyFunctions& policy, +size_t GrowToNextCapacity(CommonFields& common, + const PolicyFunctions& __restrict policy, ctrl_t* old_ctrl, void* old_slots) { using ProbedItem = typename Encoder::ProbedItem; ABSL_SWISSTABLE_ASSERT(common.capacity() <= ProbedItem::kMaxNewCapacity); @@ -1154,10 +1161,9 @@ // Grows to next capacity for relatively small tables so that even if all // elements are probed, we don't need to overflow the local buffer. // Returns total probe length. -size_t GrowToNextCapacityThatFitsInLocalBuffer(CommonFields& common, - const PolicyFunctions& policy, - ctrl_t* old_ctrl, - void* old_slots) { +size_t GrowToNextCapacityThatFitsInLocalBuffer( + CommonFields& common, const PolicyFunctions& __restrict policy, + ctrl_t* old_ctrl, void* old_slots) { ABSL_SWISSTABLE_ASSERT(common.capacity() <= kMaxLocalBufferNewCapacity); return GrowToNextCapacity< ProbedItemEncoder<ProbedItem4Bytes, /*kGuaranteedFitToBuffer=*/true>>( @@ -1167,20 +1173,20 @@ // Grows to next capacity with different encodings. Returns total probe length. // These functions are useful to simplify profile analysis. size_t GrowToNextCapacity4BytesEncoder(CommonFields& common, - const PolicyFunctions& policy, + const PolicyFunctions& __restrict policy, ctrl_t* old_ctrl, void* old_slots) { return GrowToNextCapacity<ProbedItemEncoder<ProbedItem4Bytes>>( common, policy, old_ctrl, old_slots); } size_t GrowToNextCapacity8BytesEncoder(CommonFields& common, - const PolicyFunctions& policy, + const PolicyFunctions& __restrict policy, ctrl_t* old_ctrl, void* old_slots) { return GrowToNextCapacity<ProbedItemEncoder<ProbedItem8Bytes>>( common, policy, old_ctrl, old_slots); } -size_t GrowToNextCapacity16BytesEncoder(CommonFields& common, - const PolicyFunctions& policy, - ctrl_t* old_ctrl, void* old_slots) { +size_t GrowToNextCapacity16BytesEncoder( + CommonFields& common, const PolicyFunctions& __restrict policy, + ctrl_t* old_ctrl, void* old_slots) { return GrowToNextCapacity<ProbedItemEncoder<ProbedItem16Bytes>>( common, policy, old_ctrl, old_slots); } @@ -1188,10 +1194,9 @@ // Grows to next capacity for tables with relatively large capacity so that we // can't guarantee that all probed elements fit in the local buffer. Returns // total probe length. -size_t GrowToNextCapacityOverflowLocalBuffer(CommonFields& common, - const PolicyFunctions& policy, - ctrl_t* old_ctrl, - void* old_slots) { +size_t GrowToNextCapacityOverflowLocalBuffer( + CommonFields& common, const PolicyFunctions& __restrict policy, + ctrl_t* old_ctrl, void* old_slots) { const size_t new_capacity = common.capacity(); if (ABSL_PREDICT_TRUE(new_capacity <= ProbedItem4Bytes::kMaxNewCapacity)) { return GrowToNextCapacity4BytesEncoder(common, policy, old_ctrl, old_slots); @@ -1207,7 +1212,7 @@ // capacity of the table. Returns total probe length. ABSL_ATTRIBUTE_NOINLINE size_t GrowToNextCapacityDispatch(CommonFields& common, - const PolicyFunctions& policy, + const PolicyFunctions& __restrict policy, ctrl_t* old_ctrl, void* old_slots) { const size_t new_capacity = common.capacity(); if (ABSL_PREDICT_TRUE(new_capacity <= kMaxLocalBufferNewCapacity)) { @@ -1221,9 +1226,9 @@ // Grows to next capacity and prepares insert for the given new_hash. // Returns the offset of the new element. -size_t GrowToNextCapacityAndPrepareInsert(CommonFields& common, - const PolicyFunctions& policy, - size_t new_hash) { +size_t GrowToNextCapacityAndPrepareInsert( + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t new_hash) { ABSL_SWISSTABLE_ASSERT(common.growth_left() == 0); const size_t old_capacity = common.capacity(); ABSL_SWISSTABLE_ASSERT(old_capacity == 0 || @@ -1321,9 +1326,9 @@ // Called whenever the table needs to vacate empty slots either by removing // tombstones via rehash or growth to next capacity. ABSL_ATTRIBUTE_NOINLINE -size_t RehashOrGrowToNextCapacityAndPrepareInsert(CommonFields& common, - const PolicyFunctions& policy, - size_t new_hash) { +size_t RehashOrGrowToNextCapacityAndPrepareInsert( + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t new_hash) { const size_t cap = common.capacity(); ABSL_ASSUME(cap > 0); if (cap > Group::kWidth && @@ -1380,7 +1385,8 @@ // Slow path for PrepareInsertNonSoo that is called when the table has deleted // slots or need to be resized or rehashed. size_t PrepareInsertNonSooSlow(CommonFields& common, - const PolicyFunctions& policy, size_t hash) { + const PolicyFunctions& __restrict policy, + size_t hash) { const GrowthInfo growth_info = common.growth_info(); ABSL_SWISSTABLE_ASSERT(!growth_info.HasNoDeletedAndGrowthLeft()); if (ABSL_PREDICT_TRUE(growth_info.HasNoGrowthLeftAndNoDeleted())) { @@ -1402,7 +1408,6 @@ return target.offset; } - // Resizes empty non-allocated SOO table to NextCapacity(SooCapacity()), // forces the table to be sampled and prepares the insert. // SOO tables need to switch from SOO to heap in order to store the infoz. @@ -1411,7 +1416,8 @@ // 2. `c.empty()`. ABSL_ATTRIBUTE_NOINLINE size_t GrowEmptySooTableToNextCapacityForceSamplingAndPrepareInsert( - CommonFields& common, const PolicyFunctions& policy, size_t new_hash) { + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t new_hash) { ResizeEmptyNonAllocatedTableImpl(common, policy, NextCapacity(SooCapacity()), /*force_infoz=*/true); PrepareInsertCommon(common); @@ -1428,9 +1434,9 @@ // 2. `c.empty()`. // 3. `new_size > policy.soo_capacity()`. // The table will be attempted to be sampled. -void ReserveEmptyNonAllocatedTableToFitNewSize(CommonFields& common, - const PolicyFunctions& policy, - size_t new_size) { +void ReserveEmptyNonAllocatedTableToFitNewSize( + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t new_size) { ValidateMaxSize(new_size, policy.slot_size); ABSL_ASSUME(new_size > 0); ResizeEmptyNonAllocatedTableImpl(common, policy, SizeToCapacity(new_size), @@ -1447,7 +1453,8 @@ // 1. `c.capacity() > policy.soo_capacity()` OR `!c.empty()`. // Reserving already allocated tables is considered to be a rare case. ABSL_ATTRIBUTE_NOINLINE void ReserveAllocatedTable( - CommonFields& common, const PolicyFunctions& policy, size_t new_size) { + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t new_size) { const size_t cap = common.capacity(); ValidateMaxSize(new_size, policy.slot_size); ABSL_ASSUME(new_size > 0); @@ -1474,15 +1481,16 @@ return &common; } -void ResizeAllocatedTableWithSeedChange(CommonFields& common, - const PolicyFunctions& policy, - size_t new_capacity) { +void ResizeAllocatedTableWithSeedChange( + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t new_capacity) { ResizeNonSooImpl<ResizeNonSooMode::kGuaranteedAllocated>( common, policy, new_capacity, common.infoz()); } void ReserveEmptyNonAllocatedTableToFitBucketCount( - CommonFields& common, const PolicyFunctions& policy, size_t bucket_count) { + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t bucket_count) { size_t new_capacity = NormalizeCapacity(bucket_count); ValidateMaxSize(CapacityToGrowth(new_capacity), policy.slot_size); ResizeEmptyNonAllocatedTableImpl(common, policy, new_capacity, @@ -1491,10 +1499,9 @@ // Resizes a full SOO table to the NextCapacity(SooCapacity()). template <size_t SooSlotMemcpySize, bool TransferUsesMemcpy> -size_t GrowSooTableToNextCapacityAndPrepareInsert(CommonFields& common, - const PolicyFunctions& policy, - size_t new_hash, - ctrl_t soo_slot_ctrl) { +size_t GrowSooTableToNextCapacityAndPrepareInsert( + CommonFields& common, const PolicyFunctions& __restrict policy, + size_t new_hash, ctrl_t soo_slot_ctrl) { AssertSoo(common, policy); if (ABSL_PREDICT_FALSE(soo_slot_ctrl == ctrl_t::kEmpty)) { // The table is empty, it is only used for forced sampling of SOO tables. @@ -1566,14 +1573,15 @@ } void GrowFullSooTableToNextCapacityForceSampling( - CommonFields& common, const PolicyFunctions& policy) { + CommonFields& common, const PolicyFunctions& __restrict policy) { AssertFullSoo(common, policy); ResizeFullSooTable( common, policy, NextCapacity(SooCapacity()), ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled); } -void Rehash(CommonFields& common, const PolicyFunctions& policy, size_t n) { +void Rehash(CommonFields& common, const PolicyFunctions& __restrict policy, + size_t n) { const size_t cap = common.capacity(); auto clear_backing_array = [&]() { @@ -1640,7 +1648,7 @@ } } -void Copy(CommonFields& common, const PolicyFunctions& policy, +void Copy(CommonFields& common, const PolicyFunctions& __restrict policy, const CommonFields& other, absl::FunctionRef<void(void*, const void*)> copy_fn) { const size_t size = other.size(); @@ -1716,7 +1724,8 @@ } void ReserveTableToFitNewSize(CommonFields& common, - const PolicyFunctions& policy, size_t new_size) { + const PolicyFunctions& __restrict policy, + size_t new_size) { common.reset_reserved_growth(new_size); common.set_reservation_size(new_size); ABSL_SWISSTABLE_ASSERT(new_size > policy.soo_capacity()); @@ -1736,7 +1745,8 @@ ReserveAllocatedTable(common, policy, new_size); } -size_t PrepareInsertNonSoo(CommonFields& common, const PolicyFunctions& policy, +size_t PrepareInsertNonSoo(CommonFields& common, + const PolicyFunctions& __restrict policy, size_t hash, FindInfo target) { const bool rehash_for_bug_detection = common.should_rehash_for_bug_detection_on_insert() &&
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 512c946..3bc86d1 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h
@@ -1827,11 +1827,6 @@ const PolicyFunctions& policy, size_t new_capacity); -inline void PrepareInsertCommon(CommonFields& common) { - common.increment_size(); - common.maybe_increment_generation_on_insert(); -} - // ClearBackingArray clears the backing array, either modifying it in place, // or creating a new one based on the value of "reuse". // REQUIRES: c.capacity > 0
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index cc0f4bb..7d8af92 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -23,6 +23,7 @@ "-Wno-implicit-int-conversion" "-Wno-missing-prototypes" "-Wno-missing-variable-declarations" + "-Wno-nullability-completeness" "-Wno-shadow" "-Wno-shorten-64-to-32" "-Wno-sign-compare" @@ -139,7 +140,6 @@ "-Winvalid-constexpr" "-Wliteral-conversion" "-Wmissing-declarations" - "-Wnullability-completeness" "-Woverlength-strings" "-Wpointer-arith" "-Wself-assign" @@ -165,6 +165,7 @@ "-Wno-implicit-int-conversion" "-Wno-missing-prototypes" "-Wno-missing-variable-declarations" + "-Wno-nullability-completeness" "-Wno-shadow" "-Wno-shorten-64-to-32" "-Wno-sign-compare"
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index 35319f0..23896e9 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl
@@ -24,6 +24,7 @@ "-Wno-implicit-int-conversion", "-Wno-missing-prototypes", "-Wno-missing-variable-declarations", + "-Wno-nullability-completeness", "-Wno-shadow", "-Wno-shorten-64-to-32", "-Wno-sign-compare", @@ -140,7 +141,6 @@ "-Winvalid-constexpr", "-Wliteral-conversion", "-Wmissing-declarations", - "-Wnullability-completeness", "-Woverlength-strings", "-Wpointer-arith", "-Wself-assign", @@ -166,6 +166,7 @@ "-Wno-implicit-int-conversion", "-Wno-missing-prototypes", "-Wno-missing-variable-declarations", + "-Wno-nullability-completeness", "-Wno-shadow", "-Wno-shorten-64-to-32", "-Wno-sign-compare",
diff --git a/absl/copts/copts.py b/absl/copts/copts.py index 941528e..8cf8f31 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py
@@ -93,6 +93,7 @@ "-Wno-implicit-int-conversion", "-Wno-missing-prototypes", "-Wno-missing-variable-declarations", + "-Wno-nullability-completeness", "-Wno-shadow", "-Wno-shorten-64-to-32", "-Wno-sign-compare",
diff --git a/absl/debugging/internal/decode_rust_punycode.h b/absl/debugging/internal/decode_rust_punycode.h index b1b1c97..44aad8a 100644 --- a/absl/debugging/internal/decode_rust_punycode.h +++ b/absl/debugging/internal/decode_rust_punycode.h
@@ -23,10 +23,10 @@ namespace debugging_internal { struct DecodeRustPunycodeOptions { - const char* punycode_begin; - const char* punycode_end; - char* out_begin; - char* out_end; + const char* absl_nonnull punycode_begin; + const char* absl_nonnull punycode_end; + char* absl_nonnull out_begin; + char* absl_nonnull out_end; }; // Given Rust Punycode in `punycode_begin .. punycode_end`, writes the
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index dc15b8e..5f62ebb 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc
@@ -484,36 +484,6 @@ static bool IsDigit(char c) { return c >= '0' && c <= '9'; } -// Returns true if "str" is a function clone suffix. These suffixes are used -// by GCC 4.5.x and later versions (and our locally-modified version of GCC -// 4.4.x) to indicate functions which have been cloned during optimization. -// We treat any sequence (.<alpha>+.<digit>+)+ as a function clone suffix. -// Additionally, '_' is allowed along with the alphanumeric sequence. -static bool IsFunctionCloneSuffix(const char *str) { - size_t i = 0; - while (str[i] != '\0') { - bool parsed = false; - // Consume a single [.<alpha> | _]*[.<digit>]* sequence. - if (str[i] == '.' && (IsAlpha(str[i + 1]) || str[i + 1] == '_')) { - parsed = true; - i += 2; - while (IsAlpha(str[i]) || str[i] == '_') { - ++i; - } - } - if (str[i] == '.' && IsDigit(str[i + 1])) { - parsed = true; - i += 2; - while (IsDigit(str[i])) { - ++i; - } - } - if (!parsed) - return false; - } - return true; // Consumed everything in "str". -} - static bool EndsWith(State *state, const char chr) { return state->parse_state.out_cur_idx > 0 && state->parse_state.out_cur_idx < state->out_end_idx && @@ -2932,7 +2902,7 @@ if (ParseMangledName(state)) { if (RemainingInput(state)[0] != '\0') { // Drop trailing function clone suffix, if any. - if (IsFunctionCloneSuffix(RemainingInput(state))) { + if (RemainingInput(state)[0] == '.') { return true; } // Append trailing version suffix if any.
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 9c8225a..2012184 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc
@@ -556,14 +556,15 @@ EXPECT_TRUE(Demangle("_ZL3Foov.part.9.165493.constprop.775.31805", tmp, sizeof(tmp))); EXPECT_STREQ("Foo()", tmp); - // Invalid (. without anything else), should not demangle. - EXPECT_FALSE(Demangle("_ZL3Foov.", tmp, sizeof(tmp))); - // Invalid (. with mix of alpha and digits), should not demangle. - EXPECT_FALSE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp))); - // Invalid (.clone. not followed by number), should not demangle. - EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp))); - // Invalid (.constprop. not followed by number), should not demangle. - EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp))); + // Other suffixes should demangle too. + EXPECT_TRUE(Demangle("_ZL3Foov.", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + EXPECT_TRUE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + EXPECT_TRUE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); } TEST(Demangle, Discriminators) {
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index c3182f1..7582f54 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc
@@ -29,6 +29,7 @@ #include <ostream> #include <set> #include <string> +#include <string_view> #include <tuple> #include <type_traits> #include <unordered_map> @@ -55,10 +56,6 @@ #include <filesystem> // NOLINT #endif -#ifdef ABSL_HAVE_STD_STRING_VIEW -#include <string_view> -#endif - namespace { using ::absl::hash_test_internal::is_hashable; @@ -495,22 +492,15 @@ } TEST(HashValueTest, WStringView) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else EXPECT_TRUE((is_hashable<std::wstring_view>::value)); EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( std::wstring_view(), std::wstring_view(L"ABC"), std::wstring_view(L"ABC"), std::wstring_view(L"Some other different string_view"), std::wstring_view(L"Iñtërnâtiônàlizætiøn")))); -#endif } TEST(HashValueTest, U16StringView) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else EXPECT_TRUE((is_hashable<std::u16string_view>::value)); EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( @@ -518,13 +508,9 @@ std::u16string_view(u"ABC"), std::u16string_view(u"Some other different string_view"), std::u16string_view(u"Iñtërnâtiônàlizætiøn")))); -#endif } TEST(HashValueTest, U32StringView) { -#ifndef ABSL_HAVE_STD_STRING_VIEW - GTEST_SKIP(); -#else EXPECT_TRUE((is_hashable<std::u32string_view>::value)); EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( @@ -532,7 +518,6 @@ std::u32string_view(U"ABC"), std::u32string_view(U"Some other different string_view"), std::u32string_view(U"Iñtërnâtiônàlizætiøn")))); -#endif } TEST(HashValueTest, StdFilesystemPath) {
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index c7916b5..63b3549 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h
@@ -65,6 +65,7 @@ #include <memory> #include <set> #include <string> +#include <string_view> #include <tuple> #include <type_traits> #include <unordered_map> @@ -92,10 +93,6 @@ #include <filesystem> // NOLINT #endif -#ifdef ABSL_HAVE_STD_STRING_VIEW -#include <string_view> -#endif - namespace absl { ABSL_NAMESPACE_BEGIN @@ -640,8 +637,6 @@ WeaklyMixedInteger{str.size()}); } -#ifdef ABSL_HAVE_STD_STRING_VIEW - // Support std::wstring_view, std::u16string_view and std::u32string_view. template <typename Char, typename H, typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value || @@ -653,8 +648,6 @@ WeaklyMixedInteger{str.size()}); } -#endif // ABSL_HAVE_STD_STRING_VIEW - #if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \ (!defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || \ __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000) && \
diff --git a/absl/log/CMakeLists.txt b/absl/log/CMakeLists.txt index 6aae05d..130897f 100644 --- a/absl/log/CMakeLists.txt +++ b/absl/log/CMakeLists.txt
@@ -218,6 +218,7 @@ absl::span absl::strerror absl::strings + absl::strings_internal absl::time ) @@ -395,6 +396,7 @@ DEPS absl::config absl::strings + absl::strings_internal absl::span )
diff --git a/absl/log/internal/BUILD.bazel b/absl/log/internal/BUILD.bazel index 44ec71b..953b690 100644 --- a/absl/log/internal/BUILD.bazel +++ b/absl/log/internal/BUILD.bazel
@@ -205,6 +205,7 @@ "//absl/log:log_sink_registry", "//absl/memory", "//absl/strings", + "//absl/strings:internal", "//absl/time", "//absl/types:span", ], @@ -218,6 +219,7 @@ deps = [ "//absl/base:config", "//absl/strings", + "//absl/strings:internal", "//absl/types:span", ], )
diff --git a/absl/log/internal/append_truncated.h b/absl/log/internal/append_truncated.h index f0e7912..d420a8b 100644 --- a/absl/log/internal/append_truncated.h +++ b/absl/log/internal/append_truncated.h
@@ -17,8 +17,10 @@ #include <cstddef> #include <cstring> +#include <string_view> #include "absl/base/config.h" +#include "absl/strings/internal/utf8.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" @@ -33,6 +35,32 @@ dst.remove_prefix(src.size()); return src.size(); } +// Likewise, but it also takes a wide character string and transforms it into a +// UTF-8 encoded byte string regardless of the current locale. +// - On platforms where `wchar_t` is 2 bytes (e.g., Windows), the input is +// treated as UTF-16. +// - On platforms where `wchar_t` is 4 bytes (e.g., Linux, macOS), the input +// is treated as UTF-32. +inline size_t AppendTruncated(std::wstring_view src, absl::Span<char> &dst) { + absl::strings_internal::ShiftState state; + size_t total_bytes_written = 0; + for (const wchar_t wc : src) { + // If the destination buffer might not be large enough to write the next + // character, stop. + if (dst.size() < absl::strings_internal::kMaxEncodedUTF8Size) break; + size_t bytes_written = + absl::strings_internal::WideToUtf8(wc, dst.data(), state); + if (bytes_written == static_cast<size_t>(-1)) { + // Invalid character. Encode REPLACEMENT CHARACTER (U+FFFD) instead. + constexpr wchar_t kReplacementCharacter = L'\uFFFD'; + bytes_written = absl::strings_internal::WideToUtf8(kReplacementCharacter, + dst.data(), state); + } + dst.remove_prefix(bytes_written); + total_bytes_written += bytes_written; + } + return total_bytes_written; +} // Likewise, but `n` copies of `c`. inline size_t AppendTruncated(char c, size_t n, absl::Span<char> &dst) { if (n > dst.size()) n = dst.size();
diff --git a/absl/log/internal/check_op.h b/absl/log/internal/check_op.h index dc7d19e..7253402 100644 --- a/absl/log/internal/check_op.h +++ b/absl/log/internal/check_op.h
@@ -224,7 +224,7 @@ void MakeCheckOpValueString(std::ostream& os, char v); void MakeCheckOpValueString(std::ostream& os, signed char v); void MakeCheckOpValueString(std::ostream& os, unsigned char v); -void MakeCheckOpValueString(std::ostream& os, const void* p); +void MakeCheckOpValueString(std::ostream& os, const void* absl_nullable p); namespace detect_specialization { @@ -266,8 +266,9 @@ double operator<<(std::ostream&, double value); long double operator<<(std::ostream&, long double value); bool operator<<(std::ostream&, bool value); -const void* operator<<(std::ostream&, const void* value); -const void* operator<<(std::ostream&, std::nullptr_t); +const void* absl_nullable operator<<(std::ostream&, + const void* absl_nullable value); +const void* absl_nullable operator<<(std::ostream&, std::nullptr_t); // These `char` overloads are specified like this in the standard, so we have to // write them exactly the same to ensure the call is ambiguous. @@ -281,13 +282,14 @@ template <typename Traits> unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char); template <typename Traits> -const char* operator<<(std::basic_ostream<char, Traits>&, const char*); +const char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&, + const char* absl_nonnull); template <typename Traits> -const signed char* operator<<(std::basic_ostream<char, Traits>&, - const signed char*); +const signed char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&, + const signed char* absl_nonnull); template <typename Traits> -const unsigned char* operator<<(std::basic_ostream<char, Traits>&, - const unsigned char*); +const unsigned char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&, + const unsigned char* absl_nonnull); // This overload triggers when the call is not ambiguous. // It means that T is being printed with some overload not on this list. @@ -312,7 +314,8 @@ void Append(absl::string_view text); void Append(size_t length, char ch); - friend void AbslFormatFlush(StringifySink* sink, absl::string_view text); + friend void AbslFormatFlush(StringifySink* absl_nonnull sink, + absl::string_view text); private: std::ostream& os_; @@ -376,10 +379,12 @@ ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char); ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&); ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&); -ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char*); -ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const signed char*); -ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const unsigned char*); -ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*); +ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char* absl_nonnull); +ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN( + const signed char* absl_nonnull); +ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN( + const unsigned char* absl_nonnull); +ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void* absl_nonnull); #undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN // `ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT` skips formatting the Check_OP result
diff --git a/absl/log/internal/log_message.cc b/absl/log/internal/log_message.cc index aaaaf03..07d17a0 100644 --- a/absl/log/internal/log_message.cc +++ b/absl/log/internal/log_message.cc
@@ -27,10 +27,12 @@ #include <algorithm> #include <array> #include <atomic> +#include <cwchar> #include <ios> #include <memory> #include <ostream> #include <string> +#include <string_view> #include <tuple> #include "absl/base/attributes.h" @@ -47,12 +49,14 @@ #include "absl/log/internal/globals.h" #include "absl/log/internal/log_format.h" #include "absl/log/internal/log_sink_set.h" +#include "absl/log/internal/nullguard.h" #include "absl/log/internal/proto.h" #include "absl/log/internal/structured_proto.h" #include "absl/log/log_entry.h" #include "absl/log/log_sink.h" #include "absl/log/log_sink_registry.h" #include "absl/memory/memory.h" +#include "absl/strings/internal/utf8.h" #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" @@ -403,6 +407,35 @@ CopyToEncodedBuffer<StringType::kNotLiteral>(v); return *this; } + +LogMessage& LogMessage::operator<<(const std::wstring& v) { + CopyToEncodedBuffer<StringType::kNotLiteral>(v); + return *this; +} + +LogMessage& LogMessage::operator<<(std::wstring_view v) { + CopyToEncodedBuffer<StringType::kNotLiteral>(v); + return *this; +} + +template <> +LogMessage& LogMessage::operator<< <const wchar_t*>( + const wchar_t* absl_nullable const& v) { + if (v == nullptr) { + CopyToEncodedBuffer<StringType::kNotLiteral>( + absl::string_view(kCharNull.data(), kCharNull.size() - 1)); + } else { + CopyToEncodedBuffer<StringType::kNotLiteral>( + std::wstring_view(v, wcsnlen(v, data_->encoded_remaining().size()))); + } + return *this; +} + +LogMessage& LogMessage::operator<<(wchar_t v) { + CopyToEncodedBuffer<StringType::kNotLiteral>(std::wstring_view(&v, 1)); + return *this; +} + LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) { OstreamView view(*data_); data_->manipulated << m; @@ -625,6 +658,37 @@ template void LogMessage::CopyToEncodedBuffer< LogMessage::StringType::kNotLiteral>(char ch, size_t num); +template <LogMessage::StringType str_type> +void LogMessage::CopyToEncodedBuffer(std::wstring_view str) { + auto encoded_remaining_copy = data_->encoded_remaining(); + constexpr uint8_t tag_value = str_type == StringType::kLiteral + ? ValueTag::kStringLiteral + : ValueTag::kString; + size_t max_str_byte_length = + absl::strings_internal::kMaxEncodedUTF8Size * str.length(); + auto value_start = + EncodeMessageStart(EventTag::kValue, + BufferSizeFor(tag_value, WireType::kLengthDelimited) + + max_str_byte_length, + &encoded_remaining_copy); + auto str_start = EncodeMessageStart(tag_value, max_str_byte_length, + &encoded_remaining_copy); + if (str_start.data()) { + log_internal::AppendTruncated(str, encoded_remaining_copy); + EncodeMessageLength(str_start, &encoded_remaining_copy); + EncodeMessageLength(value_start, &encoded_remaining_copy); + data_->encoded_remaining() = encoded_remaining_copy; + } else { + // The field header(s) did not fit; zero `encoded_remaining()` so we don't + // write anything else later. + data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size()); + } +} +template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>( + std::wstring_view str); +template void LogMessage::CopyToEncodedBuffer< + LogMessage::StringType::kNotLiteral>(std::wstring_view str); + template void LogMessage::CopyToEncodedBufferWithStructuredProtoField< LogMessage::StringType::kLiteral>(StructuredProtoField field, absl::string_view str); @@ -682,17 +746,13 @@ *this << "Check failed: " << failure_msg << " "; } -LogMessageFatal::~LogMessageFatal() { - FailWithoutStackTrace(); -} +LogMessageFatal::~LogMessageFatal() { FailWithoutStackTrace(); } LogMessageDebugFatal::LogMessageDebugFatal(const char* absl_nonnull file, int line) : LogMessage(file, line, absl::LogSeverity::kFatal) {} -LogMessageDebugFatal::~LogMessageDebugFatal() { - FailWithoutStackTrace(); -} +LogMessageDebugFatal::~LogMessageDebugFatal() { FailWithoutStackTrace(); } LogMessageQuietlyDebugFatal::LogMessageQuietlyDebugFatal( const char* absl_nonnull file, int line) @@ -700,9 +760,7 @@ SetFailQuietly(); } -LogMessageQuietlyDebugFatal::~LogMessageQuietlyDebugFatal() { - FailQuietly(); -} +LogMessageQuietlyDebugFatal::~LogMessageQuietlyDebugFatal() { FailQuietly(); } LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* absl_nonnull file, int line) @@ -717,9 +775,7 @@ *this << "Check failed: " << failure_msg << " "; } -LogMessageQuietlyFatal::~LogMessageQuietlyFatal() { - FailQuietly(); -} +LogMessageQuietlyFatal::~LogMessageQuietlyFatal() { FailQuietly(); } #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(pop) #endif
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h index e7eff47..1aaf05e 100644 --- a/absl/log/internal/log_message.h +++ b/absl/log/internal/log_message.h
@@ -27,12 +27,15 @@ #ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_ #define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_ +#include <wchar.h> + #include <cstddef> #include <ios> #include <memory> #include <ostream> #include <streambuf> #include <string> +#include <string_view> #include <type_traits> #include "absl/base/attributes.h" @@ -158,6 +161,13 @@ LogMessage& operator<<(const std::string& v); LogMessage& operator<<(absl::string_view v); + // Wide string overloads (since std::ostream does not provide them). + LogMessage& operator<<(const std::wstring& v); + LogMessage& operator<<(std::wstring_view v); + // `const wchar_t*` is handled by `operator<< <const wchar_t*>`. + LogMessage& operator<<(wchar_t* absl_nullable v); + LogMessage& operator<<(wchar_t v); + // Handle stream manipulators e.g. std::endl. LogMessage& operator<<(std::ostream& (*absl_nonnull m)(std::ostream& os)); LogMessage& operator<<(std::ios_base& (*absl_nonnull m)(std::ios_base& os)); @@ -169,17 +179,20 @@ // this template for every value of `SIZE` encountered in each source code // file. That significantly increases linker input sizes. Inlining is cheap // because the argument to this overload is almost always a string literal so - // the call to `strlen` can be replaced at compile time. The overload for - // `char[]` below should not be inlined. The compiler typically does not have - // the string at compile time and cannot replace the call to `strlen` so - // inlining it increases the binary size. See the discussion on + // the call to `strlen` can be replaced at compile time. The overloads for + // `char[]`/`wchar_t[]` below should not be inlined. The compiler typically + // does not have the string at compile time and cannot replace the call to + // `strlen` so inlining it increases the binary size. See the discussion on // cl/107527369. template <int SIZE> LogMessage& operator<<(const char (&buf)[SIZE]); + template <int SIZE> + LogMessage& operator<<(const wchar_t (&buf)[SIZE]); // This prevents non-const `char[]` arrays from looking like literals. template <int SIZE> LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE; + // `wchar_t[SIZE]` is handled by `operator<< <const wchar_t*>`. // Types that support `AbslStringify()` are serialized that way. // Types that don't support `AbslStringify()` but do support streaming into a @@ -243,6 +256,8 @@ void CopyToEncodedBuffer(absl::string_view str) ABSL_ATTRIBUTE_NOINLINE; template <StringType str_type> void CopyToEncodedBuffer(char ch, size_t num) ABSL_ATTRIBUTE_NOINLINE; + template <StringType str_type> + void CopyToEncodedBuffer(std::wstring_view str) ABSL_ATTRIBUTE_NOINLINE; // Copies `field` to the encoded buffer, then appends `str` after it // (truncating `str` if necessary to fit). @@ -273,6 +288,22 @@ absl_nonnull std::unique_ptr<LogMessageData> data_; }; +// Explicitly specializes the generic operator<< for `const wchar_t*` +// arguments. +// +// This method is used instead of a non-template `const wchar_t*` overload, +// as the latter was found to take precedence over the array template +// (`operator<<(const wchar_t(&)[SIZE])`) when handling string literals. +// This specialization ensures the array template now correctly processes +// literals. +template <> +LogMessage& LogMessage::operator<< <const wchar_t*>( + const wchar_t* absl_nullable const& v); + +inline LogMessage& LogMessage::operator<<(wchar_t* absl_nullable v) { + return operator<<(const_cast<const wchar_t*>(v)); +} + // Helper class so that `AbslStringify()` can modify the LogMessage. class StringifySink final { public: @@ -317,6 +348,12 @@ return *this; } +template <int SIZE> +LogMessage& LogMessage::operator<<(const wchar_t (&buf)[SIZE]) { + CopyToEncodedBuffer<StringType::kLiteral>(buf); + return *this; +} + // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE` template <int SIZE> LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) { @@ -358,6 +395,10 @@ size_t num); extern template void LogMessage::CopyToEncodedBuffer< LogMessage::StringType::kNotLiteral>(char ch, size_t num); +extern template void LogMessage::CopyToEncodedBuffer< + LogMessage::StringType::kLiteral>(std::wstring_view str); +extern template void LogMessage::CopyToEncodedBuffer< + LogMessage::StringType::kNotLiteral>(std::wstring_view str); // `LogMessageFatal` ensures the process will exit in failure after logging this // message.
diff --git a/absl/log/log_format_test.cc b/absl/log/log_format_test.cc index ecd6968..f4e33c9 100644 --- a/absl/log/log_format_test.cc +++ b/absl/log/log_format_test.cc
@@ -15,12 +15,14 @@ #include <math.h> +#include <cstring> #include <iomanip> #include <ios> #include <limits> #include <ostream> #include <sstream> #include <string> +#include <string_view> #include <type_traits> #ifdef __ANDROID__ @@ -28,6 +30,7 @@ #endif #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/base/config.h" #include "absl/log/check.h" #include "absl/log/internal/test_matchers.h" #include "absl/log/log.h" @@ -44,6 +47,7 @@ using ::absl::log_internal::RawEncodedMessage; using ::absl::log_internal::TextMessage; using ::absl::log_internal::TextPrefix; +using ::testing::_; using ::testing::AllOf; using ::testing::AnyOf; using ::testing::Each; @@ -124,6 +128,33 @@ LOG(INFO) << value; } +TEST(WideCharLogFormatTest, Printable) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("€")), + ENCODED_MESSAGE(HasValues( + ElementsAre(ValueWithStr(Eq("€")))))))); + + test_sink.StartCapturingLogs(); + const wchar_t value = L'\u20AC'; + LOG(INFO) << value; +} + +TEST(WideCharLogFormatTest, Unprintable) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + // Using NEL (Next Line) Unicode character (U+0085). + // It is encoded as "\xC2\x85" in UTF-8. + constexpr wchar_t wide_value = L'\u0085'; + constexpr char value[] = "\xC2\x85"; + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(value)), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithStr(Eq(value)))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << wide_value; +} + template <typename T> class UnsignedIntLogFormatTest : public testing::Test {}; using UnsignedIntTypes = Types<unsigned short, unsigned int, // NOLINT @@ -635,7 +666,7 @@ template <typename T> class VoidPtrLogFormatTest : public testing::Test {}; -using VoidPtrTypes = Types<void *, const void *>; +using VoidPtrTypes = Types<void*, const void*>; TYPED_TEST_SUITE(VoidPtrLogFormatTest, VoidPtrTypes); TYPED_TEST(VoidPtrLogFormatTest, Null) { @@ -676,11 +707,10 @@ template <typename T> class VolatilePtrLogFormatTest : public testing::Test {}; -using VolatilePtrTypes = - Types<volatile void*, const volatile void*, volatile char*, - const volatile char*, volatile signed char*, - const volatile signed char*, volatile unsigned char*, - const volatile unsigned char*>; +using VolatilePtrTypes = Types< + volatile void*, const volatile void*, volatile char*, const volatile char*, + volatile signed char*, const volatile signed char*, volatile unsigned char*, + const volatile unsigned char*, volatile wchar_t*, const volatile wchar_t*>; TYPED_TEST_SUITE(VolatilePtrLogFormatTest, VolatilePtrTypes); TYPED_TEST(VolatilePtrLogFormatTest, Null) { @@ -784,6 +814,38 @@ LOG(INFO) << value; } +template <typename T> +class WideCharPtrLogFormatTest : public testing::Test {}; +using WideCharPtrTypes = Types<wchar_t, const wchar_t>; +TYPED_TEST_SUITE(WideCharPtrLogFormatTest, WideCharPtrTypes); + +TYPED_TEST(WideCharPtrLogFormatTest, Null) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + TypeParam* const value = nullptr; + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("(null)")), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithStr(Eq("(null)")))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << value; +} + +TYPED_TEST(WideCharPtrLogFormatTest, NonNull) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + TypeParam data[] = {'v', 'a', 'l', 'u', 'e', '\0'}; + TypeParam* const value = data; + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("value")), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithStr(Eq("value")))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << value; +} + TEST(BoolLogFormatTest, True) { absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); @@ -836,6 +898,17 @@ LOG(INFO) << "value"; } +TEST(LogFormatTest, WideStringLiteral) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("value")), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithLiteral(Eq("value")))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << L"value"; +} + TEST(LogFormatTest, CharArray) { absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); @@ -854,6 +927,125 @@ LOG(INFO) << value; } +TEST(LogFormatTest, WideCharArray) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + wchar_t value[] = L"value"; + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("value")), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithStr(Eq("value")))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << value; +} + +// Comprehensive test string for validating wchar_t to UTF-8 conversion. +// See details in absl/strings/internal/utf8_test.cc. +// +// clang-format off +#define ABSL_LOG_INTERNAL_WIDE_LITERAL L"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩❤️💋👨 中" +#define ABSL_LOG_INTERNAL_UTF8_LITERAL u8"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩❤️💋👨 中" +// clang-format on + +absl::string_view GetUtf8TestString() { + // `u8""` forces UTF-8 encoding; MSVC will default to e.g. CP1252 (and warn) + // without it. However, the resulting character type differs between pre-C++20 + // (`char`) and C++20 (`char8_t`). So we reinterpret_cast to `char*` and wrap + // it in a `string_view`. + static const absl::string_view kUtf8TestString( + reinterpret_cast<const char*>(ABSL_LOG_INTERNAL_UTF8_LITERAL), + sizeof(ABSL_LOG_INTERNAL_UTF8_LITERAL) - 1); + return kUtf8TestString; +} + +template <typename T> +class WideStringLogFormatTest : public testing::Test {}; +using StringTypes = + Types<std::wstring, const std::wstring, wchar_t[], const wchar_t*>; +TYPED_TEST_SUITE(WideStringLogFormatTest, StringTypes); + +TYPED_TEST(WideStringLogFormatTest, NonLiterals) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + TypeParam value = ABSL_LOG_INTERNAL_WIDE_LITERAL; + absl::string_view utf8_value = GetUtf8TestString(); + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithStr(Eq(utf8_value)))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << value; +} + +TEST(WideStringLogFormatTest, StringView) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + std::wstring_view value = ABSL_LOG_INTERNAL_WIDE_LITERAL; + absl::string_view utf8_value = GetUtf8TestString(); + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithStr(Eq(utf8_value)))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << value; +} + +TEST(WideStringLogFormatTest, Literal) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + absl::string_view utf8_value = GetUtf8TestString(); + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithLiteral(Eq(utf8_value)))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << ABSL_LOG_INTERNAL_WIDE_LITERAL; +} + +#undef ABSL_LOG_INTERNAL_WIDE_LITERAL +#undef ABSL_LOG_INTERNAL_UTF8_LITERAL + +TYPED_TEST(WideStringLogFormatTest, InvalidCharactersAreReplaced) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + TypeParam value = L"AAA \xDC00 BBB"; + // NOLINTNEXTLINE(readability/utf8) + absl::string_view utf8_value = "AAA � BBB"; + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)), + ENCODED_MESSAGE(HasValues(ElementsAre( + ValueWithStr(Eq(utf8_value)))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << value; +} + +TYPED_TEST(WideStringLogFormatTest, EmptyWideString) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + TypeParam value = L""; + + EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("")), + ENCODED_MESSAGE(HasValues( + ElementsAre(ValueWithStr(Eq("")))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << value; +} + +TEST(WideStringLogFormatTest, MixedNarrowAndWideStrings) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + EXPECT_CALL(test_sink, Log(_, _, "1234")); + + test_sink.StartCapturingLogs(); + LOG(INFO) << "1" << L"2" << "3" << L"4"; +} + class CustomClass {}; std::ostream& operator<<(std::ostream& os, const CustomClass&) { return os << "CustomClass{}"; @@ -1675,6 +1867,29 @@ LOG(INFO) << std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x'); } +TEST(StructuredLoggingOverflowTest, TruncatesWideStrings) { + absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); + + // This message is too long and should be truncated to some unspecified size + // no greater than the buffer size but not too much less either. It should be + // truncated rather than discarded. + EXPECT_CALL( + test_sink, + Send(AllOf( + TextMessage(AllOf( + SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256), + Le(absl::log_internal::kLogMessageBufferSize))), + Each(Eq('x')))), + ENCODED_MESSAGE(HasOneStrThat(AllOf( + SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256), + Le(absl::log_internal::kLogMessageBufferSize))), + Each(Eq('x')))))))); + + test_sink.StartCapturingLogs(); + LOG(INFO) << std::wstring(2 * absl::log_internal::kLogMessageBufferSize, + L'x'); +} + struct StringLike { absl::string_view data; };
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 5e57a15..ba57e52 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h
@@ -38,6 +38,7 @@ #include <cstddef> #include <functional> #include <string> +#include <string_view> #include <type_traits> #include <vector> @@ -48,10 +49,6 @@ #include <span> // NOLINT(build/c++20) #endif -#ifdef ABSL_HAVE_STD_STRING_VIEW -#include <string_view> -#endif - // Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17 // feature. #if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__) @@ -507,10 +504,8 @@ struct IsView : std::integral_constant<bool, std::is_pointer<T>::value || IsViewImpl<T>::value> {}; -#ifdef ABSL_HAVE_STD_STRING_VIEW template <typename Char, typename Traits> struct IsView<std::basic_string_view<Char, Traits>> : std::true_type {}; -#endif #ifdef __cpp_lib_span template <typename T>
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc index bcf90d7..7c2dbbc 100644 --- a/absl/meta/type_traits_test.cc +++ b/absl/meta/type_traits_test.cc
@@ -16,6 +16,7 @@ #include <cstdint> #include <string> +#include <string_view> #include <type_traits> #include <utility> #include <vector> @@ -26,10 +27,6 @@ #include "absl/time/clock.h" #include "absl/time/time.h" -#ifdef ABSL_HAVE_STD_STRING_VIEW -#include <string_view> -#endif - namespace { using ::testing::StaticAssertTypeEq; @@ -45,12 +42,10 @@ "string is an owner, not a view"); static_assert(IsOwnerAndNotView<std::wstring>::value, "wstring is an owner, not a view"); -#ifdef ABSL_HAVE_STD_STRING_VIEW static_assert(!IsOwnerAndNotView<std::string_view>::value, "string_view is a view, not an owner"); static_assert(!IsOwnerAndNotView<std::wstring_view>::value, "wstring_view is a view, not an owner"); -#endif template <class T, class U> struct simple_pair {
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h index ca7c550..e986611 100644 --- a/absl/status/internal/statusor_internal.h +++ b/absl/status/internal/statusor_internal.h
@@ -39,7 +39,8 @@ struct HasConversionOperatorToStatusOr : std::false_type {}; template <typename T, typename U> -void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]); +void test(char (*absl_nullable)[sizeof( + std::declval<U>().operator absl::StatusOr<T>())]); template <typename T, typename U> struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
diff --git a/absl/status/statusor.h b/absl/status/statusor.h index 5257af0..6142a2f 100644 --- a/absl/status/statusor.h +++ b/absl/status/statusor.h
@@ -520,8 +520,8 @@ // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined. // // Use `this->ok()` to verify that there is a current value. - const T* operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND; - T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND; + const T* absl_nonnull operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND; + T* absl_nonnull operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND; // StatusOr<T>::value_or() //
diff --git a/absl/strings/cordz_test_helpers.h b/absl/strings/cordz_test_helpers.h index 9811709..66232db 100644 --- a/absl/strings/cordz_test_helpers.h +++ b/absl/strings/cordz_test_helpers.h
@@ -34,16 +34,15 @@ ABSL_NAMESPACE_BEGIN // Returns the CordzInfo for the cord, or nullptr if the cord is not sampled. -inline const cord_internal::CordzInfo* absl_nullable GetCordzInfoForTesting( +inline const cord_internal::CordzInfo* GetCordzInfoForTesting( const Cord& cord) { if (!cord.contents_.is_tree()) return nullptr; return cord.contents_.cordz_info(); } // Returns true if the provided cordz_info is in the list of sampled cords. -inline bool CordzInfoIsListed( - const cord_internal::CordzInfo* absl_nonnull cordz_info, - cord_internal::CordzSampleToken token = {}) { +inline bool CordzInfoIsListed(const cord_internal::CordzInfo* cordz_info, + cord_internal::CordzSampleToken token = {}) { for (const cord_internal::CordzInfo& info : token) { if (cordz_info == &info) return true; } @@ -121,7 +120,7 @@ // Wrapper struct managing a small CordRep `rep` struct TestCordRep { - cord_internal::CordRepFlat* absl_nonnull rep; + cord_internal::CordRepFlat* rep; TestCordRep() { rep = cord_internal::CordRepFlat::New(100);
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h index b55b412..cf1f703 100644 --- a/absl/strings/internal/cord_internal.h +++ b/absl/strings/internal/cord_internal.h
@@ -635,7 +635,7 @@ poison(); } - void CopyInlineToString(std::string* absl_nonnull dst) const { + void CopyInlineToString(std::string* dst) const { assert(!is_tree()); // As Cord can store only 15 bytes it is smaller than std::string's // small string optimization buffer size. Therefore we will always trigger
diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc index 103c85d..01e4e42 100644 --- a/absl/strings/internal/str_format/arg.cc +++ b/absl/strings/internal/str_format/arg.cc
@@ -26,6 +26,7 @@ #include <cstring> #include <cwchar> #include <string> +#include <string_view> #include <type_traits> #include "absl/base/config.h" @@ -38,10 +39,6 @@ #include "absl/strings/numbers.h" #include "absl/strings/string_view.h" -#if defined(ABSL_HAVE_STD_STRING_VIEW) -#include <string_view> -#endif - namespace absl { ABSL_NAMESPACE_BEGIN namespace str_format_internal { @@ -459,13 +456,11 @@ return {ConvertStringArg(v, conv, sink)}; } -#if defined(ABSL_HAVE_STD_STRING_VIEW) StringConvertResult FormatConvertImpl(std::wstring_view v, const FormatConversionSpecImpl conv, FormatSinkImpl* sink) { return {ConvertStringArg(v.data(), v.size(), conv, sink)}; } -#endif StringPtrConvertResult FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv,
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index 309161d..021013f 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h
@@ -26,6 +26,7 @@ #include <memory> #include <sstream> #include <string> +#include <string_view> #include <type_traits> #include <utility> @@ -37,10 +38,6 @@ #include "absl/strings/internal/str_format/extension.h" #include "absl/strings/string_view.h" -#if defined(ABSL_HAVE_STD_STRING_VIEW) -#include <string_view> -#endif - namespace absl { ABSL_NAMESPACE_BEGIN @@ -228,7 +225,6 @@ StringConvertResult FormatConvertImpl(string_view v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); -#if defined(ABSL_HAVE_STD_STRING_VIEW) StringConvertResult FormatConvertImpl(std::wstring_view v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); @@ -239,7 +235,6 @@ return FormatConvertImpl(absl::string_view(v.data(), v.size()), conv, sink); } #endif // !ABSL_USES_STD_STRING_VIEW -#endif // ABSL_HAVE_STD_STRING_VIEW using StringPtrConvertResult = ArgConvertResult<FormatConversionCharSetUnion( FormatConversionCharSetInternal::s, @@ -651,15 +646,10 @@ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const wchar_t*, __VA_ARGS__); \ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring, __VA_ARGS__) -#if defined(ABSL_HAVE_STD_STRING_VIEW) #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \ ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_( \ __VA_ARGS__); \ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring_view, __VA_ARGS__) -#else -#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \ - ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(__VA_ARGS__) -#endif ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index baffe05..e4fa44e 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc
@@ -27,6 +27,7 @@ #include <set> #include <sstream> #include <string> +#include <string_view> #include <thread> // NOLINT #include <type_traits> #include <vector> @@ -46,10 +47,6 @@ #include "absl/types/optional.h" #include "absl/types/span.h" -#if defined(ABSL_HAVE_STD_STRING_VIEW) -#include <string_view> -#endif - namespace absl { ABSL_NAMESPACE_BEGIN namespace str_format_internal { @@ -322,10 +319,8 @@ TestStringConvert(std::string("hello")); TestStringConvert(std::wstring(L"hello")); TestStringConvert(string_view("hello")); -#if defined(ABSL_HAVE_STD_STRING_VIEW) TestStringConvert(std::string_view("hello")); TestStringConvert(std::wstring_view(L"hello")); -#endif // ABSL_HAVE_STD_STRING_VIEW } TEST_F(FormatConvertTest, NullString) {
diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h index eafd8a3..84db0f6 100644 --- a/absl/strings/str_cat.h +++ b/absl/strings/str_cat.h
@@ -111,7 +111,7 @@ #include "absl/strings/numbers.h" #include "absl/strings/string_view.h" -#if defined(ABSL_HAVE_STD_STRING_VIEW) && !defined(ABSL_USES_STD_STRING_VIEW) +#if !defined(ABSL_USES_STD_STRING_VIEW) #include <string_view> #endif @@ -191,26 +191,26 @@ template <typename Int> explicit Hex( Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<sizeof(Int) == 1 && - !std::is_pointer<Int>::value>::type* = nullptr) + std::enable_if_t<sizeof(Int) == 1 && !std::is_pointer<Int>::value, bool> = + true) : Hex(spec, static_cast<uint8_t>(v)) {} template <typename Int> explicit Hex( Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<sizeof(Int) == 2 && - !std::is_pointer<Int>::value>::type* = nullptr) + std::enable_if_t<sizeof(Int) == 2 && !std::is_pointer<Int>::value, bool> = + true) : Hex(spec, static_cast<uint16_t>(v)) {} template <typename Int> explicit Hex( Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<sizeof(Int) == 4 && - !std::is_pointer<Int>::value>::type* = nullptr) + std::enable_if_t<sizeof(Int) == 4 && !std::is_pointer<Int>::value, bool> = + true) : Hex(spec, static_cast<uint32_t>(v)) {} template <typename Int> explicit Hex( Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<sizeof(Int) == 8 && - !std::is_pointer<Int>::value>::type* = nullptr) + std::enable_if_t<sizeof(Int) == 8 && !std::is_pointer<Int>::value, bool> = + true) : Hex(spec, static_cast<uint64_t>(v)) {} template <typename Pointee> explicit Hex(Pointee* absl_nullable v, PadSpec spec = absl::kNoPad) @@ -262,7 +262,7 @@ template <typename Int> explicit Dec(Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr) + std::enable_if_t<sizeof(Int) <= 8, bool> = true) : value(v >= 0 ? static_cast<uint64_t>(v) : uint64_t{0} - static_cast<uint64_t>(v)), width(spec == absl::kNoPad ? 1 @@ -366,7 +366,7 @@ ABSL_ATTRIBUTE_LIFETIME_BOUND) : piece_(pc) {} -#if defined(ABSL_HAVE_STD_STRING_VIEW) && !defined(ABSL_USES_STD_STRING_VIEW) +#if !defined(ABSL_USES_STD_STRING_VIEW) AlphaNum(std::string_view pc // NOLINT(runtime/explicit) ABSL_ATTRIBUTE_LIFETIME_BOUND) : piece_(pc.data(), pc.size()) {}
diff --git a/absl/strings/str_cat_test.cc b/absl/strings/str_cat_test.cc index 4de379e..a3bd42c 100644 --- a/absl/strings/str_cat_test.cc +++ b/absl/strings/str_cat_test.cc
@@ -21,6 +21,7 @@ #include <cstdlib> #include <limits> #include <string> +#include <string_view> #include <vector> #include "gtest/gtest.h" @@ -28,10 +29,6 @@ #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" -#if defined(ABSL_HAVE_STD_STRING_VIEW) -#include <string_view> -#endif - #ifdef __ANDROID__ // Android assert messages only go to system log, so death tests cannot inspect // the message for matching. @@ -219,13 +216,11 @@ EXPECT_EQ(result, ""); } -#if defined(ABSL_HAVE_STD_STRING_VIEW) TEST(StrCat, StdStringView) { std::string_view pieces[] = {"Hello", ", ", "World", "!"}; EXPECT_EQ(absl::StrCat(pieces[0], pieces[1], pieces[2], pieces[3]), "Hello, World!"); } -#endif // ABSL_HAVE_STD_STRING_VIEW TEST(StrCat, NullConstCharPtr) { const char* null = nullptr;
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc index 7064cc7..0a2a7a9 100644 --- a/absl/strings/string_view_test.cc +++ b/absl/strings/string_view_test.cc
@@ -34,7 +34,7 @@ #include "absl/base/config.h" #include "absl/meta/type_traits.h" -#if defined(ABSL_HAVE_STD_STRING_VIEW) || defined(__ANDROID__) +#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 // the message for matching.
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index 08f64e9..c93b1cc 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h
@@ -187,12 +187,13 @@ // vector<bool>::reference and const_reference require special help to convert // to `Arg` because it requires two user defined conversions. - template <typename T, - absl::enable_if_t< - std::is_class<T>::value && - (std::is_same<T, std::vector<bool>::reference>::value || - std::is_same<T, std::vector<bool>::const_reference>::value)>* = - nullptr> + template < + typename T, + std::enable_if_t< + std::is_class<T>::value && + (std::is_same<T, std::vector<bool>::reference>::value || + std::is_same<T, std::vector<bool>::const_reference>::value), + bool> = true> Arg(T value) // NOLINT(google-explicit-constructor) : Arg(static_cast<bool>(value)) {} @@ -237,7 +238,7 @@ : (1 << (*format - '0')); } -constexpr const char* SkipNumber(const char* absl_nonnull format) { +constexpr const char* absl_nonnull SkipNumber(const char* absl_nonnull format) { return !*format ? format : (format + 1); }
diff --git a/absl/types/span.h b/absl/types/span.h index 444b2ae..39e6a8a 100644 --- a/absl/types/span.h +++ b/absl/types/span.h
@@ -202,10 +202,11 @@ public: using element_type = T; using value_type = absl::remove_cv_t<T>; - // TODO(b/316099902) - pointer should be Nullable<T*>, but this makes it hard - // to recognize foreach loops as safe. - using pointer = T*; - using const_pointer = const T*; + // TODO(b/316099902) - pointer should be absl_nullable, but this makes it hard + // to recognize foreach loops as safe. absl_nullability_unknown is currently + // used to suppress -Wnullability-completeness warnings. + using pointer = T* absl_nullability_unknown; + using const_pointer = const T* absl_nullability_unknown; using reference = T&; using const_reference = const T&; using iterator = pointer;
diff --git a/ci/cmake_common.sh b/ci/cmake_common.sh index 3e14ca3..484230c 100644 --- a/ci/cmake_common.sh +++ b/ci/cmake_common.sh
@@ -14,6 +14,6 @@ # The commit of GoogleTest to be used in the CMake tests in this directory. # Keep this in sync with the commit in the MODULE.bazel file. -readonly ABSL_GOOGLETEST_VERSION="1.16.0" +readonly ABSL_GOOGLETEST_VERSION="1.17.0" readonly ABSL_GOOGLETEST_DOWNLOAD_URL="https://github.com/google/googletest/releases/download/v${ABSL_GOOGLETEST_VERSION}/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz"
diff --git a/ci/linux_arm_clang-latest_libcxx_bazel.sh b/ci/linux_arm_clang-latest_libcxx_bazel.sh index d9e5992..631a8bd 100755 --- a/ci/linux_arm_clang-latest_libcxx_bazel.sh +++ b/ci/linux_arm_clang-latest_libcxx_bazel.sh
@@ -51,12 +51,12 @@ BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +# Use Bazel Vendor mode to reduce reliance on external dependencies. +# See https://bazel.build/external/vendor and the Dockerfile for +# an explaination of how this works. +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}" fi for std in ${STD}; do @@ -71,13 +71,13 @@ --rm \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ - /bin/sh -c " + /bin/bash --login -c " cp -r /abseil-cpp-ro/* /abseil-cpp/ if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1 fi /usr/local/bin/bazel test ... \ - --action_env=CC=clang-18 \ + --action_env=CC=clang-19 \ --compilation_mode=\"${compilation_mode}\" \ --copt=\"${exceptions_mode}\" \ --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \
diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh index c83f3a0..cfc5510 100755 --- a/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh
@@ -73,32 +73,33 @@ --rm \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ + /bin/bash --login -c " /usr/local/bin/bazel test ... \ - --action_env="CC=/opt/llvm/clang/bin/clang" \ - --action_env="BAZEL_CXXOPTS=-std=${std}:-nostdinc++" \ - --action_env="BAZEL_LINKOPTS=-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \ - --action_env="CPLUS_INCLUDE_PATH=/opt/llvm/libcxx/include/c++/v1" \ - --compilation_mode="${compilation_mode}" \ - --copt="${exceptions_mode}" \ - --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \ - --copt="-fsanitize=address" \ - --copt="-fsanitize=${UBSAN_CHECKS}" \ - --copt="-fno-sanitize-recover=${UBSAN_CHECKS}" \ - --copt="-fno-sanitize-blacklist" \ + --action_env=\"CC=/opt/llvm/clang/bin/clang\" \ + --action_env=\"BAZEL_CXXOPTS=-std=${std}:-nostdinc++\" \ + --action_env=\"BAZEL_LINKOPTS=-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib\" \ + --action_env=\"CPLUS_INCLUDE_PATH=/opt/llvm/libcxx/include/c++/v1\" \ + --compilation_mode=\"${compilation_mode}\" \ + --copt=\"${exceptions_mode}\" \ + --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \ + --copt=\"-fsanitize=address\" \ + --copt=\"-fsanitize=${UBSAN_CHECKS}\" \ + --copt=\"-fno-sanitize-recover=${UBSAN_CHECKS}\" \ + --copt=\"-fno-sanitize-blacklist\" \ --copt=-Werror \ --enable_bzlmod=true \ --features=external_include_paths \ --keep_going \ - --linkopt="-fsanitize=address" \ - --linkopt="-fsanitize-link-c++-runtime" \ + --linkopt=\"-fsanitize=address\" \ + --linkopt=\"-fsanitize-link-c++-runtime\" \ --show_timestamps \ - --test_env="ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ - --test_env="UBSAN_OPTIONS=print_stacktrace=1" \ - --test_env="UBSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ + --test_env=\"ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer\" \ + --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \ + --test_env=\"UBSAN_OPTIONS=print_stacktrace=1\" \ + --test_env=\"UBSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer\" \ --test_output=errors \ - --test_tag_filters="-benchmark,-noasan" \ - ${BAZEL_EXTRA_ARGS:-} + --test_tag_filters=\"-benchmark,-noasan\" \ + ${BAZEL_EXTRA_ARGS:-}" done done done
diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh index 832a9d8..5c51d15 100755 --- a/ci/linux_clang-latest_libcxx_bazel.sh +++ b/ci/linux_clang-latest_libcxx_bazel.sh
@@ -51,12 +51,12 @@ BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +# Use Bazel Vendor mode to reduce reliance on external dependencies. +# See https://bazel.build/external/vendor and the Dockerfile for +# an explaination of how this works. +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}" fi for std in ${STD}; do @@ -71,7 +71,7 @@ --rm \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ - /bin/sh -c " + /bin/bash --login -c " cp -r /abseil-cpp-ro/* /abseil-cpp/ if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh index 82b4dd1..c9ea22d 100755 --- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh
@@ -51,12 +51,12 @@ BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +# Use Bazel Vendor mode to reduce reliance on external dependencies. +# See https://bazel.build/external/vendor and the Dockerfile for +# an explaination of how this works. +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}" fi for std in ${STD}; do @@ -70,28 +70,29 @@ --rm \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ + /bin/bash --login -c " /usr/local/bin/bazel test ... \ - --action_env="CC=/opt/llvm/clang/bin/clang" \ - --action_env="BAZEL_CXXOPTS=-std=${std}:-nostdinc++" \ - --action_env="BAZEL_LINKOPTS=-L/opt/llvm/libcxx-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \ - --action_env="CPLUS_INCLUDE_PATH=/opt/llvm/libcxx-tsan/include/c++/v1" \ - --build_tag_filters="-notsan" \ - --compilation_mode="${compilation_mode}" \ - --copt="${exceptions_mode}" \ - --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \ - --copt="-fsanitize=thread" \ - --copt="-fno-sanitize-blacklist" \ + --action_env=\"CC=/opt/llvm/clang/bin/clang\" \ + --action_env=\"BAZEL_CXXOPTS=-std=${std}:-nostdinc++\" \ + --action_env=\"BAZEL_LINKOPTS=-L/opt/llvm/libcxx-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib\" \ + --action_env=\"CPLUS_INCLUDE_PATH=/opt/llvm/libcxx-tsan/include/c++/v1\" \ + --build_tag_filters=\"-notsan\" \ + --compilation_mode=\"${compilation_mode}\" \ + --copt=\"${exceptions_mode}\" \ + --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \ + --copt=\"-fsanitize=thread\" \ + --copt=\"-fno-sanitize-blacklist\" \ --copt=-Werror \ --enable_bzlmod=true \ --features=external_include_paths \ --keep_going \ - --linkopt="-fsanitize=thread" \ + --linkopt=\"-fsanitize=thread\" \ --show_timestamps \ - --test_env="TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_env=\"TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer\" \ + --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \ --test_output=errors \ - --test_tag_filters="-benchmark,-notsan" \ - ${BAZEL_EXTRA_ARGS:-} + --test_tag_filters=\"-benchmark,-notsan\" \ + ${BAZEL_EXTRA_ARGS:-}" done done done
diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 06aef62..a1620e0 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh
@@ -51,12 +51,12 @@ BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +# Use Bazel Vendor mode to reduce reliance on external dependencies. +# See https://bazel.build/external/vendor and the Dockerfile for +# an explaination of how this works. +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}" fi for std in ${STD}; do @@ -70,26 +70,27 @@ --rm \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ + /bin/bash --login -c " /usr/local/bin/bazel test ... \ - --action_env="CC=/opt/llvm/clang/bin/clang" \ - --action_env="BAZEL_CXXOPTS=-std=${std}" \ - --compilation_mode="${compilation_mode}" \ - --copt="--gcc-toolchain=/usr/local" \ - --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \ - --copt="${exceptions_mode}" \ - --copt="-march=haswell" \ + --action_env=\"CC=/opt/llvm/clang/bin/clang\" \ + --action_env=\"BAZEL_CXXOPTS=-std=${std}\" \ + --compilation_mode=\"${compilation_mode}\" \ + --copt=\"--gcc-toolchain=/usr/local\" \ + --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \ + --copt=\"${exceptions_mode}\" \ + --copt=\"-march=haswell\" \ --copt=-Werror \ - --define="absl=1" \ + --define=\"absl=1\" \ --enable_bzlmod=true \ --features=external_include_paths \ --keep_going \ - --linkopt="--gcc-toolchain=/usr/local" \ + --linkopt=\"--gcc-toolchain=/usr/local\" \ --show_timestamps \ - --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \ + --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \ --test_output=errors \ --test_tag_filters=-benchmark \ - ${BAZEL_EXTRA_ARGS:-} + ${BAZEL_EXTRA_ARGS:-}" done done done
diff --git a/ci/linux_docker_containers.sh b/ci/linux_docker_containers.sh index 3f824a8..0f45471 100644 --- a/ci/linux_docker_containers.sh +++ b/ci/linux_docker_containers.sh
@@ -16,7 +16,7 @@ # Test scripts should source this file to get the identifiers. readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20230612" -readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218" -readonly LINUX_ARM_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_arm_hybrid-latest:20250224" -readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218" -readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205" +readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20250430" +readonly LINUX_ARM_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_arm_hybrid-latest:20250430" +readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20250430" +readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250430"
diff --git a/ci/linux_gcc-floor_libstdcxx_bazel.sh b/ci/linux_gcc-floor_libstdcxx_bazel.sh index 74d996a..b683b60 100755 --- a/ci/linux_gcc-floor_libstdcxx_bazel.sh +++ b/ci/linux_gcc-floor_libstdcxx_bazel.sh
@@ -51,12 +51,12 @@ BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +# Use Bazel Vendor mode to reduce reliance on external dependencies. +# See https://bazel.build/external/vendor and the Dockerfile for +# an explaination of how this works. +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}" fi for std in ${STD}; do @@ -70,22 +70,23 @@ --rm \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ + /bin/bash --login -c " /usr/local/bin/bazel test ... \ - --action_env="CC=/usr/local/bin/gcc" \ - --action_env="BAZEL_CXXOPTS=-std=${std}" \ - --compilation_mode="${compilation_mode}" \ - --copt="${exceptions_mode}" \ - --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \ + --action_env=\"CC=/usr/local/bin/gcc\" \ + --action_env=\"BAZEL_CXXOPTS=-std=${std}\" \ + --compilation_mode=\"${compilation_mode}\" \ + --copt=\"${exceptions_mode}\" \ + --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \ --copt=-Werror \ - --define="absl=1" \ + --define=\"absl=1\" \ --features=external_include_paths \ --keep_going \ --show_timestamps \ - --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \ + --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \ --test_output=errors \ --test_tag_filters=-benchmark \ - ${BAZEL_EXTRA_ARGS:-} + ${BAZEL_EXTRA_ARGS:-}" done done done
diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh index 2daa132..b092c1d 100755 --- a/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh
@@ -51,12 +51,12 @@ BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" fi -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" +# Use Bazel Vendor mode to reduce reliance on external dependencies. +# See https://bazel.build/external/vendor and the Dockerfile for +# an explaination of how this works. +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then + DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}" + BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}" fi for std in ${STD}; do @@ -71,7 +71,7 @@ --rm \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ - /bin/sh -c " + /bin/bash --login -c " cp -r /abseil-cpp-ro/* /abseil-cpp/ if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
diff --git a/ci/macos_xcode_bazel.sh b/ci/macos_xcode_bazel.sh index 51ffde8..b05cfac 100755 --- a/ci/macos_xcode_bazel.sh +++ b/ci/macos_xcode_bazel.sh
@@ -27,7 +27,7 @@ fi # If we are running on Kokoro, check for a versioned Bazel binary. -KOKORO_GFILE_BAZEL_BIN="bazel-8.0.0-darwin-x86_64" +KOKORO_GFILE_BAZEL_BIN="bazel-8.2.1-darwin-x86_64" if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}" chmod +x ${BAZEL_BIN} @@ -35,11 +35,10 @@ BAZEL_BIN="bazel" fi -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - BAZEL_EXTRA_ARGS="--distdir=${KOKORO_GFILE_DIR}/distdir ${BAZEL_EXTRA_ARGS:-}" +# Use Bazel Vendor mode to reduce reliance on external dependencies. +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then + tar -xf "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" -C "${TMP}/" + BAZEL_EXTRA_ARGS="--vendor_dir=\"${TMP}/abseil-cpp_vendor\" ${BAZEL_EXTRA_ARGS:-}" fi # Print the compiler and Bazel versions.
diff --git a/ci/windows_clangcl_bazel.bat b/ci/windows_clangcl_bazel.bat index f9512ef..26fd5af 100755 --- a/ci/windows_clangcl_bazel.bat +++ b/ci/windows_clangcl_bazel.bat
@@ -21,6 +21,14 @@ CD %~dp0\.. if %errorlevel% neq 0 EXIT /B 1 +:: Use Bazel Vendor mode to reduce reliance on external dependencies. +IF EXIST "%KOKORO_GFILE_DIR%\distdir\abseil-cpp_vendor.tar.gz" ( + tar --force-local -xf "%KOKORO_GFILE_DIR%\distdir\abseil-cpp_vendor.tar.gz" -C c:\ + SET VENDOR_FLAG=--vendor_dir=c:\abseil-cpp_vendor +) ELSE ( + SET VENDOR_FLAG= +) + :: Set the standard version, [c++17|c++20|c++latest] :: https://msdn.microsoft.com/en-us/library/mt490614.aspx :: The default is c++17 if not set on command line. @@ -39,7 +47,7 @@ :: /google/data/rw/teams/absl/kokoro/windows. :: :: TODO(absl-team): Remove -Wno-microsoft-cast -%KOKORO_GFILE_DIR%\bazel-8.0.0-windows-x86_64.exe ^ +%KOKORO_GFILE_DIR%\bazel-8.2.1-windows-x86_64.exe ^ test ... ^ --compilation_mode=%COMPILATION_MODE% ^ --compiler=clang-cl ^ @@ -47,7 +55,6 @@ --copt=-Wno-microsoft-cast ^ --cxxopt=/std:%STD% ^ --define=absl=1 ^ - --distdir=%KOKORO_GFILE_DIR%\distdir ^ --enable_bzlmod=true ^ --extra_execution_platforms=//:x64_windows-clang-cl ^ --extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl ^ @@ -55,7 +62,8 @@ --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" ^ --test_env=TZDIR="%CD%\absl\time\internal\cctz\testdata\zoneinfo" ^ --test_output=errors ^ - --test_tag_filters=-benchmark + --test_tag_filters=-benchmark ^ + %VENDOR_FLAG% if %errorlevel% neq 0 EXIT /B 1 EXIT /B 0
diff --git a/ci/windows_msvc_bazel.bat b/ci/windows_msvc_bazel.bat index e0cd016..bbb57b4 100755 --- a/ci/windows_msvc_bazel.bat +++ b/ci/windows_msvc_bazel.bat
@@ -18,6 +18,14 @@ CD %~dp0\.. if %errorlevel% neq 0 EXIT /B 1 +:: Use Bazel Vendor mode to reduce reliance on external dependencies. +IF EXIST "%KOKORO_GFILE_DIR%\distdir\abseil-cpp_vendor.tar.gz" ( + tar --force-local -xf "%KOKORO_GFILE_DIR%\distdir\abseil-cpp_vendor.tar.gz" -C c:\ + SET VENDOR_FLAG=--vendor_dir=c:\abseil-cpp_vendor +) ELSE ( + SET VENDOR_FLAG= +) + :: Set the standard version, [c++17|c++latest] :: https://msdn.microsoft.com/en-us/library/mt490614.aspx :: The default is c++17 if not set on command line. @@ -34,19 +42,19 @@ :: To upgrade Bazel, first download a new binary from :: https://github.com/bazelbuild/bazel/releases and copy it to :: /google/data/rw/teams/absl/kokoro/windows. -%KOKORO_GFILE_DIR%\bazel-8.0.0-windows-x86_64.exe ^ +"%KOKORO_GFILE_DIR%\bazel-8.2.1-windows-x86_64.exe" ^ test ... ^ --compilation_mode=%COMPILATION_MODE% ^ --copt=/WX ^ --copt=/std:%STD% ^ --define=absl=1 ^ - --distdir=%KOKORO_GFILE_DIR%\distdir ^ --enable_bzlmod=true ^ --keep_going ^ --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" ^ --test_env=TZDIR="%CD%\absl\time\internal\cctz\testdata\zoneinfo" ^ --test_output=errors ^ - --test_tag_filters=-benchmark + --test_tag_filters=-benchmark ^ + %VENDOR_FLAG% if %errorlevel% neq 0 EXIT /B 1 EXIT /B 0
diff --git a/ci/windows_msvc_cmake.bat b/ci/windows_msvc_cmake.bat index c2d9e42..62cdb70 100755 --- a/ci/windows_msvc_cmake.bat +++ b/ci/windows_msvc_cmake.bat
@@ -16,7 +16,7 @@ :: The version of GoogleTest to be used in the CMake tests in this directory. :: Keep this in sync with the version in the WORKSPACE file. -SET ABSL_GOOGLETEST_VERSION=1.16.0 +SET ABSL_GOOGLETEST_VERSION=1.17.0 SET ABSL_GOOGLETEST_DOWNLOAD_URL=https://github.com/google/googletest/releases/download/v%ABSL_GOOGLETEST_VERSION%/googletest-%ABSL_GOOGLETEST_VERSION%.tar.gz :: Replace '\' with '/' in Windows paths for CMake.