From 038561296676d1cae4a3cee30f8c924befbb6083 Mon Sep 17 00:00:00 2001 From: Evan Brown Date: Tue, 12 Mar 2024 14:29:39 -0700 Subject: Add extern templates for common swisstable types. Motivation: mitigate linker input size increase from swisstable optimizations. Note: the changes in raw_hash_set.h are fixing build errors that happened when adding the explicit instantiations. The change in unchecked_deref is because set iterators have const reference access whereas map iterators have mutable reference access and the function is never actually called for sets (it's used in raw_hash_map) so it wasn't needed before. I'm not sure why the soo_slot/soo_iterator problems didn't cause compile errors earlier. PiperOrigin-RevId: 615174043 Change-Id: Iac5eb2332a76e9b70021156fbb2b8def47a5391d --- absl/container/internal/raw_hash_set.h | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'absl/container/internal') diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 258458b0..575491c7 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -1839,7 +1839,7 @@ class HashSetResizeHelper { // Reads `capacity` and updates all other fields based on the result of // the allocation. // - // It also may do the folowing actions: + // It also may do the following actions: // 1. initialize control bytes // 2. initialize slots // 3. deallocate old slots. @@ -2204,9 +2204,14 @@ class raw_hash_set { bool is_soo() const { return fits_in_soo(capacity()); } bool is_full_soo() const { return is_soo() && !empty(); } - // Give an early error when key_type is not hashable/eq. - auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k)); - auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k)); + // Give an early error when key_type is not hashable/eq. Definitions are + // provided because otherwise explicit template instantiation fails on MSVC. + auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k)) { + ABSL_UNREACHABLE(); + } + auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k)) { + ABSL_UNREACHABLE(); + } using AllocTraits = absl::allocator_traits; using SlotAlloc = typename absl::allocator_traits< @@ -2395,7 +2400,18 @@ class raw_hash_set { const_iterator operator++(int) { return inner_++; } friend bool operator==(const const_iterator& a, const const_iterator& b) { + // Suppress erroneous uninitialized memory errors on GCC. This seems to be + // because the slot pointer in the inner_ iterator is uninitialized, even + // though that pointer is not used when uninitialized. + // Similar bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112637. +#if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif return a.inner_ == b.inner_; +#if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif } friend bool operator!=(const const_iterator& a, const const_iterator& b) { return !(a == b); @@ -3719,7 +3735,9 @@ class raw_hash_set { return const_cast(this)->iterator_at(i); } - reference unchecked_deref(iterator it) { return it.unchecked_deref(); } + reference unchecked_deref(iterator it) { + return const_cast(it.unchecked_deref()); + } private: friend struct RawHashSetTestOnlyAccess; @@ -3769,13 +3787,13 @@ class raw_hash_set { return static_cast(common().soo_data()); } const slot_type* soo_slot() const { - return reinterpret_cast(this)->soo_slot(); + return const_cast(this)->soo_slot(); } iterator soo_iterator() { return {SooControl(), soo_slot(), common().generation_ptr()}; } const_iterator soo_iterator() const { - return reinterpret_cast(this)->soo_iterator(); + return const_cast(this)->soo_iterator(); } HashtablezInfoHandle infoz() { assert(!is_soo()); -- cgit v1.2.3