[libcxx-commits] [libcxx] [libcxx] Improve handling of DummyData blocks in libcxx tests (PR #88897)

Jack Styles via libcxx-commits libcxx-commits at lists.llvm.org
Tue Apr 16 07:05:36 PDT 2024


https://github.com/Stylie777 created https://github.com/llvm/llvm-project/pull/88897

Within the libcxx tests, some tests compare a pointer to a Global Variable to one that is stored locally. This can cause issues where, both are the same value, but the assert is failing as the compiler cannot properly compare them. 

This changes how these variables are defined to specific tests to ensure the asserts pass. No change to the tests functionality is included.

>From 07273bbbc8af07260cc1757160fd8dd9cee42311 Mon Sep 17 00:00:00 2001
From: Jack Styles <jack.styles at arm.com>
Date: Tue, 16 Apr 2024 11:55:54 +0100
Subject: [PATCH 1/2] [libcxx] Update libcxx tests to better utilise
 `DoNotOptimize`

As part of the libcxx tests, there is a function provided called `DoNotOptimize`.
The tests currently utilise a version which only uses the value as an input,
leading to the compiler not removing information relating to the data-flow for
the value. This led to issues when comparing the pointer values, where one is a
global pointer and the other a pointer which is local to the function being
executed.

Another version of `DoNotOptimize` is available which allows for the value
to be an input and output of the inline assembley, which allows for the
pointers to be successfully compared to one another. To utilize this function
the `new` operator should be called beforehand, the pointer stored in its own
variable and then this passed to the `DoNotOptimize` variable.
---
 .../new.delete.array/new.size_align.replace.indirect.pass.cpp  | 3 ++-
 .../new.size_align_nothrow.replace.indirect.pass.cpp           | 3 ++-
 .../new.size_align_nothrow.replace.indirect.pass.cpp           | 3 ++-
 3 files changed, 6 insertions(+), 3 deletions(-)

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
index 0b540e09bab3cc..1ccf5501bcea33 100644
--- 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
@@ -51,7 +51,8 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = DoNotOptimize(new OverAligned[3]);
+        OverAligned* dummy_data_block = new (std::nothrow) OverAligned;
+        OverAligned* x = DoNotOptimize(dummy_data_block);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
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
index 227b20f0b1e18b..6c12a9b65f129a 100644
--- 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
@@ -55,7 +55,8 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = DoNotOptimize(new (std::nothrow) OverAligned[3]);
+        OverAligned* dummy_data_block = new (std::nothrow) OverAligned[3];
+        OverAligned* x = DoNotOptimize(dummy_data_block);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
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
index 7eab0729f9ef1a..df0c454ecd3e17 100644
--- 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
@@ -54,7 +54,8 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = DoNotOptimize(new (std::nothrow) OverAligned);
+        OverAligned* dummy_data_block = new (std::nothrow) OverAligned;
+        OverAligned* x = DoNotOptimize(dummy_data_block);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 

>From e32c5912ca34bccc43dfaaafddd827078adffb01 Mon Sep 17 00:00:00 2001
From: Jack Styles <jack.styles at arm.com>
Date: Tue, 16 Apr 2024 11:56:41 +0100
Subject: [PATCH 2/2] [libcxx] Better define the DummyData for tests

The tests utilise a DummyData block to assign a block of memory rather than
calling `malloc` and `free` as part of `new` and `delete` operations. However,
this is defined as a global variable which causes issues when comparing the
memory address to the locally stored variable within the test.

To get around this, the DummyData block is now part of a class, which
is defined globally. This is then used to compare the pointers and ensure
the operations are working correctly.
---
 .../new.size_align.replace.pass.cpp           | 25 +++++++++++++++----
 .../new.size_align.replace.pass.cpp           | 25 +++++++++++++++----
 .../new.size_align_nothrow.replace.pass.cpp   | 25 +++++++++++++++----
 3 files changed, 60 insertions(+), 15 deletions(-)

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
index 2d021ecb30e793..bdfed1bd8aae18 100644
--- 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
@@ -27,16 +27,31 @@
 #include "test_macros.h"
 #include "../types.h"
 
+class Data{
+public:
+    Data() = default;
+    ~Data() = default;
+
+    char *getDummyData() {
+        return this->dummy_data_;
+    }
+
+    std::size_t getDummyDataSize() {
+        return sizeof(this->dummy_data_);
+    }
+private:
+    alignas(OverAligned) char dummy_data_[alignof(OverAligned) * 3];
+};
+
 int new_called = 0;
 int delete_called = 0;
-
-alignas(OverAligned) char DummyData[alignof(OverAligned) * 3];
+Data data_class;
 
 void* operator new[](std::size_t s, std::align_val_t a) {
-    assert(s <= sizeof(DummyData));
+    assert(s <= data_class.getDummyDataSize());
     assert(static_cast<std::size_t>(a) == alignof(OverAligned));
     ++new_called;
-    return DummyData;
+    return data_class.getDummyData();
 }
 
 void operator delete[](void*, std::align_val_t) noexcept {
@@ -49,7 +64,7 @@ int main(int, char**) {
     {
         new_called = delete_called = 0;
         OverAligned* x = new OverAligned[3];
-        assert(static_cast<void*>(x) == DummyData);
+        assert(static_cast<void*>(x) == data_class.getDummyData());
         assert(new_called == 1);
 
         delete[] x;
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
index e5ef5f1669752b..254b864a74341f 100644
--- 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
@@ -27,16 +27,31 @@
 #include "test_macros.h"
 #include "../types.h"
 
+class Data{
+public:
+    Data() = default;
+    ~Data() = default;
+
+    char *getDummyData() {
+        return this->dummy_data_;
+    }
+
+    std::size_t getDummyDataSize() {
+        return sizeof(this->dummy_data_);
+    }
+private:
+    alignas(OverAligned) char dummy_data_[alignof(OverAligned)];
+};
+
 int new_called = 0;
 int delete_called = 0;
-
-alignas(OverAligned) char DummyData[alignof(OverAligned)];
+Data data_class;
 
 void* operator new(std::size_t s, std::align_val_t a) {
-    assert(s <= sizeof(DummyData));
+    assert(s <= data_class.getDummyDataSize());
     assert(static_cast<std::size_t>(a) == alignof(OverAligned));
     ++new_called;
-    return DummyData;
+    return data_class.getDummyData();
 }
 
 void operator delete(void*, std::align_val_t) noexcept {
@@ -49,7 +64,7 @@ int main(int, char**) {
     {
         new_called = delete_called = 0;
         OverAligned* x = new OverAligned;
-        assert(static_cast<void*>(x) == DummyData);
+        assert(static_cast<void*>(x) == data_class.getDummyData());
         assert(new_called == 1);
 
         delete x;
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
index 9a5b53e039025c..5e7f2523de4b10 100644
--- 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
@@ -26,16 +26,31 @@
 #include "test_macros.h"
 #include "../types.h"
 
+class Data{
+public:
+    Data() = default;
+    ~Data() = default;
+
+    char *getDummyData() {
+        return this->dummy_data_;
+    }
+
+    std::size_t getDummyDataSize() {
+        return sizeof(this->dummy_data_);
+    }
+private:
+    alignas(OverAligned) char dummy_data_[alignof(OverAligned)];
+};
+
 int new_nothrow_called = 0;
 int delete_called = 0;
-
-alignas(OverAligned) char DummyData[alignof(OverAligned)];
+Data data_class;
 
 void* operator new(std::size_t s, std::align_val_t a, std::nothrow_t const&) noexcept {
-    assert(s <= sizeof(DummyData));
+    assert(s <= data_class.getDummyDataSize());
     assert(static_cast<std::size_t>(a) == alignof(OverAligned));
     ++new_nothrow_called;
-    return DummyData;
+    return data_class.getDummyData();
 }
 
 void operator delete(void*, std::align_val_t) noexcept {
@@ -48,7 +63,7 @@ int main(int, char**) {
     {
         new_nothrow_called = delete_called = 0;
         OverAligned* x = new (std::nothrow) OverAligned;
-        assert(static_cast<void*>(x) == DummyData);
+        assert(static_cast<void*>(x) == data_class.getDummyData());
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
 
         delete x;



More information about the libcxx-commits mailing list