[libcxx-commits] [libcxx] [libcxx][test-support] Improve thread_unsafe_shared_ptr (PR #195932)
Nikita Belenkiy via libcxx-commits
libcxx-commits at lists.llvm.org
Tue May 5 22:59:39 PDT 2026
https://github.com/kitsnet updated https://github.com/llvm/llvm-project/pull/195932
>From fec403d00e574494e97bed2cda90446aada36da6 Mon Sep 17 00:00:00 2001
From: Nikita Belenkiy <nikita.nb.belenkiy at partner.bmw.de>
Date: Tue, 5 May 2026 22:17:44 +0200
Subject: [PATCH] [libcxx][test-support] Improve thread_unsafe_shared_ptr
Adapting test support class thread_unsafe_shared_ptr for future use
with fancy_pointer_allocator, in particular, in constexpr contexts:
* Implementing the rule of 5 / the rule of 3;
* Annotating noexcept methods (and removing the workaround in the respective test);
* Making deallocation of its control block ignored by DisableAllocationGuard;
* Adding workaround for (expected later) module export problem (https://llvm.org/PR120108)
---
.../string.cons/move_noexcept.pass.cpp | 4 --
libcxx/test/support/module.modulemap | 5 +-
libcxx/test/support/test_allocator.h | 56 ++++++++++++++++---
3 files changed, 51 insertions(+), 14 deletions(-)
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
index d807cac2c72c8..89502f6652655 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
@@ -32,11 +32,7 @@ int main(int, char**) {
}
{
typedef std::basic_string<char, std::char_traits<char>, limited_allocator<char, 10>> C;
-#if TEST_STD_VER <= 14
- static_assert(!std::is_nothrow_move_constructible<C>::value, "");
-#else
static_assert(std::is_nothrow_move_constructible<C>::value, "");
-#endif
}
return 0;
diff --git a/libcxx/test/support/module.modulemap b/libcxx/test/support/module.modulemap
index 0af147d75ee5d..07acbb6b2e2fd 100644
--- a/libcxx/test/support/module.modulemap
+++ b/libcxx/test/support/module.modulemap
@@ -5,7 +5,10 @@ module test_config {
module test {
module double_move_tracker { header "double_move_tracker.h" }
- module test_allocator { header "test_allocator.h" }
+ module test_allocator {
+ header "test_allocator.h"
+ export * // TODO: Workaround for https://llvm.org/PR120108
+ }
module test_iterators { header "test_iterators.h" }
module type_algorithms { header "type_algorithms.h" }
}
diff --git a/libcxx/test/support/test_allocator.h b/libcxx/test/support/test_allocator.h
index f8b622d7f9520..d6046518d6cf5 100644
--- a/libcxx/test/support/test_allocator.h
+++ b/libcxx/test/support/test_allocator.h
@@ -395,19 +395,32 @@ class thread_unsafe_shared_ptr {
public:
thread_unsafe_shared_ptr() = default;
- TEST_CONSTEXPR_CXX14 thread_unsafe_shared_ptr(const thread_unsafe_shared_ptr& other) : block(other.block) {
+ TEST_CONSTEXPR_CXX14 thread_unsafe_shared_ptr(const thread_unsafe_shared_ptr& other) TEST_NOEXCEPT
+ : block(other.block) {
++block->ref_count;
}
+ TEST_CONSTEXPR_CXX14 thread_unsafe_shared_ptr& operator=(const thread_unsafe_shared_ptr& other) TEST_NOEXCEPT {
+ // self-assignment safe order
+ ++other.block->ref_count;
+ detach_control_block();
+ block = other.block;
+ return *this;
+ }
- TEST_CONSTEXPR_CXX20 ~thread_unsafe_shared_ptr() {
- --block->ref_count;
- if (block->ref_count != 0)
- return;
- typedef std::allocator_traits<std::allocator<control_block> > allocator_traits;
- std::allocator<control_block> alloc;
- allocator_traits::destroy(alloc, block);
- allocator_traits::deallocate(alloc, block, 1);
+#if TEST_STD_VER >= 11
+ TEST_CONSTEXPR_CXX14 thread_unsafe_shared_ptr(thread_unsafe_shared_ptr&& other) TEST_NOEXCEPT : block(other.block) {
+ ++block->ref_count;
}
+ TEST_CONSTEXPR_CXX20 thread_unsafe_shared_ptr& operator=(thread_unsafe_shared_ptr&& other) TEST_NOEXCEPT {
+ // self-assignment safe order
+ ++other.block->ref_count;
+ detach_control_block();
+ block = other.block;
+ return *this;
+ }
+#endif
+
+ TEST_CONSTEXPR_CXX20 ~thread_unsafe_shared_ptr() TEST_NOEXCEPT { detach_control_block(); }
TEST_CONSTEXPR const T& operator*() const { return block->content; }
TEST_CONSTEXPR const T* operator->() const { return &block->content; }
@@ -424,6 +437,31 @@ class thread_unsafe_shared_ptr {
T content;
};
+ TEST_CONSTEXPR_CXX20 void detach_control_block() {
+ --block->ref_count;
+ if (block->ref_count != 0)
+ return;
+ typedef std::allocator_traits<std::allocator<control_block> > allocator_traits;
+ std::allocator<control_block> alloc;
+ allocator_traits::destroy(alloc, block);
+#ifdef COUNT_NEW_H
+ // We are called from test code instrumented by counting operator new/operator delete,
+ // which might be surprised by unexpected deallocations we introduce.
+ // Instead of changing all the potentially affected tests, we will just temporarily
+ // disable that counting here.
+ bool disable_allocations = false;
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ disable_allocations = globalMemCounter.disable_allocations;
+ globalMemCounter.disable_allocations = false;
+ }
+#endif
+ allocator_traits::deallocate(alloc, block, 1);
+#ifdef COUNT_NEW_H
+ if (!TEST_IS_CONSTANT_EVALUATED)
+ globalMemCounter.disable_allocations = disable_allocations;
+#endif
+ }
+
control_block* block = nullptr;
template <class U, class... Args>
More information about the libcxx-commits
mailing list