diff --git a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp --- a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp +++ b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp @@ -13,7 +13,7 @@ // using those with -faligned-allocation results in a link error. // XFAIL: availability-aligned_allocation-missing -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} 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 --- 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 @@ -13,7 +13,7 @@ // using those with -faligned-allocation results in a link error. // XFAIL: availability-aligned_allocation-missing -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} 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 --- 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 @@ -10,7 +10,7 @@ // UNSUPPORTED: c++03, c++11, c++14 -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: sanitizer-new-delete, c++03, c++11, c++14 -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size.verify.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.nodiscard.verify.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size.verify.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.nodiscard.verify.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size.verify.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.nodiscard.verify.cpp @@ -6,9 +6,7 @@ // //===----------------------------------------------------------------------===// -// - -// void* operator new[](std::size_t); +// [[nodiscard]] void* operator new[](std::size_t); // UNSUPPORTED: c++03, c++11, c++14, c++17 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t); + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_handler_called = 0; + +void my_new_handler() { + ++new_handler_called; + std::set_new_handler(0); +} + +int main(int, char**) { + // Test that the new handler is called if allocation fails + { +#ifndef TEST_HAS_NO_EXCEPTIONS + std::set_new_handler(my_new_handler); + try { + void* x = operator new[] (std::numeric_limits::max()); + (void)x; + assert(false); + } + catch (std::bad_alloc const&) { + assert(new_handler_called == 1); + } catch (...) { + assert(false); + } + } +#endif + + // Test that a new expression constructs the right objects + // and a delete expression deletes them + { + LifetimeInformation infos[3]; + TrackLifetime* xs = new TrackLifetime[3]{infos[0], infos[1], infos[2]}; + assert(xs != nullptr); + + void* addresses[3] = {&xs[0], &xs[1], &xs[2]}; + assert(infos[0].address_constructed == addresses[0]); + assert(infos[1].address_constructed == addresses[1]); + assert(infos[2].address_constructed == addresses[2]); + + delete[] xs; + assert(infos[0].address_destroyed == addresses[0]); + assert(infos[1].address_destroyed == addresses[1]); + assert(infos[2].address_destroyed == addresses[2]); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// -// test operator new[] replacement by replacing only operator new +// void* operator new[](std::size_t); + +// Test that we can replace the operator by replacing the `operator new(std::size_t)` (the non-array version). // UNSUPPORTED: sanitizer-new-delete // XFAIL: libcpp-no-vcruntime @@ -21,41 +23,29 @@ #include "test_macros.h" int new_called = 0; +int delete_called = 0; -void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) -{ +TEST_WORKAROUND_BUG_109234844_WEAK +void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) { ++new_called; void* ret = std::malloc(s); if (!ret) std::abort(); // placate MSVC's unchecked malloc warning return ret; } -void operator delete(void* p) TEST_NOEXCEPT -{ - --new_called; +void operator delete(void* p) TEST_NOEXCEPT { + ++delete_called; std::free(p); } -int A_constructed = 0; - -struct A -{ - A() {++A_constructed;} - ~A() {--A_constructed;} -}; - -int main(int, char**) -{ - new_called = 0; - A *ap = new A[3]; - DoNotOptimize(ap); - assert(ap); - assert(A_constructed == 3); +int main(int, char**) { + new_called = delete_called = 0; + int* x = new int[3]{1, 2, 3}; + assert(x != nullptr); ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1); - delete [] ap; - DoNotOptimize(ap); - assert(A_constructed == 0); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 0); - return 0; + delete[] x; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + + return 0; } diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// -// test operator new [] nothrow by replacing only operator new +// void* operator new[](std::size_t); + +// Test that we can replace the operator by defining our own. // UNSUPPORTED: sanitizer-new-delete // XFAIL: libcpp-no-vcruntime @@ -21,41 +23,28 @@ #include "test_macros.h" int new_called = 0; +int delete_called = 0; -void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) -{ +void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc) { ++new_called; void* ret = std::malloc(s); if (!ret) std::abort(); // placate MSVC's unchecked malloc warning return ret; } -void operator delete(void* p) TEST_NOEXCEPT -{ - --new_called; +void operator delete[](void* p) TEST_NOEXCEPT { + ++delete_called; std::free(p); } -int A_constructed = 0; - -struct A -{ - A() {++A_constructed;} - ~A() {--A_constructed;} -}; - -int main(int, char**) -{ - new_called = 0; - A *ap = new (std::nothrow) A[3]; - DoNotOptimize(ap); - assert(ap); - assert(A_constructed == 3); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called); - delete [] ap; - DoNotOptimize(ap); - assert(A_constructed == 0); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called); - - return 0; +int main(int, char**) { + new_called = delete_called = 0; + int* x = new int[3]{1, 2, 3}; + assert(x != nullptr); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1); + + delete[] x; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + + return 0; } diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align.verify.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.nodiscard.verify.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align.verify.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.nodiscard.verify.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align.verify.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.nodiscard.verify.cpp @@ -6,13 +6,11 @@ // //===----------------------------------------------------------------------===// -// - -// void* operator new[](std::size_t, std::align_val_t); +// [[nodiscard]] void* operator new[](std::size_t, std::align_val_t); // UNSUPPORTED: c++03, c++11, c++14, c++17 -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} 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 new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t, std::align_val_t); + +// UNSUPPORTED: c++03, c++11, c++14 + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +// We get availability markup errors when aligned allocation is missing +// XFAIL: availability-aligned_allocation-missing + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_handler_called = 0; + +void my_new_handler() { + ++new_handler_called; + std::set_new_handler(0); +} + +int main(int, char**) { + // Test that the new handler is called if allocation fails + { +#ifndef TEST_HAS_NO_EXCEPTIONS + std::set_new_handler(my_new_handler); + try { + void* x = operator new[] (std::numeric_limits::max(), + static_cast(32)); + (void)x; + assert(false); + } catch (std::bad_alloc const&) { + assert(new_handler_called == 1); + } catch (...) { + assert(false); + } +#endif + } + + // Test that a new expression constructs the right object + // and a delete expression deletes it + { + LifetimeInformation infos[3]; + TrackLifetimeOverAligned* xs = new TrackLifetimeOverAligned[3]{infos[0], infos[1], infos[2]}; + assert(xs != nullptr); + assert(reinterpret_cast(xs) % alignof(TrackLifetimeOverAligned) == 0); + + void* addresses[3] = {&xs[0], &xs[1], &xs[2]}; + assert(infos[0].address_constructed == addresses[0]); + assert(infos[1].address_constructed == addresses[1]); + assert(infos[2].address_constructed == addresses[2]); + + delete[] xs; + assert(infos[0].address_destroyed == addresses[0]); + assert(infos[1].address_destroyed == addresses[1]); + assert(infos[2].address_destroyed == addresses[2]); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t, std::align_val_t); + +// Test that we can replace the operator by replacing `operator new(std::size_t, std::align_val_t)` (the non-array version). + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: sanitizer-new-delete + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_called = 0; +int delete_called = 0; + +alignas(OverAligned) char DummyData[alignof(OverAligned) * 3]; + +TEST_WORKAROUND_BUG_109234844_WEAK +void* operator new(std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) { + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == alignof(OverAligned)); + ++new_called; + return DummyData; +} + +void operator delete(void*, std::align_val_t) TEST_NOEXCEPT { + ++delete_called; + // nothing to delete, we didn't actually allocate in `operator new` +} + +int main(int, char**) { + // Test with an overaligned type + { + new_called = delete_called = 0; + OverAligned* xs = new OverAligned[3]; + assert(static_cast(xs) == DummyData); + assert(new_called == 1); + + delete[] xs; + assert(delete_called == 1); + } + + // Test with a type that is right on the verge of being overaligned + { + new_called = delete_called = 0; + MaxAligned* xs = new MaxAligned[3]; + assert(xs != nullptr); + assert(new_called == 0); + + delete[] xs; + assert(delete_called == 0); + } + + // Test with a type that is clearly not overaligned + { + new_called = delete_called = 0; + int* xs = new int[3]; + assert(xs != nullptr); + assert(new_called == 0); + + delete[] xs; + assert(delete_called == 0); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t, std::align_val_t); + +// Test that we can replace the operator by defining our own. + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: sanitizer-new-delete + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_called = 0; +int delete_called = 0; + +alignas(OverAligned) char DummyData[alignof(OverAligned) * 3]; + +void* operator new[](std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) { + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == alignof(OverAligned)); + ++new_called; + return DummyData; +} + +void operator delete[](void*, std::align_val_t) TEST_NOEXCEPT { + ++delete_called; + // nothing to delete, we didn't actually allocate in `operator new` +} + +int main(int, char**) { + // Test with an overaligned type + { + new_called = delete_called = 0; + OverAligned* xs = new OverAligned[3]; + assert(static_cast(xs) == DummyData); + assert(new_called == 1); + + delete[] xs; + assert(delete_called == 1); + } + + // Test with a type that is right on the verge of being overaligned + { + new_called = delete_called = 0; + MaxAligned* xs = new MaxAligned[3]; + assert(xs != nullptr); + assert(new_called == 0); + + delete[] xs; + assert(delete_called == 0); + } + + // Test with a type that is clearly not overaligned + { + new_called = delete_called = 0; + int* xs = new int[3]; + assert(xs != nullptr); + assert(new_called == 0); + + delete[] xs; + assert(delete_called == 0); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align_nothrow.verify.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.nodiscard.verify.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align_nothrow.verify.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.nodiscard.verify.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_align_nothrow.verify.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.nodiscard.verify.cpp @@ -6,13 +6,11 @@ // //===----------------------------------------------------------------------===// -// - -// void* operator new[](std::size_t, std::align_val_t, std::nothrow_t &); +// [[nodiscard]] void* operator new[](std::size_t, std::align_val_t, std::nothrow_t const&); // UNSUPPORTED: c++03, c++11, c++14, c++17 -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} 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 new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t, std::align_val_t, std::nothrow_t const&); + +// UNSUPPORTED: c++03, c++11, c++14 + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +// We get availability markup errors when aligned allocation is missing +// XFAIL: availability-aligned_allocation-missing + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_handler_called = 0; + +void my_new_handler() { + ++new_handler_called; + std::set_new_handler(0); +} + +int main(int, char**) { + // Test that the new handler is called and we return nullptr if allocation fails + { + std::set_new_handler(my_new_handler); + void* x = operator new[](std::numeric_limits::max(), + static_cast(32), std::nothrow); + assert(new_handler_called == 1); + assert(x == nullptr); + } + + // Test that a new expression constructs the right object + // and a delete expression deletes it + { + LifetimeInformation infos[3]; + TrackLifetimeOverAligned* xs = new (std::nothrow) TrackLifetimeOverAligned[3]{infos[0], infos[1], infos[2]}; + assert(xs != nullptr); + assert(reinterpret_cast(xs) % alignof(TrackLifetimeOverAligned) == 0); + + void* addresses[3] = {&xs[0], &xs[1], &xs[2]}; + assert(infos[0].address_constructed == addresses[0]); + assert(infos[1].address_constructed == addresses[1]); + assert(infos[2].address_constructed == addresses[2]); + + delete[] xs; + assert(infos[0].address_destroyed == addresses[0]); + assert(infos[1].address_destroyed == addresses[1]); + assert(infos[2].address_destroyed == addresses[2]); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t, std::align_val_t, std::nothrow_t const&); + +// Test that we can replace the operator by replacing `operator new[](std::size_t, std::align_val_t)` +// (the throwing version). + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: sanitizer-new-delete + +// XFAIL: LIBCXX-AIX-FIXME + +// We get availability markup errors when aligned allocation is missing +// XFAIL: availability-aligned_allocation-missing + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_called = 0; +int delete_called = 0; + +alignas(OverAligned) char DummyData[alignof(OverAligned) * 3]; + +TEST_WORKAROUND_BUG_109234844_WEAK +void* operator new[](std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) { + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == alignof(OverAligned)); + ++new_called; + return DummyData; +} + +void operator delete[](void*, std::align_val_t) TEST_NOEXCEPT { + ++delete_called; + // nothing to delete, we didn't actually allocate in `operator new` +} + +int main(int, char**) { + // Test with an overaligned type + { + new_called = delete_called = 0; + OverAligned* xs = new (std::nothrow) OverAligned[3]; + assert(static_cast(xs) == DummyData); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1); + + delete[] xs; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + } + + // Test with a type that is right on the verge of being overaligned + { + new_called = delete_called = 0; + MaxAligned* xs = new (std::nothrow) MaxAligned[3]; + assert(xs != nullptr); + assert(new_called == 0); + + delete[] xs; + assert(delete_called == 0); + } + + // Test with a type that is clearly not overaligned + { + new_called = delete_called = 0; + int* xs = new (std::nothrow) int[3]; + assert(xs != nullptr); + assert(new_called == 0); + + delete[] xs; + assert(delete_called == 0); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t, std::align_val_t, std::nothrow_t const&); + +// Test that we can replace the operator by defining our own. + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: sanitizer-new-delete + +// XFAIL: LIBCXX-AIX-FIXME + +// We get availability markup errors when aligned allocation is missing +// XFAIL: availability-aligned_allocation-missing + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_nothrow_called = 0; +int delete_called = 0; + +alignas(OverAligned) char DummyData[alignof(OverAligned) * 3]; + +TEST_WORKAROUND_BUG_109234844_WEAK +void* operator new[](std::size_t s, std::align_val_t a, std::nothrow_t const&) TEST_NOEXCEPT { + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == alignof(OverAligned)); + ++new_nothrow_called; + return DummyData; +} + +void operator delete[](void*, std::align_val_t) TEST_NOEXCEPT { + ++delete_called; + // nothing to delete, we didn't actually allocate in `operator new` +} + +int main(int, char**) { + // Test with an overaligned type + { + new_nothrow_called = delete_called = 0; + OverAligned* xs = new (std::nothrow) OverAligned[3]; + assert(static_cast(xs) == DummyData); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1); + + delete[] xs; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + } + + // Test with a type that is right on the verge of being overaligned + { + new_nothrow_called = delete_called = 0; + MaxAligned* xs = new (std::nothrow) MaxAligned[3]; + assert(xs != nullptr); + assert(new_nothrow_called == 0); + + delete[] xs; + assert(delete_called == 0); + } + + // Test with a type that is clearly not overaligned + { + new_nothrow_called = delete_called = 0; + int* xs = new (std::nothrow) int[3]; + assert(xs != nullptr); + assert(new_nothrow_called == 0); + + delete[] xs; + assert(delete_called == 0); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_nothrow.verify.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.nodiscard.verify.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_nothrow.verify.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.nodiscard.verify.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_size_nothrow.verify.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.nodiscard.verify.cpp @@ -6,9 +6,7 @@ // //===----------------------------------------------------------------------===// -// - -// void* operator new[](std::size_t, std::nothrow_t &); +// [[nodiscard]] void* operator new[](std::size_t, std::nothrow_t const&); // UNSUPPORTED: c++03, c++11, c++14, c++17 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t, std::nothrow_t const&); + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_handler_called = 0; + +void my_new_handler() { + ++new_handler_called; + std::set_new_handler(0); +} + +int main(int, char**) { + // Test that the new handler is called and we return nullptr if allocation fails + { + std::set_new_handler(my_new_handler); + void* x = operator new[](std::numeric_limits::max(), std::nothrow); + assert(new_handler_called == 1); + assert(x == nullptr); + } + + // Test that a new expression constructs the right objects + // and a delete expression deletes them + { + LifetimeInformation infos[3]; + TrackLifetime* xs = new (std::nothrow) TrackLifetime[3]{infos[0], infos[1], infos[2]}; + assert(xs != nullptr); + + void* addresses[3] = {&xs[0], &xs[1], &xs[2]}; + assert(infos[0].address_constructed == addresses[0]); + assert(infos[1].address_constructed == addresses[1]); + assert(infos[2].address_constructed == addresses[2]); + + delete[] xs; + assert(infos[0].address_destroyed == addresses[0]); + assert(infos[1].address_destroyed == addresses[1]); + assert(infos[2].address_destroyed == addresses[2]); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// -// test operator new[] replacement by replacing only operator new +// void* operator new[](std::size_t, std::nothrow_t const&); + +// Test that we can replace the operator by replacing `operator new[](std::size_t)` (the throwing version). // UNSUPPORTED: sanitizer-new-delete // XFAIL: libcpp-no-vcruntime @@ -16,46 +18,33 @@ #include #include #include -#include #include "test_macros.h" int new_called = 0; +int delete_called = 0; -void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) -{ +TEST_WORKAROUND_BUG_109234844_WEAK +void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc) { ++new_called; void* ret = std::malloc(s); if (!ret) std::abort(); // placate MSVC's unchecked malloc warning - return ret; + return ret; } -void operator delete(void* p) TEST_NOEXCEPT -{ - --new_called; +void operator delete(void* p) TEST_NOEXCEPT { + ++delete_called; std::free(p); } -int A_constructed = 0; - -struct A -{ - A() {++A_constructed;} - ~A() {--A_constructed;} -}; - -int main(int, char**) -{ - new_called = 0; - A *ap = new A[3]; - DoNotOptimize(ap); - assert(ap); - assert(A_constructed == 3); +int main(int, char**) { + new_called = delete_called = 0; + int* x = new (std::nothrow) int[3]{1, 2, 3}; + assert(x != nullptr); ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1); - delete [] ap; - DoNotOptimize(ap); - assert(A_constructed == 0); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 0); - return 0; + delete[] x; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + + return 0; } diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new[](std::size_t, std::nothrow_t const&); + +// Test that we can replace the operator by defining our own. + +// UNSUPPORTED: sanitizer-new-delete +// XFAIL: libcpp-no-vcruntime +// XFAIL: LIBCXX-AIX-FIXME + +#include +#include +#include +#include + +#include "test_macros.h" + +int new_nothrow_called = 0; +int delete_called = 0; + +void* operator new[](std::size_t s, std::nothrow_t const&) TEST_NOEXCEPT { + ++new_nothrow_called; + return std::malloc(s); +} + +void operator delete[](void* p) TEST_NOEXCEPT { + ++delete_called; + std::free(p); +} + +int main(int, char**) { + new_nothrow_called = delete_called = 0; + int* xs = new (std::nothrow) int[3]{1, 2, 3}; + assert(xs != nullptr); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1); + + assert(delete_called == 0); + delete[] xs; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp +++ /dev/null @@ -1,87 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14 - -// asan and msan will not call the new handler. -// UNSUPPORTED: sanitizer-new-delete - -// We get availability markup errors when aligned allocation is missing -// XFAIL: availability-aligned_allocation-missing - -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, -// nor does the dynamic library shipped with z/OS. -// UNSUPPORTED: target={{.+}}-zos{{.*}} - -// test operator new (nothrow) - -#include -#include -#include -#include -#include - -#include "test_macros.h" - -constexpr auto OverAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; - -int new_handler_called = 0; - -void my_new_handler() -{ - ++new_handler_called; - std::set_new_handler(0); -} - -int A_constructed = 0; - -struct alignas(OverAligned) A -{ - A() { ++A_constructed; } - ~A() { --A_constructed; } -}; - -void test_max_alloc() { - std::set_new_handler(my_new_handler); - auto do_test = []() { - void* vp = operator new [](std::numeric_limits::max(), - std::align_val_t(OverAligned), - std::nothrow); - assert(new_handler_called == 1); - assert(vp == 0); - }; -#ifndef TEST_HAS_NO_EXCEPTIONS - try - { - do_test(); - } - catch (...) - { - assert(false); - } -#else - do_test(); -#endif -} - -int main(int, char**) -{ - { - A* ap = new(std::nothrow) A[3]; - assert(ap); - assert(reinterpret_cast(ap) % OverAligned == 0); - assert(A_constructed == 3); - delete [] ap; - assert(!A_constructed); - } - { - test_max_alloc(); - } - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp +++ /dev/null @@ -1,91 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14 -// UNSUPPORTED: sanitizer-new-delete - -// XFAIL: LIBCXX-AIX-FIXME - -// We get availability markup errors when aligned allocation is missing -// XFAIL: availability-aligned_allocation-missing - -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, -// nor does the dynamic library shipped with z/OS. -// UNSUPPORTED: target={{.+}}-zos{{.*}} - -// test operator new nothrow by replacing only operator new - -#include -#include -#include -#include -#include - -#include "test_macros.h" - -constexpr auto OverAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; - -int A_constructed = 0; - -struct alignas(OverAligned) A -{ - A() {++A_constructed;} - ~A() {--A_constructed;} -}; - -int B_constructed = 0; - -struct B { - std::max_align_t member; - B() { ++B_constructed; } - ~B() { --B_constructed; } -}; - -int new_called = 0; -alignas(OverAligned) char Buff[OverAligned * 3]; - -void* operator new[](std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) -{ - assert(!new_called); - assert(s <= sizeof(Buff)); - assert(static_cast(a) == OverAligned); - ++new_called; - return Buff; -} - -void operator delete[](void* p, std::align_val_t a) TEST_NOEXCEPT -{ - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(p == Buff); - assert(static_cast(a) == OverAligned); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called); - --new_called; -} - -int main(int, char**) -{ - { - A* ap = new (std::nothrow) A[2]; - assert(ap); - assert(A_constructed == 2); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called); - delete [] ap; - assert(A_constructed == 0); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called); - } - { - B* bp = new (std::nothrow) B[2]; - assert(bp); - assert(B_constructed == 2); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called); - delete [] bp; - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called); - assert(!B_constructed); - } - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_replace.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_replace.pass.cpp +++ /dev/null @@ -1,91 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14 -// UNSUPPORTED: sanitizer-new-delete - -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, -// nor does the dynamic library shipped with z/OS. -// UNSUPPORTED: target={{.+}}-zos{{.*}} - -// test operator new replacement - -#include -#include -#include -#include -#include -#include - -#include "test_macros.h" - -constexpr auto OverAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; - -int A_constructed = 0; - -struct alignas(OverAligned) A { - A() { ++A_constructed;} - ~A() { --A_constructed;} -}; - - -int B_constructed = 0; - -struct alignas(std::max_align_t) B -{ - std::max_align_t member; - B() { ++B_constructed;} - ~B() { --B_constructed;} -}; - -int new_called = 0; - -alignas(OverAligned) char DummyData[OverAligned * 4]; - -void* operator new[](std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) -{ - assert(new_called == 0); // We already allocated - assert(s <= sizeof(DummyData)); - assert(static_cast(a) == OverAligned); - ++new_called; - void *Ret = DummyData; - DoNotOptimize(Ret); - return Ret; -} - -void operator delete[](void* p, std::align_val_t) TEST_NOEXCEPT -{ - assert(new_called == 1); - --new_called; - assert(p == DummyData); - DoNotOptimize(p); -} - - -int main(int, char**) -{ - { - A* ap = new A[3]; - assert(ap); - assert(A_constructed == 3); - assert(new_called); - delete [] ap; - assert(!A_constructed); - assert(!new_called); - } - { - B* bp = new B[3]; - assert(bp); - assert(B_constructed == 3); - assert(!new_called); - delete [] bp; - assert(!new_called); - } - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array.pass.cpp +++ /dev/null @@ -1,65 +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 operator new[] -// NOTE: asan and msan will not call the new handler. -// UNSUPPORTED: sanitizer-new-delete - - -#include -#include -#include -#include - -#include "test_macros.h" - -int new_handler_called = 0; - -void my_new_handler() -{ - ++new_handler_called; - std::set_new_handler(0); -} - -int A_constructed = 0; - -struct A -{ - A() {++A_constructed;} - ~A() {--A_constructed;} -}; - -int main(int, char**) -{ -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_new_handler(my_new_handler); - try - { - void* vp = operator new[] (std::numeric_limits::max()); - DoNotOptimize(vp); - assert(false); - } - catch (std::bad_alloc&) - { - assert(new_handler_called == 1); - } - catch (...) - { - assert(false); - } -#endif - A* ap = new A[3]; - DoNotOptimize(ap); - assert(ap); - assert(A_constructed == 3); - delete [] ap; - DoNotOptimize(ap); - assert(A_constructed == 0); - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow.pass.cpp +++ /dev/null @@ -1,65 +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 operator new [] (nothrow) -// NOTE: asan and msan will not call the new handler. -// UNSUPPORTED: sanitizer-new-delete - - -#include -#include -#include -#include - -#include "test_macros.h" - -int new_handler_called = 0; - -void my_new_handler() -{ - ++new_handler_called; - std::set_new_handler(0); -} - -int A_constructed = 0; - -struct A -{ - A() {++A_constructed;} - ~A() {--A_constructed;} -}; - -int main(int, char**) -{ - new_handler_called = 0; - std::set_new_handler(my_new_handler); -#ifndef TEST_HAS_NO_EXCEPTIONS - try -#endif - { - void* vp = operator new [] (std::numeric_limits::max(), std::nothrow); - DoNotOptimize(vp); - assert(new_handler_called == 1); - assert(vp == 0); - } -#ifndef TEST_HAS_NO_EXCEPTIONS - catch (...) - { - assert(false); - } -#endif - A* ap = new(std::nothrow) A[3]; - DoNotOptimize(ap); - assert(ap); - assert(A_constructed == 3); - delete [] ap; - DoNotOptimize(ap); - assert(A_constructed == 0); - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp @@ -10,10 +10,7 @@ // UNSUPPORTED: sanitizer-new-delete, c++03, c++11, c++14 -// Aligned allocation was not provided before macosx10.14 and as a result we -// get availability errors when the deployment target is older than macosx10.14. - -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.pass.cpp +++ /dev/null @@ -1,63 +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 operator new - -// asan and msan will not call the new handler. -// UNSUPPORTED: sanitizer-new-delete - -#include -#include -#include -#include - -#include "test_macros.h" - -int new_handler_called = 0; - -void my_new_handler() -{ - ++new_handler_called; - std::set_new_handler(0); -} - -bool A_constructed = false; - -struct A -{ - A() {A_constructed = true;} - ~A() {A_constructed = false;} -}; - -int main(int, char**) -{ -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_new_handler(my_new_handler); - try - { - void* vp = operator new (std::numeric_limits::max()); - ((void)vp); - assert(false); - } - catch (std::bad_alloc&) - { - assert(new_handler_called == 1); - } - catch (...) - { - assert(false); - } -#endif - A* ap = new A; - assert(ap); - assert(A_constructed); - delete ap; - assert(!A_constructed); - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size.verify.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.nodiscard.verify.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size.verify.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.nodiscard.verify.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size.verify.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.nodiscard.verify.cpp @@ -6,9 +6,7 @@ // //===----------------------------------------------------------------------===// -// - -// void* operator new(std::size_t); +// [[nodiscard]] void* operator new(std::size_t); // UNSUPPORTED: c++03, c++11, c++14, c++17 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new(std::size_t); + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_handler_called = 0; + +void my_new_handler() { + ++new_handler_called; + std::set_new_handler(0); +} + +int main(int, char**) { + // Test that the new handler is called if allocation fails + { +#ifndef TEST_HAS_NO_EXCEPTIONS + std::set_new_handler(my_new_handler); + try { + void* x = operator new (std::numeric_limits::max()); + (void)x; + assert(false); + } catch (std::bad_alloc const&) { + assert(new_handler_called == 1); + } catch (...) { + assert(false); + } +#endif + } + + // Test that a new expression constructs the right object + // and a delete expression deletes it + { + LifetimeInformation info; + TrackLifetime* x = new TrackLifetime(info); + assert(x != nullptr); + assert(info.address_constructed == x); + + delete x; + assert(info.address_destroyed == x); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_replace.pass.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// -// test operator new replacement +// void* operator new(std::size_t); + +// Test that we can replace the operator by defining our own. // UNSUPPORTED: sanitizer-new-delete @@ -14,46 +16,32 @@ #include #include #include -#include #include "test_macros.h" int new_called = 0; +int delete_called = 0; -void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) -{ +void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) { ++new_called; void* ret = std::malloc(s); if (!ret) std::abort(); // placate MSVC's unchecked malloc warning return ret; } -void operator delete(void* p) TEST_NOEXCEPT -{ - --new_called; +void operator delete(void* p) TEST_NOEXCEPT { + ++delete_called; std::free(p); } -bool A_constructed = false; - -struct A -{ - A() {A_constructed = true;} - ~A() {A_constructed = false;} -}; - -int main(int, char**) -{ - new_called = 0; - A *ap = new A; - DoNotOptimize(ap); - assert(ap); - assert(A_constructed); - assert(new_called); - delete ap; - DoNotOptimize(ap); - assert(!A_constructed); - assert(!new_called); - - return 0; +int main(int, char**) { + new_called = delete_called = 0; + int* x = new int(3); + assert(x != nullptr); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1); + + delete x; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + + return 0; } diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align.verify.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.nodiscard.verify.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align.verify.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.nodiscard.verify.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align.verify.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.nodiscard.verify.cpp @@ -6,13 +6,11 @@ // //===----------------------------------------------------------------------===// -// - -// void* operator new(std::size_t, std::align_val_t); +// [[nodiscard]] void* operator new(std::size_t, std::align_val_t); // UNSUPPORTED: c++03, c++11, c++14, c++17 -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.pass.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.pass.cpp @@ -6,20 +6,20 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++03, c++11, c++14 +// void* operator new(std::size_t, std::align_val_t); -// asan and msan will not call the new handler. -// UNSUPPORTED: sanitizer-new-delete +// UNSUPPORTED: c++03, c++11, c++14 // We get availability markup errors when aligned allocation is missing // XFAIL: availability-aligned_allocation-missing -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} -// test operator new - #include #include #include @@ -27,59 +27,45 @@ #include #include "test_macros.h" - -constexpr auto OverAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; +#include "../types.h" int new_handler_called = 0; -void my_new_handler() -{ +void my_new_handler() { ++new_handler_called; std::set_new_handler(0); } -int A_constructed = 0; - -struct alignas(OverAligned) A -{ - A() { ++A_constructed;} - ~A() { --A_constructed;} -}; - -void test_throw_max_size() { -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_new_handler(my_new_handler); - try +int main(int, char**) { + // Test that the new handler is called if allocation fails { - void* vp = operator new[] (std::numeric_limits::max(), +#ifndef TEST_HAS_NO_EXCEPTIONS + std::set_new_handler(my_new_handler); + try { + void* x = operator new (std::numeric_limits::max(), static_cast(32)); - ((void)vp); - assert(false); - } - catch (std::bad_alloc&) - { - assert(new_handler_called == 1); - } - catch (...) - { - assert(false); - } + (void)x; + assert(false); + } catch (std::bad_alloc const&) { + assert(new_handler_called == 1); + } catch (...) { + assert(false); + } #endif -} - -int main(int, char**) -{ - { - A* ap = new A[2]; - assert(ap); - assert(reinterpret_cast(ap) % OverAligned == 0); - assert(A_constructed == 2); - delete [] ap; - assert(A_constructed == 0); } + + // Test that a new expression constructs the right object + // and a delete expression deletes it { - test_throw_max_size(); + LifetimeInformation info; + TrackLifetimeOverAligned* x = new TrackLifetimeOverAligned(info); + assert(x != nullptr); + assert(reinterpret_cast(x) % alignof(TrackLifetimeOverAligned) == 0); + assert(info.address_constructed == x); + + delete x; + assert(info.address_destroyed == x); } - return 0; + return 0; } diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.replace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align.replace.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new(std::size_t, std::align_val_t); + +// Test that we can replace the operator by defining our own. + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: sanitizer-new-delete + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_called = 0; +int delete_called = 0; + +alignas(OverAligned) char DummyData[alignof(OverAligned)]; + +void* operator new(std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) { + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == alignof(OverAligned)); + ++new_called; + return DummyData; +} + +void operator delete(void*, std::align_val_t) TEST_NOEXCEPT { + ++delete_called; + // nothing to delete, we didn't actually allocate in `operator new` +} + +int main(int, char**) { + // Test with an overaligned type + { + new_called = delete_called = 0; + OverAligned* x = new OverAligned; + assert(static_cast(x) == DummyData); + assert(new_called == 1); + + delete x; + assert(delete_called == 1); + } + + // Test with a type that is right on the verge of being overaligned + { + new_called = delete_called = 0; + MaxAligned* x = new MaxAligned; + assert(x != nullptr); + assert(new_called == 0); + + delete x; + assert(delete_called == 0); + } + + // Test with a type that is clearly not overaligned + { + new_called = delete_called = 0; + int* x = new int; + assert(x != nullptr); + assert(new_called == 0); + + delete x; + assert(delete_called == 0); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align_nothrow.verify.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.nodiscard.verify.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align_nothrow.verify.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.nodiscard.verify.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_align_nothrow.verify.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.nodiscard.verify.cpp @@ -6,13 +6,11 @@ // //===----------------------------------------------------------------------===// -// - -// void* operator new(std::size_t, std::align_val_t, std::nothrow_t &); +// [[nodiscard]] void* operator new(std::size_t, std::align_val_t, std::nothrow_t const&); // UNSUPPORTED: c++03, c++11, c++14, c++17 -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. // UNSUPPORTED: target={{.+}}-zos{{.*}} 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 new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new(std::size_t, std::align_val_t, std::nothrow_t const&); + +// UNSUPPORTED: c++03, c++11, c++14 + +// We get availability markup errors when aligned allocation is missing +// XFAIL: availability-aligned_allocation-missing + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_handler_called = 0; + +void my_new_handler() { + ++new_handler_called; + std::set_new_handler(0); +} + +int main(int, char**) { + // Test that the new handler is called and we return nullptr if allocation fails + { + std::set_new_handler(my_new_handler); + void* x = operator new(std::numeric_limits::max(), + static_cast(32), std::nothrow); + assert(new_handler_called == 1); + assert(x == nullptr); + } + + // Test that a new expression constructs the right object + // and a delete expression deletes it + { + LifetimeInformation info; + TrackLifetimeOverAligned* x = new (std::nothrow) TrackLifetimeOverAligned(info); + assert(x != nullptr); + assert(reinterpret_cast(x) % alignof(TrackLifetimeOverAligned) == 0); + assert(info.address_constructed == x); + + delete x; + assert(info.address_destroyed == x); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new(std::size_t, std::align_val_t, std::nothrow_t const&); + +// Test that we can replace the operator by replacing `operator new(std::size_t, std::align_val_t)` (the throwing version). + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: sanitizer-new-delete + +// XFAIL: LIBCXX-AIX-FIXME + +// We get availability markup errors when aligned allocation is missing +// XFAIL: availability-aligned_allocation-missing + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_called = 0; +int delete_called = 0; + +alignas(OverAligned) char DummyData[alignof(OverAligned)]; + +TEST_WORKAROUND_BUG_109234844_WEAK +void* operator new(std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) { + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == alignof(OverAligned)); + ++new_called; + return DummyData; +} + +void operator delete(void*, std::align_val_t) TEST_NOEXCEPT { + ++delete_called; + // nothing to delete, we didn't actually allocate in `operator new` +} + +int main(int, char**) { + // Test with an overaligned type + { + new_called = delete_called = 0; + OverAligned* x = new (std::nothrow) OverAligned; + assert(static_cast(x) == DummyData); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1); + + delete x; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + } + + // Test with a type that is right on the verge of being overaligned + { + new_called = delete_called = 0; + MaxAligned* x = new (std::nothrow) MaxAligned; + assert(x != nullptr); + assert(new_called == 0); + + delete x; + assert(delete_called == 0); + } + + // Test with a type that is clearly not overaligned + { + new_called = delete_called = 0; + int* x = new (std::nothrow) int; + assert(x != nullptr); + assert(new_called == 0); + + delete x; + assert(delete_called == 0); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new(std::size_t, std::align_val_t, std::nothrow_t const&); + +// Test that we can replace the operator by defining our own. + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: sanitizer-new-delete + +// XFAIL: LIBCXX-AIX-FIXME + +// We get availability markup errors when aligned allocation is missing +// XFAIL: availability-aligned_allocation-missing + +// Libc++ when built for z/OS doesn't contain the aligned allocation functions, +// nor does the dynamic library shipped with z/OS. +// UNSUPPORTED: target={{.+}}-zos{{.*}} + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_nothrow_called = 0; +int delete_called = 0; + +alignas(OverAligned) char DummyData[alignof(OverAligned)]; + +void* operator new(std::size_t s, std::align_val_t a, std::nothrow_t const&) TEST_NOEXCEPT { + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == alignof(OverAligned)); + ++new_nothrow_called; + return DummyData; +} + +void operator delete(void*, std::align_val_t) TEST_NOEXCEPT { + ++delete_called; + // nothing to delete, we didn't actually allocate in `operator new` +} + +int main(int, char**) { + // Test with an overaligned type + { + new_nothrow_called = delete_called = 0; + OverAligned* x = new (std::nothrow) OverAligned; + assert(static_cast(x) == DummyData); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1); + + delete x; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + } + + // Test with a type that is right on the verge of being overaligned + { + new_nothrow_called = delete_called = 0; + MaxAligned* x = new (std::nothrow) MaxAligned; + assert(x != nullptr); + assert(new_nothrow_called == 0); + + delete x; + assert(delete_called == 0); + } + + // Test with a type that is clearly not overaligned + { + new_nothrow_called = delete_called = 0; + int* x = new (std::nothrow) int; + assert(x != nullptr); + assert(new_nothrow_called == 0); + + delete x; + assert(delete_called == 0); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_nothrow.verify.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.nodiscard.verify.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_nothrow.verify.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.nodiscard.verify.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_size_nothrow.verify.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.nodiscard.verify.cpp @@ -6,9 +6,7 @@ // //===----------------------------------------------------------------------===// -// - -// void* operator new(std::size_t, std::nothrow_t &); +// [[nodiscard]] void* operator new(std::size_t, std::nothrow_t const&); // UNSUPPORTED: c++03, c++11, c++14, c++17 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new(std::size_t, std::nothrow_t const&); + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +int new_handler_called = 0; + +void my_new_handler() { + ++new_handler_called; + std::set_new_handler(0); +} + +int main(int, char**) { + // Test that the new handler is called and we return nullptr if allocation fails + { + std::set_new_handler(my_new_handler); + void* x = operator new(std::numeric_limits::max(), std::nothrow); + assert(new_handler_called == 1); + assert(x == nullptr); + } + + // Test that a new expression constructs the right object + // and a delete expression deletes it + { + LifetimeInformation info; + TrackLifetime* x = new (std::nothrow) TrackLifetime(info); + assert(x != nullptr); + assert(info.address_constructed == x); + + delete x; + assert(info.address_destroyed == x); + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp rename from libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp rename to libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// -// test operator new nothrow by replacing only operator new +// void* operator new(std::size_t, std::nothrow_t const&); + +// Test that we can replace the operator by replacing `operator new(std::size_t)` (the throwing version). // UNSUPPORTED: sanitizer-new-delete // XFAIL: libcpp-no-vcruntime @@ -16,46 +18,33 @@ #include #include #include -#include #include "test_macros.h" int new_called = 0; +int delete_called = 0; -void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) -{ +TEST_WORKAROUND_BUG_109234844_WEAK +void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) { ++new_called; void* ret = std::malloc(s); if (!ret) std::abort(); // placate MSVC's unchecked malloc warning return ret; } -void operator delete(void* p) TEST_NOEXCEPT -{ - --new_called; +void operator delete(void* p) TEST_NOEXCEPT { + ++delete_called; std::free(p); } -bool A_constructed = false; - -struct A -{ - A() {A_constructed = true;} - ~A() {A_constructed = false;} -}; - -int main(int, char**) -{ - new_called = 0; - A *ap = new (std::nothrow) A; - DoNotOptimize(ap); - assert(ap); - assert(A_constructed); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called); - delete ap; - DoNotOptimize(ap); - assert(!A_constructed); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called); - - return 0; +int main(int, char**) { + new_called = delete_called = 0; + int* x = new (std::nothrow) int(3); + assert(x != nullptr); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1); + + delete x; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + + return 0; } diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// void* operator new(std::size_t, std::nothrow_t const&); + +// Test that we can replace the operator by defining our own. + +// UNSUPPORTED: sanitizer-new-delete +// XFAIL: libcpp-no-vcruntime +// XFAIL: LIBCXX-AIX-FIXME + +#include +#include +#include +#include + +#include "test_macros.h" + +int new_nothrow_called = 0; +int delete_called = 0; + +void* operator new(std::size_t s, std::nothrow_t const&) TEST_NOEXCEPT { + ++new_nothrow_called; + return std::malloc(s); +} + +void operator delete(void* p) TEST_NOEXCEPT { + ++delete_called; + std::free(p); +} + +int main(int, char**) { + new_nothrow_called = delete_called = 0; + int* x = new (std::nothrow) int(3); + assert(x != nullptr); + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1); + + assert(delete_called == 0); + delete x; + ASSERT_WITH_OPERATOR_NEW_FALLBACKS(delete_called == 1); + + return 0; +} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp +++ /dev/null @@ -1,85 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14 - -// We get availability markup errors when aligned allocation is missing -// XFAIL: availability-aligned_allocation-missing - -// asan and msan will not call the new handler. -// UNSUPPORTED: sanitizer-new-delete - -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, -// nor does the dynamic library shipped with z/OS. -// UNSUPPORTED: target={{.+}}-zos{{.*}} - -// test operator new - -#include -#include -#include -#include -#include - -#include "test_macros.h" - -constexpr auto OverAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; - -int new_handler_called = 0; - -void my_new_handler() -{ - ++new_handler_called; - std::set_new_handler(0); -} - -bool A_constructed = false; - -struct alignas(OverAligned) A -{ - A() {A_constructed = true;} - ~A() {A_constructed = false;} -}; - -void test_throw_max_size() { -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_new_handler(my_new_handler); - try - { - void* vp = operator new (std::numeric_limits::max(), - static_cast(32)); - ((void)vp); - assert(false); - } - catch (std::bad_alloc&) - { - assert(new_handler_called == 1); - } - catch (...) - { - assert(false); - } -#endif -} - -int main(int, char**) -{ - { - A* ap = new A; - assert(ap); - assert(reinterpret_cast(ap) % OverAligned == 0); - assert(A_constructed); - delete ap; - assert(!A_constructed); - } - { - test_throw_max_size(); - } - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp +++ /dev/null @@ -1,87 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14 - -// We get availability markup errors when aligned allocation is missing -// XFAIL: availability-aligned_allocation-missing - -// asan and msan will not call the new handler. -// UNSUPPORTED: sanitizer-new-delete - -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, -// nor does the dynamic library shipped with z/OS. -// UNSUPPORTED: target={{.+}}-zos{{.*}} - -// test operator new (nothrow) - -#include -#include -#include -#include -#include - -#include "test_macros.h" - -constexpr auto OverAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; - -int new_handler_called = 0; - -void my_new_handler() -{ - ++new_handler_called; - std::set_new_handler(0); -} - -bool A_constructed = false; - -struct alignas(OverAligned) A -{ - A() {A_constructed = true;} - ~A() {A_constructed = false;} -}; - -void test_max_alloc() { - std::set_new_handler(my_new_handler); - auto do_test = []() { - void* vp = operator new (std::numeric_limits::max(), - std::align_val_t(OverAligned), - std::nothrow); - assert(new_handler_called == 1); - assert(vp == 0); - }; -#ifndef TEST_HAS_NO_EXCEPTIONS - try - { - do_test(); - } - catch (...) - { - assert(false); - } -#else - do_test(); -#endif -} - -int main(int, char**) -{ - { - A* ap = new(std::nothrow) A; - assert(ap); - assert(reinterpret_cast(ap) % OverAligned == 0); - assert(A_constructed); - delete ap; - assert(!A_constructed); - } - { - test_max_alloc(); - } - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp +++ /dev/null @@ -1,92 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14 -// UNSUPPORTED: sanitizer-new-delete - -// XFAIL: LIBCXX-AIX-FIXME - -// We get availability markup errors when aligned allocation is missing -// XFAIL: availability-aligned_allocation-missing - -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, -// nor does the dynamic library shipped with z/OS. -// UNSUPPORTED: target={{.+}}-zos{{.*}} - -// test operator new nothrow by replacing only operator new - -#include -#include -#include -#include -#include - -#include "test_macros.h" - -constexpr auto OverAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; - -bool A_constructed = false; - -struct alignas(OverAligned) A -{ - A() {A_constructed = true;} - ~A() {A_constructed = false;} -}; - -bool B_constructed = false; - -struct B { - std::max_align_t member; - B() { B_constructed = true; } - ~B() { B_constructed = false; } -}; - -int new_called = 0; -alignas(OverAligned) char Buff[OverAligned * 2]; - -void* operator new(std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) -{ - assert(!new_called); - assert(s <= sizeof(Buff)); - assert(static_cast(a) == OverAligned); - ++new_called; - return Buff; -} - -void operator delete(void* p, std::align_val_t a) TEST_NOEXCEPT -{ - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(p == Buff); - assert(static_cast(a) == OverAligned); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called); - --new_called; -} - - -int main(int, char**) -{ - { - A* ap = new (std::nothrow) A; - assert(ap); - assert(A_constructed); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called); - delete ap; - assert(!A_constructed); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called); - } - { - B* bp = new (std::nothrow) B; - assert(bp); - assert(B_constructed); - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called); - delete bp; - ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called); - assert(!B_constructed); - } - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_replace.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_replace.pass.cpp +++ /dev/null @@ -1,91 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14 -// UNSUPPORTED: sanitizer-new-delete - -// Libcxx when built for z/OS doesn't contain the aligned allocation functions, -// nor does the dynamic library shipped with z/OS. -// UNSUPPORTED: target={{.+}}-zos{{.*}} - -// test operator new replacement - -#include -#include -#include -#include -#include -#include - -#include "test_macros.h" - -constexpr auto OverAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; - -bool A_constructed = false; - -struct alignas(OverAligned) A { - A() {A_constructed = true;} - ~A() {A_constructed = false;} -}; - - -bool B_constructed = false; - -struct alignas(std::max_align_t) B -{ - std::max_align_t member; - B() {B_constructed = true;} - ~B() {B_constructed = false;} -}; - -int new_called = 0; - -alignas(OverAligned) char DummyData[OverAligned]; - -void* operator new(std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_alloc) -{ - assert(new_called == 0); // We already allocated - assert(s <= sizeof(DummyData)); - assert(static_cast(a) == OverAligned); - ++new_called; - void *Ret = DummyData; - DoNotOptimize(Ret); - return Ret; -} - -void operator delete(void* p, std::align_val_t) TEST_NOEXCEPT -{ - assert(new_called == 1); - --new_called; - assert(p == DummyData); - DoNotOptimize(DummyData); -} - - -int main(int, char**) -{ - { - A* ap = new A; - assert(ap); - assert(A_constructed); - assert(new_called); - delete ap; - assert(!A_constructed); - assert(!new_called); - } - { - B* bp = new B; - assert(bp); - assert(B_constructed); - assert(!new_called); - delete bp; - assert(!new_called); - } - - return 0; -} diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow.pass.cpp deleted file mode 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow.pass.cpp +++ /dev/null @@ -1,61 +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 operator new (nothrow) - -// asan and msan will not call the new handler. -// UNSUPPORTED: sanitizer-new-delete - -#include -#include -#include -#include - -#include "test_macros.h" - -int new_handler_called = 0; - -void my_new_handler() -{ - ++new_handler_called; - std::set_new_handler(0); -} - -bool A_constructed = false; - -struct A -{ - A() {A_constructed = true;} - ~A() {A_constructed = false;} -}; - -int main(int, char**) -{ - std::set_new_handler(my_new_handler); -#ifndef TEST_HAS_NO_EXCEPTIONS - try -#endif - { - void* vp = operator new (std::numeric_limits::max(), std::nothrow); - assert(new_handler_called == 1); - assert(vp == 0); - } -#ifndef TEST_HAS_NO_EXCEPTIONS - catch (...) - { - assert(false); - } -#endif - A* ap = new(std::nothrow) A; - assert(ap); - assert(A_constructed); - delete ap; - assert(!A_constructed); - - 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 new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/types.h @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_LANGUAGE_SUPPORT_SUPPORT_DYNAMIC_NEW_DELETE_TYPES_H +#define TEST_STD_LANGUAGE_SUPPORT_SUPPORT_DYNAMIC_NEW_DELETE_TYPES_H + +#include + +struct LifetimeInformation { + void* address_constructed = nullptr; + void* address_destroyed = nullptr; +}; + +struct TrackLifetime { + TrackLifetime(LifetimeInformation& info) : info_(&info) { + info_->address_constructed = this; + } + ~TrackLifetime() { + info_->address_destroyed = this; + } + LifetimeInformation* info_; +}; + +struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) TrackLifetimeOverAligned { + TrackLifetimeOverAligned(LifetimeInformation& info) : info_(&info) { + info_->address_constructed = this; + } + ~TrackLifetimeOverAligned() { + info_->address_destroyed = this; + } + LifetimeInformation* info_; +}; + +struct alignas(std::max_align_t) TrackLifetimeMaxAligned { + TrackLifetimeMaxAligned(LifetimeInformation& info) : info_(&info) { + info_->address_constructed = this; + } + ~TrackLifetimeMaxAligned() { + info_->address_destroyed = this; + } + LifetimeInformation* info_; +}; + +struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) OverAligned { + +}; + +struct alignas(std::max_align_t) MaxAligned { + +}; + +#endif // TEST_STD_LANGUAGE_SUPPORT_SUPPORT_DYNAMIC_NEW_DELETE_TYPES_H diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -438,4 +438,13 @@ # define TEST_SHORT_WCHAR #endif +// This is a temporary workaround for user-defined `operator new` definitions +// not being picked up on Apple platforms in some circumstances. This is under +// investigation and should be short-lived. +#ifdef __APPLE__ +# define TEST_WORKAROUND_BUG_109234844_WEAK __attribute__((weak)) +#else +# define TEST_WORKAROUND_BUG_109234844_WEAK /* nothing */ +#endif + #endif // SUPPORT_TEST_MACROS_HPP