[libcxx-commits] [libcxx] 128b213 - [libcxx] [test] Generalize defines for skipping allocation checks
Martin Storsjö via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Aug 10 01:06:58 PDT 2021
Author: Martin Storsjö
Date: 2021-08-10T11:05:00+03:00
New Revision: 128b2136ec62ccfaac8f2b02e87d14f191a154ca
URL: https://github.com/llvm/llvm-project/commit/128b2136ec62ccfaac8f2b02e87d14f191a154ca
DIFF: https://github.com/llvm/llvm-project/commit/128b2136ec62ccfaac8f2b02e87d14f191a154ca.diff
LOG: [libcxx] [test] Generalize defines for skipping allocation checks
This allows waiving the right amount of asserts on Windows and zOS.
This should supersede D107124 and D105910.
Differential Revision: https://reviews.llvm.org/D107755
Added:
Modified:
libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp
libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp
libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp
libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp
libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp
libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp
libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp
libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
libcxx/test/support/test_macros.h
Removed:
################################################################################
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp
index d9701a321bcf4..5157161bae872 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp
@@ -194,22 +194,23 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC)
// For "char" no allocations will be performed because no conversion is
// required.
// On Windows, the append method is more complex and uses intermediate
- // path objects, which causes extra allocations.
- // In DLL builds on Windows, the overridden operator new won't pick up
- // allocations done within the DLL, so the RequireAllocationGuard below
- // won't necessarily see allocations in the cases where they're expected.
-#ifdef _WIN32
- bool DisableAllocations = false;
-#else
- bool DisableAllocations = std::is_same<CharT, char>::value;
+ // path objects, which causes extra allocations. This is checked by comparing
+ // path::value_type with "char" - on Windows, it's wchar_t.
+#if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
+ // Only check allocations if we can pick up allocations done within the
+ // library implementation.
+ bool ExpectNoAllocations = std::is_same<CharT, char>::value &&
+ std::is_same<path::value_type, char>::value;
#endif
{
path LHS(L); PathReserve(LHS, ReserveSize);
InputIter RHS(R);
{
- RequireAllocationGuard g; // requires 1 or more allocations occur by default
- if (DisableAllocations) g.requireExactly(0);
- else TEST_ONLY_WIN32_DLL(g.requireAtLeast(0));
+ RequireAllocationGuard g(0); // require "at least zero" allocations by default
+#if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
+ if (ExpectNoAllocations)
+ g.requireExactly(0);
+#endif
LHS /= RHS;
}
assert(PathEq(LHS, E));
@@ -219,9 +220,11 @@ void doAppendSourceAllocTest(AppendOperatorTestcase const& TC)
InputIter RHS(R);
InputIter REnd(StrEnd(R));
{
- RequireAllocationGuard g;
- if (DisableAllocations) g.requireExactly(0);
- else TEST_ONLY_WIN32_DLL(g.requireAtLeast(0));
+ RequireAllocationGuard g(0); // require "at least zero" allocations by default
+#if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
+ if (ExpectNoAllocations)
+ g.requireExactly(0);
+#endif
LHS.append(RHS, REnd);
}
assert(PathEq(LHS, E));
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
index c13469fd30d17..cb25c66bf5120 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
@@ -28,9 +28,8 @@ int main(int, char**) {
assert(globalMemCounter.checkOutstandingNewEq(0));
const std::string s("we really really really really really really really "
"really really long string so that we allocate");
- // On windows, the operator new from count_new.h can't override the default
- // operator for calls within the libc++ DLL.
- TEST_NOT_WIN32_DLL(assert(globalMemCounter.checkOutstandingNewEq(1)));
+ ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
+ globalMemCounter.checkOutstandingNewEq(1));
const fs::path::string_type ps(s.begin(), s.end());
path p(s);
{
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp
index 221c4c464e6ce..6212e1d706338 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp
@@ -141,17 +141,20 @@ void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC)
// For the path native type, no allocations will be performed because no
// conversion is required.
- // In DLL builds on Windows, the overridden operator new won't pick up
- // allocations done within the DLL, so the RequireAllocationGuard below
- // won't necessarily see allocations in the cases where they're expected.
- bool DisableAllocations = std::is_same<CharT, path::value_type>::value;
+#if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
+ // Only check allocations if we can pick up allocations done within the
+ // library implementation.
+ bool ExpectNoAllocations = std::is_same<CharT, path::value_type>::value;
+#endif
{
path LHS(L); PathReserve(LHS, ReserveSize);
InputIter RHS(R);
{
- RequireAllocationGuard g; // requires 1 or more allocations occur by default
- if (DisableAllocations) g.requireExactly(0);
- else TEST_ONLY_WIN32_DLL(g.requireAtLeast(0));
+ RequireAllocationGuard g(0); // require "at least zero" allocations by default
+#if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
+ if (ExpectNoAllocations)
+ g.requireExactly(0);
+#endif
LHS += RHS;
}
assert(LHS == E);
@@ -161,9 +164,11 @@ void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC)
InputIter RHS(R);
InputIter REnd(StrEnd(R));
{
- RequireAllocationGuard g;
- if (DisableAllocations) g.requireExactly(0);
- else TEST_ONLY_WIN32_DLL(g.requireAtLeast(0));
+ RequireAllocationGuard g(0); // require "at least zero" allocations by default
+#if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS
+ if (ExpectNoAllocations)
+ g.requireExactly(0);
+#endif
LHS.concat(RHS, REnd);
}
assert(LHS == E);
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
index f0d324b2f8601..cdf39e33d3fd1 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
@@ -28,9 +28,8 @@ int main(int, char**) {
assert(globalMemCounter.checkOutstandingNewEq(0));
const std::string s("we really really really really really really really "
"really really long string so that we allocate");
- // On windows, the operator new from count_new.h can't override the default
- // operator for calls within the libc++ DLL.
- TEST_NOT_WIN32_DLL(assert(globalMemCounter.checkOutstandingNewEq(1)));
+ ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
+ globalMemCounter.checkOutstandingNewEq(1));
const fs::path::string_type ps(s.begin(), s.end());
path p(s);
{
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
index 038b0e7b7ae0b..ee2f932761f1d 100644
--- 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
@@ -62,9 +62,9 @@ void* operator new[](std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad
void operator delete[](void* p, std::align_val_t a) TEST_NOEXCEPT
{
- assert(p == Buff);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(p == Buff);
assert(static_cast<std::size_t>(a) == OverAligned);
- assert(new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called);
--new_called;
}
@@ -74,18 +74,18 @@ int main(int, char**)
A* ap = new (std::nothrow) A[2];
assert(ap);
assert(A_constructed == 2);
- assert(new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called);
delete [] ap;
assert(A_constructed == 0);
- assert(!new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called);
}
{
B* bp = new (std::nothrow) B[2];
assert(bp);
assert(B_constructed == 2);
- assert(!new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called);
delete [] bp;
- assert(!new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called);
assert(!B_constructed);
}
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_array_nothrow_replace.pass.cpp
index 90785d8dc24d8..dcfc603f5da94 100644
--- 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_array_nothrow_replace.pass.cpp
@@ -50,11 +50,11 @@ int main(int, char**)
DoNotOptimize(ap);
assert(ap);
assert(A_constructed == 3);
- assert(new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called);
delete [] ap;
DoNotOptimize(ap);
assert(A_constructed == 0);
- assert(!new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called);
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_array_replace.pass.cpp
index 9058171bbdc3a..384c97beca9b9 100644
--- 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_array_replace.pass.cpp
@@ -51,11 +51,11 @@ int main(int, char**)
DoNotOptimize(ap);
assert(ap);
assert(A_constructed == 3);
- assert(new_called == 1);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
delete [] ap;
DoNotOptimize(ap);
assert(A_constructed == 0);
- assert(new_called == 0);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 0);
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
index 7df5663a1c73e..8057e2974987d 100644
--- 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
@@ -62,9 +62,9 @@ void* operator new(std::size_t s, std::align_val_t a) TEST_THROW_SPEC(std::bad_a
void operator delete(void* p, std::align_val_t a) TEST_NOEXCEPT
{
- assert(p == Buff);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(p == Buff);
assert(static_cast<std::size_t>(a) == OverAligned);
- assert(new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called);
--new_called;
}
@@ -75,18 +75,18 @@ int main(int, char**)
A* ap = new (std::nothrow) A;
assert(ap);
assert(A_constructed);
- assert(new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called);
delete ap;
assert(!A_constructed);
- assert(!new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called);
}
{
B* bp = new (std::nothrow) B;
assert(bp);
assert(B_constructed);
- assert(!new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called);
delete bp;
- assert(!new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called);
assert(!B_constructed);
}
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_nothrow_replace.pass.cpp
index cf6e5f4586005..4182788d43b88 100644
--- 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_nothrow_replace.pass.cpp
@@ -50,11 +50,11 @@ int main(int, char**)
DoNotOptimize(ap);
assert(ap);
assert(A_constructed);
- assert(new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called);
delete ap;
DoNotOptimize(ap);
assert(!A_constructed);
- assert(!new_called);
+ ASSERT_WITH_OPERATOR_NEW_FALLBACKS(!new_called);
return 0;
}
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp
index 0533bb8c20b32..7be7e8d574e6c 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp
@@ -37,9 +37,8 @@ int main(int, char**)
new std::ctype<char>(new std::ctype<char>::mask[256], true));
assert(globalMemCounter.checkDeleteArrayCalledEq(0));
}
- // On windows, the operator new from count_new.h can't override the default
- // operator for calls within the libc++ DLL.
- TEST_NOT_WIN32_DLL(assert(globalMemCounter.checkDeleteArrayCalledEq(1)));
+ ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
+ globalMemCounter.checkDeleteArrayCalledEq(1));
return 0;
}
diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
index 6dfe1ceffb19c..b5f38478ca70c 100644
--- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
+++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
@@ -136,7 +136,7 @@ void test_throwing_new_during_thread_creation() {
for (int i=0; i <= numAllocs; ++i) {
throw_one = i;
f_run = false;
- TEST_NOT_WIN32_DLL(unsigned old_outstanding = outstanding_new);
+ unsigned old_outstanding = outstanding_new;
try {
std::thread t(f);
assert(i == numAllocs); // Only final iteration will not throw.
@@ -146,9 +146,7 @@ void test_throwing_new_during_thread_creation() {
assert(i < numAllocs);
assert(!f_run); // (2.2)
}
- // In DLL builds on Windows, the overridden operators new/delete won't
- // override calls from within the DLL, so this won't match.
- TEST_NOT_WIN32_DLL(assert(old_outstanding == outstanding_new)); // (2.3)
+ ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(old_outstanding == outstanding_new); // (2.3)
}
f_run = false;
throw_one = 0xFFF;
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index 96c6965ec65d4..cdff591cab548 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -381,12 +381,43 @@ inline void DoNotOptimize(Tp const& value) {
#define TEST_NOT_WIN32(...) __VA_ARGS__
#endif
-#if defined(_WIN32) && !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
-#define TEST_NOT_WIN32_DLL(...) ((void)0)
-#define TEST_ONLY_WIN32_DLL(...) __VA_ARGS__
+#if (defined(_WIN32) && !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)) || \
+ defined(__MVS__)
+// Macros for waiving cases when we can't count allocations done within
+// the library implementation.
+//
+// On Windows, when libc++ is built as a DLL, references to operator new/delete
+// within the DLL are bound at link time to the operator new/delete within
+// the library; replacing them in the user executable doesn't override the
+// calls within the library.
+//
+// The same goes on IBM zOS.
+#define ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(...) ((void)(__VA_ARGS__))
+#define TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS 0
+#else
+#define ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(...) assert(__VA_ARGS__)
+#define TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS 1
+#endif
+
+#if (defined(_WIN32) && !defined(_MSC_VER) && \
+ !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)) || \
+ defined(__MVS__)
+// Normally, a replaced e.g. 'operator new' ends up used if the user code
+// does a call to e.g. 'operator new[]'; it's enough to replace the base
+// versions and have it override all of them.
+//
+// When the fallback operators are located within the libc++ library and we
+// can't override the calls within it (see above), this fallback mechanism
+// doesn't work either.
+//
+// On Windows, when using the MSVC vcruntime, the operator new/delete fallbacks
+// are linked separately from the libc++ library, linked statically into
+// the end user executable, and these fallbacks work even in DLL configurations.
+// In MinGW configurations when built as a DLL, and on zOS, these fallbacks
+// don't work though.
+#define ASSERT_WITH_OPERATOR_NEW_FALLBACKS(...) ((void)(__VA_ARGS__))
#else
-#define TEST_NOT_WIN32_DLL(...) __VA_ARGS__
-#define TEST_ONLY_WIN32_DLL(...) ((void)0)
+#define ASSERT_WITH_OPERATOR_NEW_FALLBACKS(...) assert(__VA_ARGS__)
#endif
#ifdef _WIN32
More information about the libcxx-commits
mailing list