Skip to content

Conversation

@marcauberer
Copy link
Member

std::aligned_storage is deprecated with C++23, see here.

This replaces the usages of std::aligned_storage within compiler-rt with an aligned std::byte array.
I will provide patches for other subcomponents as well.

@github-actions
Copy link

github-actions bot commented Jun 2, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@marcauberer marcauberer requested review from deanberris and dvyukov June 2, 2024 21:53
@marcauberer marcauberer marked this pull request as ready for review June 2, 2024 21:53
@llvmbot
Copy link
Member

llvmbot commented Jun 2, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

@llvm/pr-subscribers-xray

Author: Marc Auberer (marcauberer)

Changes

std::aligned_storage is deprecated with C++23, see here.

This replaces the usages of std::aligned_storage within compiler-rt with an aligned std::byte array.
I will provide patches for other subcomponents as well.


Full diff: https://github.com/llvm/llvm-project/pull/94171.diff

11 Files Affected:

  • (modified) compiler-rt/lib/xray/tests/unit/function_call_trie_test.cpp (+3-5)
  • (modified) compiler-rt/lib/xray/tests/unit/profile_collector_test.cpp (+2-2)
  • (modified) compiler-rt/lib/xray/tests/unit/segmented_array_test.cpp (+3-5)
  • (modified) compiler-rt/lib/xray/tests/unit/test_helpers.cpp (+1-2)
  • (modified) compiler-rt/lib/xray/xray_fdr_logging.cpp (+7-12)
  • (modified) compiler-rt/lib/xray/xray_function_call_trie.h (+8-12)
  • (modified) compiler-rt/lib/xray/xray_profile_collector.cpp (+12-15)
  • (modified) compiler-rt/lib/xray/xray_profiling.cpp (+5-8)
  • (modified) compiler-rt/lib/xray/xray_segmented_array.h (+1-2)
  • (modified) compiler-rt/test/tsan/custom_mutex4.cpp (+4-4)
  • (modified) compiler-rt/test/tsan/custom_mutex5.cpp (+4-4)
