From 0d99e5aad4299d8e4b3bcf4bf1e1bea4a32a9044 Mon Sep 17 00:00:00 2001 From: Victor Hugo Vianna Silva Date: Tue, 28 Jan 2025 13:56:03 +0000 Subject: [PATCH] build: Remove usage of deprecated std::aligned_storage/union These are deprecated in c++23. Note: in the one instance where the default Align value was used for std::aligned_storage (i.e. std::aligned_storage), this patch now adopts an implementation similar to libc++ to avoid behavior changes. --- layers/containers/subresource_adapter.h | 8 +- layers/external/inplace_function.h | 116 ++++++++++++------------ 2 files changed, 61 insertions(+), 63 deletions(-) diff --git a/layers/containers/subresource_adapter.h b/layers/containers/subresource_adapter.h index d9bcee26423..042375b5ae3 100644 --- a/layers/containers/subresource_adapter.h +++ b/layers/containers/subresource_adapter.h @@ -20,6 +20,7 @@ */ #pragma once +#include #include #include "range_vector.h" #include "custom_containers.h" @@ -761,13 +762,13 @@ class BothRangeMap { } BigMap* MakeBigMap() { if (BigMode()) { - return new (&backing_store) BigMap(); + return new (backing_store) BigMap(); } return nullptr; } SmallMap* MakeSmallMap(index_type limit) { if (SmallMode()) { - return new (&backing_store) SmallMap(limit); + return new (backing_store) SmallMap(limit); } return nullptr; } @@ -777,8 +778,7 @@ class BothRangeMap { BigMap* big_map_ = nullptr; SmallMap* small_map_ = nullptr; - using Storage = typename std::aligned_union<0, SmallMap, BigMap>::type; - Storage backing_store; + alignas(std::max(alignof(SmallMap), alignof(BigMap))) std::byte backing_store[std::max(sizeof(SmallMap), sizeof(BigMap))]; }; } // namespace subresource_adapter diff --git a/layers/external/inplace_function.h b/layers/external/inplace_function.h index 57b11bbfcfa..15a8a27cafc 100644 --- a/layers/external/inplace_function.h +++ b/layers/external/inplace_function.h @@ -29,6 +29,7 @@ #pragma once +#include #include #include #include @@ -45,47 +46,6 @@ namespace inplace_function_detail { static constexpr size_t InplaceFunctionDefaultCapacity = 32; -#ifndef SG14_USE_STD_ALIGNED_STORAGE -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61458 -// MSVC 32-bit has the same bug. -// libc++ and MSVC 64-bit seem to work fine right now, but why run the risk? -template -union aligned_storage_helper { - struct double1 { - double a; - }; - struct double4 { - double a[4]; - }; - template - using maybe = std::conditional_t<(Cap >= sizeof(T)), T, char>; - char real_data[Cap]; - maybe a; - maybe b; - maybe c; - maybe d; - maybe e; - maybe f; - maybe g; - maybe h; -}; - -template )> -struct aligned_storage { - using type = std::aligned_storage_t; -}; - -template )> -using aligned_storage_t = typename aligned_storage::type; -static_assert(sizeof(aligned_storage_t) == sizeof(void*), "A"); -static_assert(alignof(aligned_storage_t) == alignof(void*), "B"); -#else -using std::aligned_storage; -using std::aligned_storage_t; -static_assert(sizeof(std::aligned_storage_t) == sizeof(void*), "C"); -static_assert(alignof(std::aligned_storage_t) == alignof(void*), "D"); -#endif - template struct wrapper { using type = T; @@ -171,10 +131,49 @@ struct is_invocable_r_impl(std::declval()(std::declval using is_invocable_r = is_invocable_r_impl; + +// The max element in Values which is <= Cap. min(Values) must be <= Cap. +template +struct GetMaxValueWithinCap; + +template +struct GetMaxValueWithinCap { + static_assert(Value <= Cap); + static const size_t value = Value; +}; + +template +struct GetMaxValueWithinCap { + private: + static const size_t rest = GetMaxValueWithinCap::value; + + public: + // Ensure the problem is well-defined. This assertion causes quadratic time + // but that's fine, the list is small. + static_assert(std::min({Head, Tail...}) <= Cap); + static const size_t value = std::max(Head, rest) <= Cap ? std::max(Head, rest) : std::min(Head, rest); +}; + +struct struct_double { + long double lx; +}; + +struct struct_double4 { + double lx[4]; +}; + } // namespace inplace_function_detail +// Note about default alignment: This class used to employ +// std::aligned_storage, which is now deprecated and got removed. To +// avoid behavior changes, the new implementation mimics the default alignment +// of std::aligned_storage, as per the link below. +// https://source.chromium.org/chromium/chromium/src/+/main:third_party/libc++/src/include/__type_traits/aligned_storage.h;l=49;drc=66b494f0101bb862e9e7b034f18645af4b1dd080 template )> + size_t Alignment = inplace_function_detail::GetMaxValueWithinCap< + Capacity, alignof(unsigned char), alignof(unsigned short), alignof(unsigned int), alignof(unsigned long), + alignof(unsigned long long), alignof(double), alignof(long double), alignof(int*), + alignof(inplace_function_detail::struct_double), alignof(inplace_function_detail::struct_double4)>::value> class inplace_function; // unspecified namespace inplace_function_detail { @@ -186,7 +185,6 @@ struct is_inplace_function> : std::true_type { template class inplace_function { - using storage_t = inplace_function_detail::aligned_storage_t; using vtable_t = inplace_function_detail::vtable; using vtable_ptr_t = const vtable_t*; @@ -213,19 +211,19 @@ class inplace_function { static const vtable_t vt{inplace_function_detail::wrapper{}}; vtable_ptr_ = std::addressof(vt); - ::new (std::addressof(storage_)) C{std::forward(closure)}; + ::new (storage_) C{std::forward(closure)}; } template inplace_function(const inplace_function& other) - : inplace_function(other.vtable_ptr_, other.vtable_ptr_->copy_ptr, std::addressof(other.storage_)) { + : inplace_function(other.vtable_ptr_, other.vtable_ptr_->copy_ptr, other.storage_) { static_assert(inplace_function_detail::is_valid_inplace_dst::value, "conversion not allowed"); } template inplace_function(inplace_function&& other) noexcept - : inplace_function(other.vtable_ptr_, other.vtable_ptr_->relocate_ptr, std::addressof(other.storage_)) { + : inplace_function(other.vtable_ptr_, other.vtable_ptr_->relocate_ptr, other.storage_) { static_assert(inplace_function_detail::is_valid_inplace_dst::value, "conversion not allowed"); @@ -235,31 +233,31 @@ class inplace_function { inplace_function(std::nullptr_t) noexcept : vtable_ptr_{std::addressof(inplace_function_detail::empty_vtable)} {} inplace_function(const inplace_function& other) : vtable_ptr_{other.vtable_ptr_} { - vtable_ptr_->copy_ptr(std::addressof(storage_), std::addressof(other.storage_)); + vtable_ptr_->copy_ptr(storage_, other.storage_); } inplace_function(inplace_function&& other) noexcept : vtable_ptr_{std::exchange(other.vtable_ptr_, std::addressof(inplace_function_detail::empty_vtable))} { - vtable_ptr_->relocate_ptr(std::addressof(storage_), std::addressof(other.storage_)); + vtable_ptr_->relocate_ptr(storage_, other.storage_); } inplace_function& operator=(std::nullptr_t) noexcept { - vtable_ptr_->destructor_ptr(std::addressof(storage_)); + vtable_ptr_->destructor_ptr(storage_); vtable_ptr_ = std::addressof(inplace_function_detail::empty_vtable); return *this; } inplace_function& operator=(inplace_function other) noexcept { - vtable_ptr_->destructor_ptr(std::addressof(storage_)); + vtable_ptr_->destructor_ptr(storage_); vtable_ptr_ = std::exchange(other.vtable_ptr_, std::addressof(inplace_function_detail::empty_vtable)); - vtable_ptr_->relocate_ptr(std::addressof(storage_), std::addressof(other.storage_)); + vtable_ptr_->relocate_ptr(storage_, other.storage_); return *this; } - ~inplace_function() { vtable_ptr_->destructor_ptr(std::addressof(storage_)); } + ~inplace_function() { vtable_ptr_->destructor_ptr(storage_); } - R operator()(Args... args) const { return vtable_ptr_->invoke_ptr(std::addressof(storage_), std::forward(args)...); } + R operator()(Args... args) const { return vtable_ptr_->invoke_ptr(storage_, std::forward(args)...); } constexpr bool operator==(std::nullptr_t) const noexcept { return !operator bool(); } @@ -272,12 +270,12 @@ class inplace_function { void swap(inplace_function& other) noexcept { if (this == std::addressof(other)) return; - storage_t tmp; - vtable_ptr_->relocate_ptr(std::addressof(tmp), std::addressof(storage_)); + alignas(Alignment) std::byte tmp[Capacity]; + vtable_ptr_->relocate_ptr(tmp, storage_); - other.vtable_ptr_->relocate_ptr(std::addressof(storage_), std::addressof(other.storage_)); + other.vtable_ptr_->relocate_ptr(storage_, other.storage_); - vtable_ptr_->relocate_ptr(std::addressof(other.storage_), std::addressof(tmp)); + vtable_ptr_->relocate_ptr(other.storage_, tmp); std::swap(vtable_ptr_, other.vtable_ptr_); } @@ -286,12 +284,12 @@ class inplace_function { private: vtable_ptr_t vtable_ptr_; - mutable storage_t storage_; + alignas(Alignment) mutable std::byte storage_[Capacity]; inplace_function(vtable_ptr_t vtable_ptr, typename vtable_t::process_ptr_t process_ptr, typename vtable_t::storage_ptr_t storage_ptr) : vtable_ptr_{vtable_ptr} { - process_ptr(std::addressof(storage_), storage_ptr); + process_ptr(storage_, storage_ptr); } };