Skip to content

Commit

Permalink
Remove pre-C++17 workarounds for lack of std::launder
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 734142314
Change-Id: Ib1308def5a6ab9be8890c6a83e793d298b3c777f
  • Loading branch information
derekmauro authored and copybara-github committed Mar 6, 2025
1 parent bdbaf37 commit 0bd8438
Show file tree
Hide file tree
Showing 7 changed files with 5 additions and 46 deletions.
27 changes: 4 additions & 23 deletions absl/base/no_destructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,32 +161,13 @@ class NoDestructor {
new (&space_) T(std::forward<Args>(args)...);
}
absl::Nonnull<const T*> get() const {
return Launder(reinterpret_cast<const T*>(&space_));
return std::launder(reinterpret_cast<const T*>(&space_));
}
absl::Nonnull<T*> get() { return Launder(reinterpret_cast<T*>(&space_)); }

private:
template <typename P>
static absl::Nonnull<P*> Launder(absl::Nonnull<P*> p) {
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
return std::launder(p);
#elif ABSL_HAVE_BUILTIN(__builtin_launder)
return __builtin_launder(p);
#else
// When `std::launder` or equivalent are not available, we rely on
// undefined behavior, which works as intended on Abseil's officially
// supported platforms as of Q3 2023.
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
return p;
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
#endif
absl::Nonnull<T*> get() {
return std::launder(reinterpret_cast<T*>(&space_));
}

private:
alignas(T) unsigned char space_[sizeof(T)];
};

Expand Down
3 changes: 0 additions & 3 deletions absl/container/btree_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2674,8 +2674,6 @@ TEST(Btree, HeterogeneousInsertOrAssign) {
}
#endif

// This test requires std::launder for mutable key access in node handles.
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
TEST(Btree, NodeHandleMutableKeyAccess) {
{
absl::btree_map<std::string, std::string> map;
Expand All @@ -2701,7 +2699,6 @@ TEST(Btree, NodeHandleMutableKeyAccess) {
EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
}
}
#endif

struct MultiKey {
int i1;
Expand Down
3 changes: 0 additions & 3 deletions absl/container/flat_hash_map_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,6 @@ TEST(FlatHashMap, CForEachMutate) {
}
}

// This test requires std::launder for mutable key access in node handles.
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
TEST(FlatHashMap, NodeHandleMutableKeyAccess) {
flat_hash_map<std::string, std::string> map;

Expand All @@ -373,7 +371,6 @@ TEST(FlatHashMap, NodeHandleMutableKeyAccess) {

EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
}
#endif

TEST(FlatHashMap, Reserve) {
// Verify that if we reserve(size() + n) then we can perform n insertions
Expand Down
3 changes: 1 addition & 2 deletions absl/container/internal/common_policy_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ struct common_policy_traits {
old_slot)) {
return P::transfer(alloc, new_slot, old_slot);
}
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606

// This overload returns true_type for the trait below.
// The conditional_t is to make the enabler type dependent.
template <class Alloc,
Expand All @@ -135,7 +135,6 @@ struct common_policy_traits {
static_cast<const void*>(&element(old_slot)), sizeof(value_type));
return {};
}
#endif

template <class Alloc>
static void transfer_impl(Alloc* alloc, slot_type* new_slot,
Expand Down
8 changes: 0 additions & 8 deletions absl/container/internal/container_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,19 +374,13 @@ struct map_slot_policy {
return slot->value;
}

// When C++17 is available, we can use std::launder to provide mutable
// access to the key for use in node handle.
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
static K& mutable_key(slot_type* slot) {
// Still check for kMutableKeys so that we can avoid calling std::launder
// unless necessary because it can interfere with optimizations.
return kMutableKeys::value ? slot->key
: *std::launder(const_cast<K*>(
std::addressof(slot->value.first)));
}
#else // !(defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606)
static const K& mutable_key(slot_type* slot) { return key(slot); }
#endif

static const K& key(const slot_type* slot) {
return kMutableKeys::value ? slot->key : slot->value.first;
Expand Down Expand Up @@ -443,15 +437,13 @@ struct map_slot_policy {
typename absl::is_trivially_relocatable<value_type>::type();

emplace(new_slot);
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
if (is_relocatable) {
// TODO(b/247130232,b/251814870): remove casts after fixing warnings.
std::memcpy(static_cast<void*>(std::launder(&new_slot->value)),
static_cast<const void*>(&old_slot->value),
sizeof(value_type));
return is_relocatable;
}
#endif

if (kMutableKeys::value) {
absl::allocator_traits<Allocator>::construct(
Expand Down
4 changes: 0 additions & 4 deletions absl/container/internal/hash_policy_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,12 @@ struct hash_policy_traits : common_policy_traits<Policy> {

private:
struct ReturnKey {
// When C++17 is available, we can use std::launder to provide mutable
// access to the key for use in node handle.
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
template <class Key,
absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
static key_type& Impl(Key&& k, int) {
return *std::launder(
const_cast<key_type*>(std::addressof(std::forward<Key>(k))));
}
#endif

template <class Key>
static Key Impl(Key&& k, char) {
Expand Down
3 changes: 0 additions & 3 deletions absl/container/node_hash_map_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,6 @@ TEST(NodeHashMap, CForEachMutate) {
}
}

// This test requires std::launder for mutable key access in node handles.
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
TEST(NodeHashMap, NodeHandleMutableKeyAccess) {
node_hash_map<std::string, std::string> map;

Expand All @@ -335,7 +333,6 @@ TEST(NodeHashMap, NodeHandleMutableKeyAccess) {

EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
}
#endif

TEST(NodeHashMap, RecursiveTypeCompiles) {
struct RecursiveType {
Expand Down

0 comments on commit 0bd8438

Please sign in to comment.