diff --git a/compiler-rt/lib/xray/tests/unit/function_call_trie_test.cpp b/compiler-rt/lib/xray/tests/unit/function_call_trie_test.cpp index c90d6637fff5e..b058e3ced2792 100644 --- a/compiler-rt/lib/xray/tests/unit/function_call_trie_test.cpp +++ b/compiler-rt/lib/xray/tests/unit/function_call_trie_test.cpp @@ -310,16 +310,14 @@ TEST(FunctionCallTrieTest, MergeInto) { TEST(FunctionCallTrieTest, PlacementNewOnAlignedStorage) { profilingFlags()->setDefaults(); - typename std::aligned_storage<sizeof(FunctionCallTrie::Allocators), - alignof(FunctionCallTrie::Allocators)>::type - AllocatorsStorage; + alignas(FunctionCallTrie::Allocators) + std::byte AllocatorsStorage[sizeof(FunctionCallTrie::Allocators)]; new (&AllocatorsStorage) FunctionCallTrie::Allocators(FunctionCallTrie::InitAllocators()); auto *A = reinterpret_cast<FunctionCallTrie::Allocators *>(&AllocatorsStorage); - typename std::aligned_storage<sizeof(FunctionCallTrie), - alignof(FunctionCallTrie)>::type FCTStorage; + alignas(FunctionCallTrie) std::byte FCTStorage[sizeof(FunctionCallTrie)]; new (&FCTStorage) FunctionCallTrie(*A); auto *T = reinterpret_cast<FunctionCallTrie *>(&FCTStorage); diff --git a/compiler-rt/lib/xray/tests/unit/profile_collector_test.cpp b/compiler-rt/lib/xray/tests/unit/profile_collector_test.cpp index eab5579cb3ee0..da50642284d43 100644 --- a/compiler-rt/lib/xray/tests/unit/profile_collector_test.cpp +++ b/compiler-rt/lib/xray/tests/unit/profile_collector_test.cpp @@ -38,8 +38,8 @@ struct ExpectedProfilingFileHeader { void ValidateFileHeaderBlock(XRayBuffer B) { ASSERT_NE(static_cast<const void *>(B.Data), nullptr); ASSERT_EQ(B.Size, sizeof(ExpectedProfilingFileHeader)); - typename std::aligned_storage<sizeof(ExpectedProfilingFileHeader)>::type - FileHeaderStorage; + alignas(ExpectedProfilingFileHeader) + std::byte FileHeaderStorage[sizeof(ExpectedProfilingFileHeader)]; ExpectedProfilingFileHeader ExpectedHeader; std::memcpy(&FileHeaderStorage, B.Data, B.Size); auto &FileHeader = diff --git a/compiler-rt/lib/xray/tests/unit/segmented_array_test.cpp b/compiler-rt/lib/xray/tests/unit/segmented_array_test.cpp index 46aeb88f71b4c..26c80ded1d7ec 100644 --- a/compiler-rt/lib/xray/tests/unit/segmented_array_test.cpp +++ b/compiler-rt/lib/xray/tests/unit/segmented_array_test.cpp @@ -226,13 +226,11 @@ TEST(SegmentedArrayTest, SimulateStackBehaviour) { TEST(SegmentedArrayTest, PlacementNewOnAlignedStorage) { using AllocatorType = typename Array<ShadowStackEntry>::AllocatorType; - typename std::aligned_storage<sizeof(AllocatorType), - alignof(AllocatorType)>::type AllocatorStorage; + alignas(AllocatorType) std::byte AllocatorStorage[sizeof(AllocatorType)]; new (&AllocatorStorage) AllocatorType(1 << 10); auto *A = reinterpret_cast<AllocatorType *>(&AllocatorStorage); - typename std::aligned_storage<sizeof(Array<ShadowStackEntry>), - alignof(Array<ShadowStackEntry>)>::type - ArrayStorage; + alignas(Array<ShadowStackEntry>) + std::byte ArrayStorage[sizeof(Array<ShadowStackEntry>)]; new (&ArrayStorage) Array<ShadowStackEntry>(*A); auto *Data = reinterpret_cast<Array<ShadowStackEntry> *>(&ArrayStorage); diff --git a/compiler-rt/lib/xray/tests/unit/test_helpers.cpp b/compiler-rt/lib/xray/tests/unit/test_helpers.cpp index 6075f36a4a78a..81a93d8720a6c 100644 --- a/compiler-rt/lib/xray/tests/unit/test_helpers.cpp +++ b/compiler-rt/lib/xray/tests/unit/test_helpers.cpp @@ -69,8 +69,7 @@ namespace __xray { std::string serialize(BufferQueue &Buffers, int32_t Version) { std::string Serialized; - std::aligned_storage<sizeof(XRayFileHeader), alignof(XRayFileHeader)>::type - HeaderStorage; + alignas(XRayFileHeader) std::byte HeaderStorage[sizeof(XRayFileHeader)]; auto *Header = reinterpret_cast<XRayFileHeader *>(&HeaderStorage); new (Header) XRayFileHeader(); Header->Version = Version; diff --git a/compiler-rt/lib/xray/xray_fdr_logging.cpp b/compiler-rt/lib/xray/xray_fdr_logging.cpp index 378a8c0f4a70a..7def3565d56ab 100644 --- a/compiler-rt/lib/xray/xray_fdr_logging.cpp +++ b/compiler-rt/lib/xray/xray_fdr_logging.cpp @@ -55,17 +55,12 @@ struct XRAY_TLS_ALIGNAS(64) ThreadLocalData { BufferQueue::Buffer Buffer{}; BufferQueue *BQ = nullptr; - using LogWriterStorage = - typename std::aligned_storage<sizeof(FDRLogWriter), - alignof(FDRLogWriter)>::type; - - LogWriterStorage LWStorage; + using LogWriterStorage = std::byte[sizeof(FDRLogWriter)]; + alignas(FDRLogWriter) LogWriterStorage LWStorage; FDRLogWriter *Writer = nullptr; - using ControllerStorage = - typename std::aligned_storage<sizeof(FDRController<>), - alignof(FDRController<>)>::type; - ControllerStorage CStorage; + using ControllerStorage = std::byte[sizeof(FDRController<>)]; + alignas(FDRController<>) ControllerStorage CStorage; FDRController<> *Controller = nullptr; }; @@ -78,7 +73,7 @@ static_assert(std::is_trivially_destructible<ThreadLocalData>::value, static pthread_key_t Key; // Global BufferQueue. -static std::aligned_storage<sizeof(BufferQueue)>::type BufferQueueStorage; +static std::byte BufferQueueStorage[sizeof(BufferQueue)]; static BufferQueue *BQ = nullptr; // Global thresholds for function durations. @@ -129,8 +124,8 @@ static_assert(alignof(ThreadLocalData) >= 64, "ThreadLocalData must be cache line aligned."); #endif static ThreadLocalData &getThreadLocalData() { - thread_local typename std::aligned_storage< - sizeof(ThreadLocalData), alignof(ThreadLocalData)>::type TLDStorage{}; + alignas(ThreadLocalData) thread_local std::byte + TLDStorage[sizeof(ThreadLocalData)]; if (pthread_getspecific(Key) == NULL) { new (reinterpret_cast<ThreadLocalData *>(&TLDStorage)) ThreadLocalData{}; diff --git a/compiler-rt/lib/xray/xray_function_call_trie.h b/compiler-rt/lib/xray/xray_function_call_trie.h index b8c60583761b5..7536f39b8081a 100644 --- a/compiler-rt/lib/xray/xray_function_call_trie.h +++ b/compiler-rt/lib/xray/xray_function_call_trie.h @@ -139,18 +139,14 @@ class FunctionCallTrie { // Use hosted aligned storage members to allow for trivial move and init. // This also allows us to sidestep the potential-failing allocation issue. - typename std::aligned_storage<sizeof(NodeAllocatorType), - alignof(NodeAllocatorType)>::type - NodeAllocatorStorage; - typename std::aligned_storage<sizeof(RootAllocatorType), - alignof(RootAllocatorType)>::type - RootAllocatorStorage; - typename std::aligned_storage<sizeof(ShadowStackAllocatorType), - alignof(ShadowStackAllocatorType)>::type - ShadowStackAllocatorStorage; - typename std::aligned_storage<sizeof(NodeIdPairAllocatorType), - alignof(NodeIdPairAllocatorType)>::type - NodeIdPairAllocatorStorage; + alignas(NodeAllocatorType) std::byte + NodeAllocatorStorage[sizeof(NodeAllocatorType)]; + alignas(RootAllocatorType) std::byte + RootAllocatorStorage[sizeof(RootAllocatorType)]; + alignas(ShadowStackAllocatorType) std::byte + ShadowStackAllocatorStorage[sizeof(ShadowStackAllocatorType)]; + alignas(NodeIdPairAllocatorType) std::byte + NodeIdPairAllocatorStorage[sizeof(NodeIdPairAllocatorType)]; NodeAllocatorType *NodeAllocator = nullptr; RootAllocatorType *RootAllocator = nullptr; diff --git a/compiler-rt/lib/xray/xray_profile_collector.cpp b/compiler-rt/lib/xray/xray_profile_collector.cpp index bef2504f2a16e..3a28240e603c9 100644 --- a/compiler-rt/lib/xray/xray_profile_collector.cpp +++ b/compiler-rt/lib/xray/xray_profile_collector.cpp @@ -29,7 +29,7 @@ namespace { SpinMutex GlobalMutex; struct ThreadTrie { tid_t TId; - typename std::aligned_storage<sizeof(FunctionCallTrie)>::type TrieStorage; + alignas(FunctionCallTrie) std::byte TrieStorage[sizeof(FunctionCallTrie)]; }; struct ProfileBuffer { @@ -71,16 +71,13 @@ using ThreadDataAllocator = ThreadDataArray::AllocatorType; // by the ThreadData array. This lets us host the buffers, allocators, and tries // associated with a thread by moving the data into the array instead of // attempting to copy the data to a separately backed set of tries. -static typename std::aligned_storage< - sizeof(BufferQueue), alignof(BufferQueue)>::type BufferQueueStorage; +alignas(BufferQueue) static std::byte BufferQueueStorage[sizeof(BufferQueue)]; static BufferQueue *BQ = nullptr; static BufferQueue::Buffer Buffer; -static typename std::aligned_storage<sizeof(ThreadDataAllocator), - alignof(ThreadDataAllocator)>::type - ThreadDataAllocatorStorage; -static typename std::aligned_storage<sizeof(ThreadDataArray), - alignof(ThreadDataArray)>::type - ThreadDataArrayStorage; +alignas(ThreadDataAllocator) static std::byte + ThreadDataAllocatorStorage[sizeof(ThreadDataAllocator)]; +alignas(ThreadDataArray) static std::byte + ThreadDataArrayStorage[sizeof(ThreadDataArray)]; static ThreadDataAllocator *TDAllocator = nullptr; static ThreadDataArray *TDArray = nullptr; @@ -91,10 +88,10 @@ using ProfileBufferArrayAllocator = typename ProfileBufferArray::AllocatorType; // These need to be global aligned storage to avoid dynamic initialization. We // need these to be aligned to allow us to placement new objects into the // storage, and have pointers to those objects be appropriately aligned. -static typename std::aligned_storage<sizeof(ProfileBufferArray)>::type - ProfileBuffersStorage; -static typename std::aligned_storage<sizeof(ProfileBufferArrayAllocator)>::type - ProfileBufferArrayAllocatorStorage; +alignas(ProfileBufferArray) static std::byte + ProfileBuffersStorage[sizeof(ProfileBufferArray)]; +alignas(ProfileBufferArrayAllocator) static std::byte + ProfileBufferArrayAllocatorStorage[sizeof(ProfileBufferArrayAllocator)]; static ProfileBufferArrayAllocator *ProfileBuffersAllocator = nullptr; static ProfileBufferArray *ProfileBuffers = nullptr; @@ -382,8 +379,8 @@ XRayBuffer nextBuffer(XRayBuffer B) XRAY_NEVER_INSTRUMENT { return {nullptr, 0}; static pthread_once_t Once = PTHREAD_ONCE_INIT; - static typename std::aligned_storage<sizeof(XRayProfilingFileHeader)>::type - FileHeaderStorage; + alignas(XRayProfilingFileHeader) static std::byte + FileHeaderStorage[sizeof(XRayProfilingFileHeader)]; pthread_once( &Once, +[]() XRAY_NEVER_INSTRUMENT { new (&FileHeaderStorage) XRayProfilingFileHeader{}; diff --git a/compiler-rt/lib/xray/xray_profiling.cpp b/compiler-rt/lib/xray/xray_profiling.cpp index 259ec65a76a1f..e9ac2fdd8aadf 100644 --- a/compiler-rt/lib/xray/xray_profiling.cpp +++ b/compiler-rt/lib/xray/xray_profiling.cpp @@ -48,17 +48,14 @@ static pthread_key_t ProfilingKey; // We use a global buffer queue, which gets initialized once at initialisation // time, and gets reset when profiling is "done". -static std::aligned_storage<sizeof(BufferQueue), alignof(BufferQueue)>::type - BufferQueueStorage; +alignas(BufferQueue) static std::byte BufferQueueStorage[sizeof(BufferQueue)]; static BufferQueue *BQ = nullptr; thread_local FunctionCallTrie::Allocators::Buffers ThreadBuffers; -thread_local std::aligned_storage<sizeof(FunctionCallTrie::Allocators), - alignof(FunctionCallTrie::Allocators)>::type - AllocatorsStorage; -thread_local std::aligned_storage<sizeof(FunctionCallTrie), - alignof(FunctionCallTrie)>::type - FunctionCallTrieStorage; +alignas(FunctionCallTrie::Allocators) thread_local std::byte + AllocatorsStorage[sizeof(FunctionCallTrie::Allocators)]; +alignas(FunctionCallTrie) thread_local std::byte + FunctionCallTrieStorage[sizeof(FunctionCallTrie)]; thread_local ProfilingData TLD{{0}, {0}}; thread_local atomic_uint8_t ReentranceGuard{0}; diff --git a/compiler-rt/lib/xray/xray_segmented_array.h b/compiler-rt/lib/xray/xray_segmented_array.h index 6eb673edffea4..3ab174bcbe18c 100644 --- a/compiler-rt/lib/xray/xray_segmented_array.h +++ b/compiler-rt/lib/xray/xray_segmented_array.h @@ -56,8 +56,7 @@ template <class T> class Array { // kCacheLineSize-multiple segments, minus the size of two pointers. // // - Request cacheline-multiple sized elements from the allocator. - static constexpr uint64_t AlignedElementStorageSize = - sizeof(typename std::aligned_storage<sizeof(T), alignof(T)>::type); + static constexpr uint64_t AlignedElementStorageSize = sizeof(T); static constexpr uint64_t SegmentControlBlockSize = sizeof(Segment *) * 2; diff --git a/compiler-rt/test/tsan/custom_mutex4.cpp b/compiler-rt/test/tsan/custom_mutex4.cpp index 539a8be803c60..f7dfab0235312 100644 --- a/compiler-rt/test/tsan/custom_mutex4.cpp +++ b/compiler-rt/test/tsan/custom_mutex4.cpp @@ -1,7 +1,7 @@ -// RUN: %clangxx_tsan -O1 --std=c++11 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_tsan -O1 --std=c++17 %s -o %t && %run %t 2>&1 | FileCheck %s #include "custom_mutex.h" -#include <type_traits> +#include <cstddef> // Test that the destruction events of a mutex are ignored when the // annotations request this. @@ -12,14 +12,14 @@ // has run. int main() { - std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu1_store; + alignas(Mutex) std::byte mu1_store[sizeof(Mutex)]; Mutex* mu1 = reinterpret_cast<Mutex*>(&mu1_store); new(&mu1_store) Mutex(false, __tsan_mutex_linker_init); mu1->Lock(); mu1->~Mutex(); mu1->Unlock(); - std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu2_store; + alignas(Mutex) std::byte mu2_store[sizeof(Mutex)]; Mutex* mu2 = reinterpret_cast<Mutex*>(&mu2_store); new(&mu2_store) Mutex(false, 0, __tsan_mutex_not_static); mu2->Lock(); diff --git a/compiler-rt/test/tsan/custom_mutex5.cpp b/compiler-rt/test/tsan/custom_mutex5.cpp index cb18b235e2628..6d65829e5df3c 100644 --- a/compiler-rt/test/tsan/custom_mutex5.cpp +++ b/compiler-rt/test/tsan/custom_mutex5.cpp @@ -1,20 +1,20 @@ -// RUN: %clangxx_tsan -O1 --std=c++11 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_tsan -O1 --std=c++17 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s #include "custom_mutex.h" -#include <type_traits> +#include <cstddef> // Test that we detect the destruction of an in-use mutex when the // thread annotations don't otherwise disable the check. int main() { - std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu1_store; + alignas(Mutex) std::byte mu1_store[sizeof(Mutex)]; Mutex* mu1 = reinterpret_cast<Mutex*>(&mu1_store); new(&mu1_store) Mutex(false, 0); mu1->Lock(); mu1->~Mutex(); mu1->Unlock(); - std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu2_store; + alignas(Mutex) std::byte mu2_store[sizeof(Mutex)]; Mutex* mu2 = reinterpret_cast<Mutex*>(&mu2_store); new(&mu2_store) Mutex(false, __tsan_mutex_not_static, __tsan_mutex_not_static); 
Copy link
Collaborator

@vitalybuka vitalybuka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TSAN LGTM

@marcauberer marcauberer merged commit cac7821 into llvm:main Jun 8, 2024
@marcauberer marcauberer deleted the compiler-rt/replace-aligned-storage-with-aligned-byte-array branch June 8, 2024 10:29
@HerrCai0907 HerrCai0907 mentioned this pull request Jun 13, 2024
noclowns added a commit to noclowns/llvm that referenced this pull request Aug 6, 2025
No behavioral change, but eliminates potential UB in strict-alignment systems. The previous commit (llvm#94171) bulk-updated alignment usage to C++23 spec, but missed this occurrence.
noclowns added a commit that referenced this pull request Aug 8, 2025
…eue (#152408) No behavioral change, but eliminates potential UB in strict-alignment systems. The previous commit (#94171) bulk-updated alignment usage to C++23 spec, but missed this occurrence.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment