[libcxx-commits] [libcxx] [libc++] Refactor tests for aligned allocation and sized deallocation (PR #117915)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Dec 2 11:00:40 PST 2024
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/117915
>From 2ac0fff67a590e17dde5a28cc4365245518a5bc0 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 27 Nov 2024 14:10:09 -0500
Subject: [PATCH] [libc++] Refactor tests for aligned allocation and sized
deallocation
This patch refactors the tests around aligned allocation and sized
deallocation to avoid relying on passing the -fsized-deallocation or
-faligned-allocation flags by default. Since both of these features are
enabled by default in >= C++14 mode, it now makes sense to make that
assumption in the test suite.
A notable exception is MinGW and some older compilers, where sized
deallocation is still not enabled by default. We treat that as a
"bug" in the test suite and we work around it by explicitly adding
-fsized-deallocation, but only under those configurations.
---
libcxx/test/benchmarks/allocation.bench.cpp | 11 +-
.../new_faligned_allocation.pass.cpp | 108 ------------------
.../libcxx/memory/shared_ptr_array.pass.cpp | 10 +-
.../support.dynamic/align_val_t.pass.cpp | 48 ++++++--
.../new.delete.array/new.size_align.pass.cpp | 11 +-
.../new.size_align_nothrow.pass.cpp | 11 +-
...n.pass.cpp => sized_delete_array.pass.cpp} | 26 ++++-
.../sized_delete_array14.pass.cpp | 78 -------------
.../new.delete.single/new.size_align.pass.cpp | 11 +-
.../new.size_align_nothrow.pass.cpp | 11 +-
...elete14.pass.cpp => sized_delete.pass.cpp} | 30 +++--
.../sized_delete_fsizeddeallocation.pass.cpp | 71 ------------
.../support.dynamic/new.delete/types.h | 31 +++++
libcxx/utils/libcxx/test/features.py | 8 --
14 files changed, 147 insertions(+), 318 deletions(-)
delete mode 100644 libcxx/test/libcxx/language.support/support.dynamic/new_faligned_allocation.pass.cpp
rename libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/{sized_delete_array_fsizeddeallocation.pass.cpp => sized_delete_array.pass.cpp} (67%)
delete mode 100644 libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp
rename libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/{sized_delete14.pass.cpp => sized_delete.pass.cpp} (62%)
delete mode 100644 libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete_fsizeddeallocation.pass.cpp
diff --git a/libcxx/test/benchmarks/allocation.bench.cpp b/libcxx/test/benchmarks/allocation.bench.cpp
index 66a9b88793412b..bdccaa2c133bd7 100644
--- a/libcxx/test/benchmarks/allocation.bench.cpp
+++ b/libcxx/test/benchmarks/allocation.bench.cpp
@@ -6,8 +6,15 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: -fsized-deallocation
-// ADDITIONAL_COMPILE_FLAGS: -fsized-deallocation
+// UNSUPPORTED: c++03, c++11
+
+// These compiler versions and platforms don't enable sized deallocation by default.
+// ADDITIONAL_COMPILE_FLAGS(clang-17): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(clang-18): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(apple-clang-15): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(apple-clang-16): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(target=x86_64-w64-windows-gnu): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(target=i686-w64-windows-gnu): -fsized-deallocation
#include "benchmark/benchmark.h"
diff --git a/libcxx/test/libcxx/language.support/support.dynamic/new_faligned_allocation.pass.cpp b/libcxx/test/libcxx/language.support/support.dynamic/new_faligned_allocation.pass.cpp
deleted file mode 100644
index 87f4783e12973e..00000000000000
--- a/libcxx/test/libcxx/language.support/support.dynamic/new_faligned_allocation.pass.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// test libc++'s implementation of align_val_t, and the relevant new/delete
-// overloads in all dialects when -faligned-allocation is present.
-
-// Libc++ when built for z/OS doesn't contain the aligned allocation functions,
-// nor does the dynamic library shipped with z/OS.
-// XFAIL: target={{.+}}-zos{{.*}}
-
-// REQUIRES: -faligned-allocation
-// ADDITIONAL_COMPILE_FLAGS: -faligned-allocation
-
-#include <cassert>
-#include <new>
-#include <string>
-#include <type_traits>
-#include <typeinfo>
-
-#include "test_macros.h"
-
-static void test_allocations(std::size_t size, size_t alignment) {
- {
- void* ptr = ::operator new(size, std::align_val_t(alignment));
- assert(ptr);
- assert(reinterpret_cast<std::uintptr_t>(ptr) % alignment == 0);
- ::operator delete(ptr, std::align_val_t(alignment));
- }
- {
- void* ptr = ::operator new(size, std::align_val_t(alignment), std::nothrow);
- assert(ptr);
- assert(reinterpret_cast<std::uintptr_t>(ptr) % alignment == 0);
- ::operator delete(ptr, std::align_val_t(alignment), std::nothrow);
- }
- {
- void* ptr = ::operator new[](size, std::align_val_t(alignment));
- assert(ptr);
- assert(reinterpret_cast<std::uintptr_t>(ptr) % alignment == 0);
- ::operator delete[](ptr, std::align_val_t(alignment));
- }
- {
- void* ptr = ::operator new[](size, std::align_val_t(alignment), std::nothrow);
- assert(ptr);
- assert(reinterpret_cast<std::uintptr_t>(ptr) % alignment == 0);
- ::operator delete[](ptr, std::align_val_t(alignment), std::nothrow);
- }
-}
-
-int main(int, char**) {
- {
- static_assert(std::is_enum<std::align_val_t>::value, "");
- typedef std::underlying_type<std::align_val_t>::type UT;
- static_assert((std::is_same<UT, std::size_t>::value), "");
- }
- {
- static_assert((!std::is_constructible<std::align_val_t, std::size_t>::value), "");
-#if TEST_STD_VER >= 11
- static_assert(!std::is_constructible<std::size_t, std::align_val_t>::value, "");
-#else
- static_assert((std::is_constructible<std::size_t, std::align_val_t>::value), "");
-#endif
- }
- {
- std::align_val_t a = std::align_val_t(0);
- std::align_val_t b = std::align_val_t(32);
- assert(a != b);
- assert(a == std::align_val_t(0));
- assert(b == std::align_val_t(32));
- }
- // First, check the basic case, a large allocation with alignment==size.
- test_allocations(64, 64);
- // Size being a multiple of alignment also needs to be supported.
- test_allocations(64, 32);
- // When aligned allocation is implemented using aligned_alloc,
- // that function requires a minimum alignment of sizeof(void*).
- // Check that we can also create overaligned allocations with
- // an alignment argument less than sizeof(void*).
- test_allocations(2, 2);
- // When implemented using the C11 aligned_alloc() function,
- // that requires that size be a multiple of alignment.
- // However, the C++ operator new has no such requirements.
- // Check that we can create an overaligned allocation that does
- // adhere to not have this constraint.
- test_allocations(1, 128);
- // Finally, test size > alignment, but with size not being
- // a multiple of alignment.
- test_allocations(65, 32);
-#ifndef TEST_HAS_NO_RTTI
- {
- // Check that libc++ doesn't define align_val_t in a versioning namespace.
- // And that it mangles the same in C++03 through C++17
-#ifdef _MSC_VER
- // MSVC uses a different C++ ABI with a different name mangling scheme.
- // The type id name doesn't seem to contain the mangled form at all.
- assert(typeid(std::align_val_t).name() == std::string("enum std::align_val_t"));
-#else
- assert(typeid(std::align_val_t).name() == std::string("St11align_val_t"));
-#endif
- }
-#endif
-
- return 0;
-}
diff --git a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp
index 772198304b415a..cc8c7438308266 100644
--- a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp
+++ b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp
@@ -8,8 +8,14 @@
//
// UNSUPPORTED: c++03, c++11, c++14, c++17
-// REQUIRES: -fsized-deallocation
-// ADDITIONAL_COMPILE_FLAGS: -fsized-deallocation
+
+// These compiler versions and platforms don't enable sized deallocation by default.
+// ADDITIONAL_COMPILE_FLAGS(clang-17): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(clang-18): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(apple-clang-15): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(apple-clang-16): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(target=x86_64-w64-windows-gnu): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(target=i686-w64-windows-gnu): -fsized-deallocation
// This test will fail with ASan if the implementation passes different sizes
// to corresponding allocation and deallocation functions.
diff --git a/libcxx/test/std/language.support/support.dynamic/align_val_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/align_val_t.pass.cpp
index 28c72f0be7aed8..b898b37ebc7e9d 100644
--- a/libcxx/test/std/language.support/support.dynamic/align_val_t.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/align_val_t.pass.cpp
@@ -15,26 +15,50 @@
// XFAIL: target={{.+}}-zos{{.*}}
#include <new>
+#include <cassert>
+#include <cstddef>
+#include <string>
#include <type_traits>
+#include <typeinfo>
#include "test_macros.h"
-int main(int, char**) {
+constexpr bool test() {
+ static_assert(std::is_enum<std::align_val_t>::value, "");
+ static_assert(std::is_same<std::underlying_type<std::align_val_t>::type, std::size_t>::value, "");
+ static_assert(!std::is_constructible<std::align_val_t, std::size_t>::value, "");
+ static_assert(!std::is_constructible<std::size_t, std::align_val_t>::value, "");
+
{
- static_assert(std::is_enum<std::align_val_t>::value, "");
- static_assert(std::is_same<std::underlying_type<std::align_val_t>::type, std::size_t>::value, "");
- static_assert(!std::is_constructible<std::align_val_t, std::size_t>::value, "");
- static_assert(!std::is_constructible<std::size_t, std::align_val_t>::value, "");
+ auto a = std::align_val_t(0);
+ auto b = std::align_val_t(32);
+ auto c = std::align_val_t(-1);
+ assert(a != b);
+ assert(a == std::align_val_t(0));
+ assert(b == std::align_val_t(32));
+ assert(static_cast<std::size_t>(c) == static_cast<std::size_t>(-1));
}
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test(), "");
+
+#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_RTTI)
{
- constexpr auto a = std::align_val_t(0);
- constexpr auto b = std::align_val_t(32);
- constexpr auto c = std::align_val_t(-1);
- static_assert(a != b, "");
- static_assert(a == std::align_val_t(0), "");
- static_assert(b == std::align_val_t(32), "");
- static_assert(static_cast<std::size_t>(c) == (std::size_t)-1, "");
+ // Check that libc++ doesn't define align_val_t in a versioning namespace.
+ // And that it mangles the same in C++03 through C++17
+# ifdef _MSC_VER
+ // MSVC uses a different C++ ABI with a different name mangling scheme.
+ // The type id name doesn't seem to contain the mangled form at all.
+ assert(typeid(std::align_val_t).name() == std::string("enum std::align_val_t"));
+# else
+ assert(typeid(std::align_val_t).name() == std::string("St11align_val_t"));
+# endif
}
+#endif
return 0;
}
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.pass.cpp
index dd8090aca5b285..c9b59ecaff396d 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.pass.cpp
@@ -34,13 +34,12 @@ void my_new_handler() {
}
int main(int, char**) {
- // Test that we can call the function directly
- {
- void* x = operator new[](10, static_cast<std::align_val_t>(64));
+ test_with_interesting_alignments([](std::size_t size, std::size_t alignment) {
+ void* x = operator new[](size, static_cast<std::align_val_t>(alignment));
assert(x != nullptr);
- assert(reinterpret_cast<std::uintptr_t>(x) % 64 == 0);
- operator delete[](x, static_cast<std::align_val_t>(64));
- }
+ assert(reinterpret_cast<std::uintptr_t>(x) % alignment == 0);
+ operator delete[](x, static_cast<std::align_val_t>(alignment));
+ });
// Test that the new handler is called if allocation fails
{
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.pass.cpp
index 6ae8ceaf534e48..1bdae8d597f00f 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.pass.cpp
@@ -34,13 +34,12 @@ void my_new_handler() {
}
int main(int, char**) {
- // Test that we can call the function directly
- {
- void* x = operator new[](10, static_cast<std::align_val_t>(64), std::nothrow);
+ test_with_interesting_alignments([](std::size_t size, std::size_t alignment) {
+ void* x = operator new[](size, static_cast<std::align_val_t>(alignment), std::nothrow);
assert(x != nullptr);
- assert(reinterpret_cast<std::uintptr_t>(x) % 64 == 0);
- operator delete[](x, static_cast<std::align_val_t>(64), std::nothrow);
- }
+ assert(reinterpret_cast<std::uintptr_t>(x) % alignment == 0);
+ operator delete[](x, static_cast<std::align_val_t>(alignment), std::nothrow);
+ });
// Test that the new handler is called and we return nullptr if allocation fails
{
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_fsizeddeallocation.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp
similarity index 67%
rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_fsizeddeallocation.pass.cpp
rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp
index 6077318278a1ba..f0ad2c0e67df32 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_fsizeddeallocation.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp
@@ -6,15 +6,29 @@
//
//===----------------------------------------------------------------------===//
-// test sized operator delete[] replacement.
+// Test sized operator delete[] replacement.
-// Note that sized delete operator definitions below are simply ignored
-// when sized deallocation is not supported, e.g., prior to C++14.
+// UNSUPPORTED: c++03, c++11
+
+// These compiler versions and platforms don't enable sized deallocation by default.
+// ADDITIONAL_COMPILE_FLAGS(clang-17): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(clang-18): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(apple-clang-15): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(apple-clang-16): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(target=x86_64-w64-windows-gnu): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(target=i686-w64-windows-gnu): -fsized-deallocation
+
+// Android clang-r536225 identifies as clang-19.0 but it predates the real
+// LLVM 19.0.0, so it also leaves sized deallocation off by default.
+// UNSUPPORTED: android && clang-19.0
// UNSUPPORTED: sanitizer-new-delete
-// REQUIRES: -fsized-deallocation
-// ADDITIONAL_COMPILE_FLAGS: -fsized-deallocation
+// Sized deallocation was introduced in LLVM 11
+// XFAIL: using-built-library-before-llvm-11
+
+// AIX, and z/OS default to -fno-sized-deallocation.
+// XFAIL: target={{.+}}-aix{{.*}}, target={{.+}}-zos{{.*}}
#if !defined(__cpp_sized_deallocation)
# error __cpp_sized_deallocation should be defined
@@ -76,5 +90,5 @@ int main(int, char**)
assert(0 == unsized_delete_nothrow_called);
assert(1 == sized_delete_called);
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp
deleted file mode 100644
index 52c4e3e0f69b69..00000000000000
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// test sized operator delete[] replacement.
-
-// These compiler versions don't enable sized deallocation by default.
-// UNSUPPORTED: clang-17, clang-18
-
-// Android clang-r536225 identifies as clang-19.0 but it predates the real
-// LLVM 19.0.0, so it also leaves sized deallocation off by default.
-// UNSUPPORTED: android && clang-19.0
-
-// UNSUPPORTED: sanitizer-new-delete, c++03, c++11
-// XFAIL: apple-clang
-// XFAIL: using-built-library-before-llvm-11
-
-// AIX, z/OS, and MinGW default to -fno-sized-deallocation.
-// XFAIL: target={{.+}}-aix{{.*}}, target={{.+}}-zos{{.*}}, target={{.+}}-windows-gnu
-
-#include <new>
-#include <cstddef>
-#include <cstdlib>
-#include <cassert>
-
-#include "test_macros.h"
-
-int unsized_delete_called = 0;
-int unsized_delete_nothrow_called = 0;
-int sized_delete_called = 0;
-
-void operator delete[](void* p) TEST_NOEXCEPT
-{
- ++unsized_delete_called;
- std::free(p);
-}
-
-void operator delete[](void* p, const std::nothrow_t&) TEST_NOEXCEPT
-{
- ++unsized_delete_nothrow_called;
- std::free(p);
-}
-
-void operator delete[](void* p, std::size_t) TEST_NOEXCEPT
-{
- ++sized_delete_called;
- std::free(p);
-}
-
-// NOTE: Use a class with a non-trivial destructor as the test type in order
-// to ensure the correct overload is called.
-// C++14 5.3.5 [expr.delete]p10
-// - If the type is complete and if, for the second alternative (delete array)
-// only, the operand is a pointer to a class type with a non-trivial
-// destructor or a (possibly multi-dimensional) array thereof, the function
-// with two parameters is selected.
-// - Otherwise, it is unspecified which of the two deallocation functions is
-// selected.
-struct A { ~A() {} };
-
-int main(int, char**)
-{
- A* x = new A[3];
- assert(0 == unsized_delete_called);
- assert(0 == unsized_delete_nothrow_called);
- assert(0 == sized_delete_called);
-
- delete [] x;
- assert(0 == unsized_delete_called);
- assert(0 == unsized_delete_nothrow_called);
- assert(1 == sized_delete_called);
-
- return 0;
-}
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.pass.cpp
index dbb10a76ad9e9b..5d321f08282b21 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.pass.cpp
@@ -34,13 +34,12 @@ void my_new_handler() {
}
int main(int, char**) {
- // Test that we can call the function directly
- {
- void* x = operator new(10, static_cast<std::align_val_t>(64));
+ test_with_interesting_alignments([](std::size_t size, std::size_t alignment) {
+ void* x = operator new(size, static_cast<std::align_val_t>(alignment));
assert(x != nullptr);
- assert(reinterpret_cast<std::uintptr_t>(x) % 64 == 0);
- operator delete(x, static_cast<std::align_val_t>(64));
- }
+ assert(reinterpret_cast<std::uintptr_t>(x) % alignment == 0);
+ operator delete(x, static_cast<std::align_val_t>(alignment));
+ });
// Test that the new handler is called if allocation fails
{
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.pass.cpp
index b9d8ea2f4e4947..3e5ba574110fda 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.pass.cpp
@@ -34,13 +34,12 @@ void my_new_handler() {
}
int main(int, char**) {
- // Test that we can call the function directly
- {
- void* x = operator new(10, static_cast<std::align_val_t>(64), std::nothrow);
+ test_with_interesting_alignments([](std::size_t size, std::size_t alignment) {
+ void* x = operator new(size, static_cast<std::align_val_t>(alignment), std::nothrow);
assert(x != nullptr);
- assert(reinterpret_cast<std::uintptr_t>(x) % 64 == 0);
- operator delete(x, static_cast<std::align_val_t>(64), std::nothrow);
- }
+ assert(reinterpret_cast<std::uintptr_t>(x) % alignment == 0);
+ operator delete(x, static_cast<std::align_val_t>(alignment), std::nothrow);
+ });
// Test that the new handler is called and we return nullptr if allocation fails
{
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete14.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp
similarity index 62%
rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete14.pass.cpp
rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp
index e00339761ec24c..fd52df451afc81 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete14.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp
@@ -8,19 +8,35 @@
// Test sized operator delete replacement.
-// These compiler versions do not enable sized deallocation by default.
-// UNSUPPORTED: clang-17, clang-18
+// UNSUPPORTED: c++03, c++11
+
+// These compiler versions and platforms don't enable sized deallocation by default.
+// ADDITIONAL_COMPILE_FLAGS(clang-17): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(clang-18): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(apple-clang-15): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(apple-clang-16): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(target=x86_64-w64-windows-gnu): -fsized-deallocation
+// ADDITIONAL_COMPILE_FLAGS(target=i686-w64-windows-gnu): -fsized-deallocation
// Android clang-r536225 identifies as clang-19.0 but it predates the real
// LLVM 19.0.0, so it also leaves sized deallocation off by default.
// UNSUPPORTED: android && clang-19.0
-// UNSUPPORTED: sanitizer-new-delete, c++03, c++11
-// XFAIL: apple-clang
+// UNSUPPORTED: sanitizer-new-delete
+
+// Sized deallocation was introduced in LLVM 11
// XFAIL: using-built-library-before-llvm-11
-// AIX, z/OS, and MinGW default to -fno-sized-deallocation.
-// XFAIL: target={{.+}}-aix{{.*}}, target={{.+}}-zos{{.*}}, target={{.+}}-windows-gnu
+// AIX, and z/OS default to -fno-sized-deallocation.
+// XFAIL: target={{.+}}-aix{{.*}}, target={{.+}}-zos{{.*}}
+
+#if !defined(__cpp_sized_deallocation)
+# error __cpp_sized_deallocation should be defined
+#endif
+
+#if !(__cpp_sized_deallocation >= 201309L)
+# error expected __cpp_sized_deallocation >= 201309L
+#endif
#include <new>
#include <cstddef>
@@ -65,5 +81,5 @@ int main(int, char**)
assert(1 == sized_delete_called);
assert(0 == unsized_delete_nothrow_called);
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete_fsizeddeallocation.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete_fsizeddeallocation.pass.cpp
deleted file mode 100644
index ff88662d208751..00000000000000
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete_fsizeddeallocation.pass.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// test sized operator delete replacement.
-
-// Note that sized delete operator definitions below are simply ignored
-// when sized deallocation is not supported, e.g., prior to C++14.
-
-// UNSUPPORTED: sanitizer-new-delete
-
-// REQUIRES: -fsized-deallocation
-// ADDITIONAL_COMPILE_FLAGS: -fsized-deallocation -O3
-
-#if !defined(__cpp_sized_deallocation)
-# error __cpp_sized_deallocation should be defined
-#endif
-
-#if !(__cpp_sized_deallocation >= 201309L)
-# error expected __cpp_sized_deallocation >= 201309L
-#endif
-
-#include <new>
-#include <cstddef>
-#include <cstdlib>
-#include <cassert>
-
-#include "test_macros.h"
-
-int unsized_delete_called = 0;
-int unsized_delete_nothrow_called = 0;
-int sized_delete_called = 0;
-
-void operator delete(void* p) TEST_NOEXCEPT
-{
- ++unsized_delete_called;
- std::free(p);
-}
-
-void operator delete(void* p, const std::nothrow_t&) TEST_NOEXCEPT
-{
- ++unsized_delete_nothrow_called;
- std::free(p);
-}
-
-void operator delete(void* p, std::size_t) TEST_NOEXCEPT
-{
- ++sized_delete_called;
- std::free(p);
-}
-
-int main(int, char**)
-{
- int *x = new int(42);
- DoNotOptimize(x);
- assert(0 == sized_delete_called);
- assert(0 == unsized_delete_called);
- assert(0 == unsized_delete_nothrow_called);
-
- delete x;
- DoNotOptimize(x);
- assert(1 == sized_delete_called);
- assert(0 == unsized_delete_called);
- assert(0 == unsized_delete_nothrow_called);
-
- return 0;
-}
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/types.h b/libcxx/test/std/language.support/support.dynamic/new.delete/types.h
index f19de73bf4417a..46a2d6ce7f0111 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/types.h
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/types.h
@@ -60,4 +60,35 @@ struct alignas(std::max_align_t) MaxAligned {
};
#endif // TEST_STD_VER >= 17
+template <class F>
+void test_with_interesting_alignments(F f) {
+ // First, check the basic case, a large allocation with alignment == size.
+ f(/* size */ 64, /* alignment */ 64);
+
+ // Size being a multiple of alignment also needs to be supported.
+ f(/* size */ 64, /* alignment */ 32);
+
+ // Test with a non power-of-two size.
+ f(/* size */ 10, /* alignment */ 64);
+
+ // When aligned allocation is implemented using aligned_alloc,
+ // that function requires a minimum alignment of sizeof(void*).
+ //
+ // Check that we can also create overaligned allocations with
+ // an alignment argument less than sizeof(void*).
+ f(/* size */ 2, /* alignment */ 2);
+
+ // When implemented using the C11 aligned_alloc() function,
+ // that requires that size be a multiple of alignment.
+ // However, the C++ operator new has no such requirements.
+ //
+ // Check that we can create an overaligned allocation that does
+ // adhere to not have this constraint.
+ f(/* size */ 1, /* alignment */ 128);
+
+ // Finally, test size > alignment, but with size not being
+ // a multiple of alignment.
+ f(/* size */ 65, /* alignment */ 32);
+}
+
#endif // TEST_STD_LANGUAGE_SUPPORT_SUPPORT_DYNAMIC_NEW_DELETE_TYPES_H
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index 49b61c8935e1ba..e4b413deff4dba 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -159,14 +159,6 @@ def _mingwSupportsModules(cfg):
when=lambda cfg: hasCompileFlag(cfg, "-fconstexpr-ops-limit=1"),
),
Feature(name="has-fblocks", when=lambda cfg: hasCompileFlag(cfg, "-fblocks")),
- Feature(
- name="-fsized-deallocation",
- when=lambda cfg: hasCompileFlag(cfg, "-fsized-deallocation"),
- ),
- Feature(
- name="-faligned-allocation",
- when=lambda cfg: hasCompileFlag(cfg, "-faligned-allocation"),
- ),
Feature(
name="fdelayed-template-parsing",
when=lambda cfg: hasCompileFlag(cfg, "-fdelayed-template-parsing"),
More information about the libcxx-commits
mailing list