[libcxx-commits] [llvm] [clang-tools-extra] [libunwind] [clang] [libcxx] [libc++] Allow running the test suite with optimizations (PR #68753)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Nov 16 13:07:30 PST 2023
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/68753
>From 9824ef111975386152173916c1fd6a85264be0a0 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 10 Oct 2023 16:35:11 -0700
Subject: [PATCH 1/9] [libc++] Allow running the test suite with optimizations
This patch adds a configuration of the libc++ test suite that enables
optimizations when building the tests. It also adds a new CI configuration
to exercise this on a regular basis. This is added in the context of [1],
which requires building with optimizations in order to hit the bug.
[1]: https://github.com/llvm/llvm-project/issues/68552
---
libcxx/cmake/caches/Generic-optimized.cmake | 4 +++
libcxx/utils/ci/buildkite-pipeline.yml | 18 +++++++++++++
libcxx/utils/ci/run-buildbot | 5 ++++
libcxx/utils/libcxx/test/params.py | 28 ++++++++++++++++++++-
4 files changed, 54 insertions(+), 1 deletion(-)
create mode 100644 libcxx/cmake/caches/Generic-optimized.cmake
diff --git a/libcxx/cmake/caches/Generic-optimized.cmake b/libcxx/cmake/caches/Generic-optimized.cmake
new file mode 100644
index 000000000000000..577a5de9f34c539
--- /dev/null
+++ b/libcxx/cmake/caches/Generic-optimized.cmake
@@ -0,0 +1,4 @@
+set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
+set(LIBCXX_TEST_PARAMS "optimization=speed" CACHE STRING "")
+set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
+set(LIBUNWIND_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml
index ebfb35eee91e1ed..1b52d994081c46f 100644
--- a/libcxx/utils/ci/buildkite-pipeline.yml
+++ b/libcxx/utils/ci/buildkite-pipeline.yml
@@ -743,6 +743,24 @@ steps:
limit: 2
timeout_in_minutes: 120
+ - label: "Optimized build and test suite"
+ command: "libcxx/utils/ci/run-buildbot generic-optimized"
+ artifact_paths:
+ - "**/test-results.xml"
+ - "**/*.abilist"
+ env:
+ CC: "clang-${LLVM_HEAD_VERSION}"
+ CXX: "clang++-${LLVM_HEAD_VERSION}"
+ ENABLE_CLANG_TIDY: "On"
+ agents:
+ queue: "libcxx-builders"
+ os: "linux"
+ retry:
+ automatic:
+ - exit_status: -1 # Agent was lost
+ limit: 2
+ timeout_in_minutes: 120
+
# Other non-testing CI jobs
- label: "Benchmarks"
command: "libcxx/utils/ci/run-buildbot benchmarks"
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index a71318123db3b12..18243b44a3d745c 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -479,6 +479,11 @@ generic-abi-unstable)
generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-abi-unstable.cmake"
check-runtimes
;;
+generic-optimized)
+ clean
+ generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-optimized.cmake"
+ check-runtimes
+;;
apple-system)
clean
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index 456794b9b1cce95..9452f179aea3fec 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -11,7 +11,7 @@
from pathlib import Path
from libcxx.test.dsl import *
-from libcxx.test.features import _isMSVC
+from libcxx.test.features import _isClang, _isAppleClang, _isGCC, _isMSVC
_warningFlags = [
@@ -90,6 +90,21 @@ def getStdFlag(cfg, std):
return "-std=" + fallbacks[std]
return None
+def getSpeedOptimizationFlag(cfg):
+ if _isClang(cfg) or _isAppleClang(cfg) or _isGCC(cfg):
+ return "-O3"
+ elif _isMSVC(cfg):
+ return "/O2"
+ else:
+ raise RuntimeError("Can't figure out what compiler is used in the configuration")
+
+def getSizeOptimizationFlag(cfg):
+ if _isClang(cfg) or _isAppleClang(cfg) or _isGCC(cfg):
+ return "-Os"
+ elif _isMSVC(cfg):
+ return "/O1"
+ else:
+ raise RuntimeError("Can't figure out what compiler is used in the configuration")
# fmt: off
DEFAULT_PARAMETERS = [
@@ -121,6 +136,17 @@ def getStdFlag(cfg, std):
AddCompileFlag(lambda cfg: getStdFlag(cfg, std)),
],
),
+ Parameter(
+ name="optimization",
+ choices=["none", "speed", "size"],
+ type=str,
+ help="The version of the standard to compile the test suite with.",
+ default="none",
+ actions=lambda opt: filter(None, [
+ AddCompileFlag(lambda cfg: getSpeedOptimizationFlag(cfg)) if opt == "speed" else None,
+ AddCompileFlag(lambda cfg: getSizeOptimizationFlag(cfg)) if opt == "size" else None,
+ ]),
+ ),
Parameter(
name="enable_modules",
choices=["none", "clang", "clang-lsv"],
>From f799be39afed6b82d1942a87cea66a4d1192d765 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 1 Nov 2023 10:56:30 -0400
Subject: [PATCH 2/9] Fix incorrect help
---
libcxx/utils/libcxx/test/params.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index 9452f179aea3fec..9b284265f95c695 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -140,7 +140,7 @@ def getSizeOptimizationFlag(cfg):
name="optimization",
choices=["none", "speed", "size"],
type=str,
- help="The version of the standard to compile the test suite with.",
+ help="The optimization level to use when compiling the test suite.",
default="none",
actions=lambda opt: filter(None, [
AddCompileFlag(lambda cfg: getSpeedOptimizationFlag(cfg)) if opt == "speed" else None,
>From fe134eb76136bbbeea4ece2b67e499a3d4cba45f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 1 Nov 2023 11:21:19 -0400
Subject: [PATCH 3/9] Fix failing tests due to new/delete ellision
---
.../support.dynamic/libcpp_deallocate.sh.cpp | 17 +++++------
.../new.size.replace.indirect.pass.cpp | 3 +-
.../new.size.replace.pass.cpp | 3 +-
.../new.size_align.replace.indirect.pass.cpp | 7 +++--
...ze_align_nothrow.replace.indirect.pass.cpp | 7 +++--
.../new.size_align_nothrow.replace.pass.cpp | 7 +++--
...new.size_nothrow.replace.indirect.pass.cpp | 3 +-
.../new.size_nothrow.replace.pass.cpp | 3 +-
.../new.size.replace.pass.cpp | 3 +-
...ze_align_nothrow.replace.indirect.pass.cpp | 7 +++--
...new.size_nothrow.replace.indirect.pass.cpp | 3 +-
.../func.wrap.func.con/F.pass.cpp | 2 +-
libcxx/test/support/count_new.h | 5 ++++
libcxx/test/support/escape.h | 28 +++++++++++++++++++
14 files changed, 71 insertions(+), 27 deletions(-)
create mode 100644 libcxx/test/support/escape.h
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
index 3b33737466c7419..a2c53861caba036 100644
--- a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
+++ b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
@@ -39,6 +39,7 @@
#include <string>
#include <cassert>
+#include "escape.h"
#include "test_macros.h"
TEST_DIAGNOSTIC_PUSH
@@ -192,13 +193,13 @@ void test_allocator_and_new_match() {
stats.reset();
#if defined(NO_SIZE) && defined(NO_ALIGN)
{
- int* x = new int(42);
+ int* x = support::escape(new int(42));
delete x;
assert(stats.expect_plain());
}
stats.reset();
{
- AlignedType* a = new AlignedType();
+ AlignedType* a = support::escape(new AlignedType());
delete a;
assert(stats.expect_plain());
}
@@ -207,14 +208,14 @@ void test_allocator_and_new_match() {
stats.reset();
#if TEST_STD_VER >= 11
{
- int* x = new int(42);
+ int* x = support::escape(new int(42));
delete x;
assert(stats.expect_plain());
}
#endif
stats.reset();
{
- AlignedType* a = new AlignedType();
+ AlignedType* a = support::escape(new AlignedType());
delete a;
assert(stats.expect_align(TEST_ALIGNOF(AlignedType)));
}
@@ -222,13 +223,13 @@ void test_allocator_and_new_match() {
#elif defined(NO_ALIGN)
stats.reset();
{
- int* x = new int(42);
+ int* x = support::escape(new int(42));
delete x;
assert(stats.expect_size(sizeof(int)));
}
stats.reset();
{
- AlignedType* a = new AlignedType();
+ AlignedType* a = support::escape(new AlignedType());
delete a;
assert(stats.expect_size(sizeof(AlignedType)));
}
@@ -236,13 +237,13 @@ void test_allocator_and_new_match() {
#else
stats.reset();
{
- int* x = new int(42);
+ int* x = support::escape(new int(42));
delete x;
assert(stats.expect_size(sizeof(int)));
}
stats.reset();
{
- AlignedType* a = new AlignedType();
+ AlignedType* a = support::escape(new AlignedType());
delete a;
assert(stats.expect_size_align(sizeof(AlignedType),
TEST_ALIGNOF(AlignedType)));
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
index 172b6cc2f2944ad..56264c25575847e 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
@@ -20,6 +20,7 @@
#include <cassert>
#include <limits>
+#include "escape.h"
#include "test_macros.h"
int new_called = 0;
@@ -40,7 +41,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = new int[3];
+ int* x = support::escape(new int[3]);
assert(x != nullptr);
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.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
index e352c00b4d0af94..1612ecba96ac9b8 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
@@ -19,6 +19,7 @@
#include <cassert>
#include <limits>
+#include "escape.h"
#include "test_macros.h"
int new_called = 0;
@@ -38,7 +39,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = new int[3];
+ int* x = support::escape(new int[3]);
assert(x != nullptr);
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.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 64d987ed691b297..370aba01a2c819d 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
@@ -29,6 +29,7 @@
#include <cassert>
#include <limits>
+#include "escape.h"
#include "test_macros.h"
#include "../types.h"
@@ -54,7 +55,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
- OverAligned* x = new OverAligned[3];
+ OverAligned* x = support::escape(new OverAligned[3]);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
@@ -65,7 +66,7 @@ int main(int, char**) {
// Test with a type that is right on the verge of being overaligned
{
new_called = delete_called = 0;
- MaxAligned* x = new MaxAligned[3];
+ MaxAligned* x = support::escape(new MaxAligned[3]);
assert(x != nullptr);
assert(new_called == 0);
@@ -76,7 +77,7 @@ int main(int, char**) {
// Test with a type that is clearly not overaligned
{
new_called = delete_called = 0;
- int* x = new int[3];
+ int* x = support::escape(new int[3]);
assert(x != nullptr);
assert(new_called == 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
index a62128942eaf638..12b77c4d33c9417 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
@@ -29,6 +29,7 @@
#include <cassert>
#include <limits>
+#include "escape.h"
#include "test_macros.h"
#include "../types.h"
@@ -54,7 +55,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
- OverAligned* x = new (std::nothrow) OverAligned[3];
+ OverAligned* x = support::escape(new (std::nothrow) OverAligned[3]);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
@@ -65,7 +66,7 @@ int main(int, char**) {
// Test with a type that is right on the verge of being overaligned
{
new_called = delete_called = 0;
- MaxAligned* x = new (std::nothrow) MaxAligned[3];
+ MaxAligned* x = support::escape(new (std::nothrow) MaxAligned[3]);
assert(x != nullptr);
assert(new_called == 0);
@@ -76,7 +77,7 @@ int main(int, char**) {
// Test with a type that is clearly not overaligned
{
new_called = delete_called = 0;
- int* x = new (std::nothrow) int[3];
+ int* x = support::escape(new (std::nothrow) int[3]);
assert(x != nullptr);
assert(new_called == 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
index 9a830e0e82990aa..6e4b95a2eea213a 100644
--- 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
@@ -26,6 +26,7 @@
#include <cassert>
#include <limits>
+#include "escape.h"
#include "test_macros.h"
#include "../types.h"
@@ -51,7 +52,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_nothrow_called = delete_called = 0;
- OverAligned* x = new (std::nothrow) OverAligned[3];
+ OverAligned* x = support::escape(new (std::nothrow) OverAligned[3]);
assert(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
@@ -62,7 +63,7 @@ int main(int, char**) {
// 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[3];
+ MaxAligned* x = support::escape(new (std::nothrow) MaxAligned[3]);
assert(x != nullptr);
assert(new_nothrow_called == 0);
@@ -73,7 +74,7 @@ int main(int, char**) {
// Test with a type that is clearly not overaligned
{
new_nothrow_called = delete_called = 0;
- int* x = new (std::nothrow) int[3];
+ int* x = support::escape(new (std::nothrow) int[3]);
assert(x != nullptr);
assert(new_nothrow_called == 0);
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
index 8ad0292dcb5ca4b..2b481c21d5de01d 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
@@ -24,6 +24,7 @@
#include <cstdlib>
#include <cassert>
+#include "escape.h"
#include "test_macros.h"
int new_called = 0;
@@ -44,7 +45,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = new (std::nothrow) int[3];
+ int* x = support::escape(new (std::nothrow) int[3]);
assert(x != nullptr);
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_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp
index b85e15ce64b48ac..f06940ba3701855 100644
--- 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
@@ -18,6 +18,7 @@
#include <cstdlib>
#include <cassert>
+#include "escape.h"
#include "test_macros.h"
int new_nothrow_called = 0;
@@ -35,7 +36,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_nothrow_called = delete_called = 0;
- int* x = new (std::nothrow) int[3];
+ int* x = support::escape(new (std::nothrow) int[3]);
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
index a03313e5872ef3b..f992ad325c0068a 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
@@ -17,6 +17,7 @@
#include <cstdlib>
#include <cassert>
+#include "escape.h"
#include "test_macros.h"
int new_called = 0;
@@ -36,7 +37,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = new int(3);
+ int* x = support::escape(new int(3));
assert(x != nullptr);
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 3cbb5aaf8f0be6d..6575dce91606f6c 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
@@ -28,6 +28,7 @@
#include <cassert>
#include <limits>
+#include "escape.h"
#include "test_macros.h"
#include "../types.h"
@@ -53,7 +54,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
- OverAligned* x = new (std::nothrow) OverAligned;
+ OverAligned* x = support::escape(new (std::nothrow) OverAligned);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
@@ -64,7 +65,7 @@ int main(int, char**) {
// Test with a type that is right on the verge of being overaligned
{
new_called = delete_called = 0;
- MaxAligned* x = new (std::nothrow) MaxAligned;
+ MaxAligned* x = support::escape(new (std::nothrow) MaxAligned);
assert(x != nullptr);
assert(new_called == 0);
@@ -75,7 +76,7 @@ int main(int, char**) {
// Test with a type that is clearly not overaligned
{
new_called = delete_called = 0;
- int* x = new (std::nothrow) int;
+ int* x = support::escape(new (std::nothrow) int);
assert(x != nullptr);
assert(new_called == 0);
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
index 2ae0dfa4f1abc41..e38376a2ce96e06 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
@@ -19,6 +19,7 @@
#include <cstdlib>
#include <cassert>
+#include "escape.h"
#include "test_macros.h"
int new_called = 0;
@@ -39,7 +40,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = new (std::nothrow) int(3);
+ int* x = support::escape(new (std::nothrow) int(3));
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
index c1ad528254af1a4..2c8e22941c999f8 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
@@ -69,7 +69,7 @@ int main(int, char**)
{
std::function<int(int)> f = A();
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
RTTI_ASSERT(f.target<A>());
RTTI_ASSERT(f.target<int(*)(int)>() == 0);
}
diff --git a/libcxx/test/support/count_new.h b/libcxx/test/support/count_new.h
index b6424850101625b..ef4306e520b195b 100644
--- a/libcxx/test/support/count_new.h
+++ b/libcxx/test/support/count_new.h
@@ -181,6 +181,11 @@ class MemCounter
return disable_checking || n == outstanding_new;
}
+ bool checkOutstandingNewLessThanOrEqual(int n) const
+ {
+ return disable_checking || outstanding_new <= n;
+ }
+
bool checkOutstandingNewNotEq(int n) const
{
return disable_checking || n != outstanding_new;
diff --git a/libcxx/test/support/escape.h b/libcxx/test/support/escape.h
new file mode 100644
index 000000000000000..a5556418a8b2e88
--- /dev/null
+++ b/libcxx/test/support/escape.h
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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 SUPPORT_ESCAPE_H
+#define SUPPORT_ESCAPE_H
+
+#include "test_macros.h"
+
+namespace support {
+// This function can be used to hide some objects from compiler optimizations.
+//
+// For example, this is useful to hide the result of a call to `new` and ensure
+// ensure that the compiler doesn't elide the call to new/delete. Otherwise,
+// elliding calls to new/delete is allowed by the Standard and compilers actually
+// do it when optimizations are enabled.
+template <class T>
+TEST_CONSTEXPR __attribute__((noinline)) T* escape(T* ptr) TEST_NOEXCEPT {
+ return ptr;
+}
+} // namespace support
+
+#endif // SUPPORT_ESCAPE_H
>From d2041979ad5d701e58384da37403c636eef5023e Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 1 Nov 2023 14:42:17 -0400
Subject: [PATCH 4/9] Fix more tests that relied on exact numbers of calls to
new
---
.../path.member/path.assign/move.pass.cpp | 2 +-
.../path.member/path.construct/move.pass.cpp | 2 +-
.../func.wrap.func.alg/swap.pass.cpp | 16 ++++++++--------
.../func.wrap.func/func.wrap.func.con/F.pass.cpp | 2 +-
.../func.wrap.func.con/copy_assign.pass.cpp | 8 ++++----
.../func.wrap.func.con/copy_move.pass.cpp | 8 ++++----
.../func.wrap.func.con/nullptr_t_assign.pass.cpp | 2 +-
.../func.wrap.func.mod/swap.pass.cpp | 12 ++++++------
.../make_shared.pass.cpp | 4 ++--
9 files changed, 28 insertions(+), 28 deletions(-)
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 bbc3754fd6992e6..96e44f7b7dadf65 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
@@ -31,7 +31,7 @@ int main(int, char**) {
const std::string s("we really really really really really really really "
"really really long string so that we allocate");
ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
- globalMemCounter.checkOutstandingNewEq(1));
+ globalMemCounter.checkOutstandingNewLessThanOrEqual(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.construct/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
index 8a3aff85690db7c..48ce89544220487 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
@@ -31,7 +31,7 @@ int main(int, char**) {
const std::string s("we really really really really really really really "
"really really long string so that we allocate");
ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
- globalMemCounter.checkOutstandingNewEq(1));
+ globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
const fs::path::string_type ps(s.begin(), s.end());
path p(s);
{
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
index 3924274190c41b1..97f78ac62dab03f 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
@@ -69,12 +69,12 @@ int main(int, char**)
static_assert(noexcept(swap(f1, f2)), "" );
#endif
assert(A::count == 2);
- assert(globalMemCounter.checkOutstandingNewEq(2));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
RTTI_ASSERT(f1.target<A>()->id() == 1);
RTTI_ASSERT(f2.target<A>()->id() == 2);
swap(f1, f2);
assert(A::count == 2);
- assert(globalMemCounter.checkOutstandingNewEq(2));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
RTTI_ASSERT(f1.target<A>()->id() == 2);
RTTI_ASSERT(f2.target<A>()->id() == 1);
}
@@ -87,12 +87,12 @@ int main(int, char**)
static_assert(noexcept(swap(f1, f2)), "" );
#endif
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f1.target<A>()->id() == 1);
RTTI_ASSERT(*f2.target<int(*)(int)>() == g);
swap(f1, f2);
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(*f1.target<int(*)(int)>() == g);
RTTI_ASSERT(f2.target<A>()->id() == 1);
}
@@ -105,12 +105,12 @@ int main(int, char**)
static_assert(noexcept(swap(f1, f2)), "" );
#endif
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(*f1.target<int(*)(int)>() == g);
RTTI_ASSERT(f2.target<A>()->id() == 1);
swap(f1, f2);
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f1.target<A>()->id() == 1);
RTTI_ASSERT(*f2.target<int(*)(int)>() == g);
}
@@ -123,12 +123,12 @@ int main(int, char**)
static_assert(noexcept(swap(f1, f2)), "" );
#endif
assert(A::count == 0);
- assert(globalMemCounter.checkOutstandingNewEq(0));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(0));
RTTI_ASSERT(*f1.target<int(*)(int)>() == g);
RTTI_ASSERT(*f2.target<int(*)(int)>() == h);
swap(f1, f2);
assert(A::count == 0);
- assert(globalMemCounter.checkOutstandingNewEq(0));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(0));
RTTI_ASSERT(*f1.target<int(*)(int)>() == h);
RTTI_ASSERT(*f2.target<int(*)(int)>() == g);
}
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
index 2c8e22941c999f8..92409577d60de51 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
@@ -69,7 +69,7 @@ int main(int, char**)
{
std::function<int(int)> f = A();
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f.target<A>());
RTTI_ASSERT(f.target<int(*)(int)>() == 0);
}
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
index 75eaa55dc71edd3..e3bd6ef78d61029 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
@@ -57,13 +57,13 @@ int main(int, char**) {
{
std::function<int(int)> f = A();
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f.target<A>());
RTTI_ASSERT(f.target<int (*)(int)>() == 0);
std::function<int(int)> f2;
f2 = f;
assert(A::count == 2);
- assert(globalMemCounter.checkOutstandingNewEq(2));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
RTTI_ASSERT(f2.target<A>());
RTTI_ASSERT(f2.target<int (*)(int)>() == 0);
}
@@ -125,13 +125,13 @@ int main(int, char**) {
{
std::function<int(int)> f = A();
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f.target<A>());
RTTI_ASSERT(f.target<int (*)(int)>() == 0);
std::function<int(int)> f2;
f2 = std::move(f);
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f2.target<A>());
RTTI_ASSERT(f2.target<int (*)(int)>() == 0);
RTTI_ASSERT(f.target<A>() == 0);
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
index 4a2a272ae0a3b9d..5b3f4f10cadbb5e 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
@@ -64,12 +64,12 @@ int main(int, char**)
{
std::function<int(int)> f = A();
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f.target<A>());
RTTI_ASSERT(f.target<int(*)(int)>() == 0);
std::function<int(int)> f2 = f;
assert(A::count == 2);
- assert(globalMemCounter.checkOutstandingNewEq(2));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
RTTI_ASSERT(f2.target<A>());
RTTI_ASSERT(f2.target<int(*)(int)>() == 0);
}
@@ -113,7 +113,7 @@ int main(int, char**)
{ // Test rvalue references
std::function<int(int)> f = A();
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f.target<A>());
RTTI_ASSERT(f.target<int(*)(int)>() == 0);
LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f)));
@@ -122,7 +122,7 @@ int main(int, char**)
#endif
std::function<int(int)> f2 = std::move(f);
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f2.target<A>());
RTTI_ASSERT(f2.target<int(*)(int)>() == 0);
RTTI_ASSERT(f.target<A>() == 0);
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
index 391e2a7434bf715..b2f61fa9b68a27c 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
@@ -57,7 +57,7 @@ int main(int, char**)
{
std::function<int(int)> f = A();
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f.target<A>());
f = nullptr;
assert(A::count == 0);
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
index d51c35ea44fa058..1723ddfd33bedc7 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
@@ -68,12 +68,12 @@ int main(int, char**) {
std::function<int(int)> f1 = A(1);
std::function<int(int)> f2 = A(2);
assert(A::count == 2);
- assert(globalMemCounter.checkOutstandingNewEq(2));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
RTTI_ASSERT(f1.target<A>()->id() == 1);
RTTI_ASSERT(f2.target<A>()->id() == 2);
f1.swap(f2);
assert(A::count == 2);
- assert(globalMemCounter.checkOutstandingNewEq(2));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
RTTI_ASSERT(f1.target<A>()->id() == 2);
RTTI_ASSERT(f2.target<A>()->id() == 1);
}
@@ -83,12 +83,12 @@ int main(int, char**) {
std::function<int(int)> f1 = A(1);
std::function<int(int)> f2 = g;
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f1.target<A>()->id() == 1);
RTTI_ASSERT(*f2.target<int (*)(int)>() == g);
f1.swap(f2);
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(*f1.target<int (*)(int)>() == g);
RTTI_ASSERT(f2.target<A>()->id() == 1);
}
@@ -98,12 +98,12 @@ int main(int, char**) {
std::function<int(int)> f1 = g;
std::function<int(int)> f2 = A(1);
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(*f1.target<int (*)(int)>() == g);
RTTI_ASSERT(f2.target<A>()->id() == 1);
f1.swap(f2);
assert(A::count == 1);
- assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
RTTI_ASSERT(f1.target<A>()->id() == 1);
RTTI_ASSERT(*f2.target<int (*)(int)>() == g);
}
diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
index 23a904f8ae11f7f..be7505f218cdd0c 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
@@ -96,7 +96,7 @@ int main(int, char**)
int i = 67;
char c = 'e';
std::shared_ptr<A> p = std::make_shared<A>(i, c);
- assert(globalMemCounter.checkOutstandingNewEq(nc+1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(nc+1));
assert(A::count == 1);
assert(p->get_int() == 67);
assert(p->get_char() == 'e');
@@ -116,7 +116,7 @@ int main(int, char**)
{
char c = 'e';
std::shared_ptr<A> p = std::make_shared<A>(67, c);
- assert(globalMemCounter.checkOutstandingNewEq(nc+1));
+ assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(nc+1));
assert(A::count == 1);
assert(p->get_int() == 67);
assert(p->get_char() == 'e');
>From 8499198a4d7b3b1e269f843ee71108cb6d7fc03c Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Sun, 5 Nov 2023 17:29:38 -0700
Subject: [PATCH 5/9] Try to make libunwind tests more robust to optimizations
---
libunwind/test/libunwind_02.pass.cpp | 26 +++++++++++++++++----
libunwind/test/unw_resume.pass.cpp | 2 +-
libunwind/test/unwind_leaffunction.pass.cpp | 4 ++--
3 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/libunwind/test/libunwind_02.pass.cpp b/libunwind/test/libunwind_02.pass.cpp
index fc034378781a2fa..499cc3b69ab3a3d 100644
--- a/libunwind/test/libunwind_02.pass.cpp
+++ b/libunwind/test/libunwind_02.pass.cpp
@@ -18,7 +18,7 @@
#define EXPECTED_NUM_FRAMES 50
#define NUM_FRAMES_UPPER_BOUND 100
-_Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) {
+__attribute__((noinline)) _Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) {
(void)context;
int *i = (int *)cnt;
++*i;
@@ -28,7 +28,7 @@ _Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) {
return _URC_NO_REASON;
}
-void test_backtrace() {
+__attribute__((noinline)) void test_backtrace() {
int n = 0;
_Unwind_Backtrace(&callback, &n);
if (n < EXPECTED_NUM_FRAMES) {
@@ -36,17 +36,33 @@ void test_backtrace() {
}
}
-int test(int i) {
+// These functions are effectively the same, but we have to be careful to avoid unwanted
+// optimizations that would mess with the number of frames we expect. Surprisingly,
+// slapping `noinline` is not sufficient -- we also have to avoid writing the function
+// in a way that the compiler can easily spot tail recursion.
+__attribute__((noinline)) int test1(int i);
+__attribute__((noinline)) int test2(int i);
+
+__attribute__((noinline)) int test1(int i) {
+ if (i == 0) {
+ test_backtrace();
+ return 0;
+ } else {
+ return i + test2(i - 1);
+ }
+}
+
+__attribute__((noinline)) int test2(int i) {
if (i == 0) {
test_backtrace();
return 0;
} else {
- return i + test(i - 1);
+ return i + test1(i - 1);
}
}
int main(int, char**) {
- int total = test(50);
+ int total = test1(50);
assert(total == 1275);
return 0;
}
diff --git a/libunwind/test/unw_resume.pass.cpp b/libunwind/test/unw_resume.pass.cpp
index 08e8d4edeaf2927..2b7470b5cad0eb7 100644
--- a/libunwind/test/unw_resume.pass.cpp
+++ b/libunwind/test/unw_resume.pass.cpp
@@ -15,7 +15,7 @@
#include <libunwind.h>
-void test_unw_resume() {
+__attribute__((noinline)) void test_unw_resume() {
unw_context_t context;
unw_cursor_t cursor;
diff --git a/libunwind/test/unwind_leaffunction.pass.cpp b/libunwind/test/unwind_leaffunction.pass.cpp
index 8c9912e3c38680b..6e6d9a0ed80d0ff 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -24,7 +24,7 @@
#include <unistd.h>
#include <unwind.h>
-_Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
+__attribute__((noinline)) _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
(void)arg;
Dl_info info = { 0, 0, 0, 0 };
@@ -37,7 +37,7 @@ _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
return _URC_NO_REASON;
}
-void signal_handler(int signum) {
+__attribute__((noinline)) void signal_handler(int signum) {
(void)signum;
_Unwind_Backtrace(frame_handler, NULL);
_Exit(-1);
>From 9c8032b6100c461c1a3c45a1a34ebf99e82bacd3 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 16 Nov 2023 15:23:12 -0500
Subject: [PATCH 6/9] Rename to do_not_optimize()
---
.../support.dynamic/libcpp_deallocate.sh.cpp | 18 +++++++++---------
.../new.size.replace.indirect.pass.cpp | 4 ++--
.../new.delete.array/new.size.replace.pass.cpp | 4 ++--
.../new.size_align.replace.indirect.pass.cpp | 8 ++++----
...ize_align_nothrow.replace.indirect.pass.cpp | 8 ++++----
.../new.size_align_nothrow.replace.pass.cpp | 8 ++++----
.../new.size_nothrow.replace.indirect.pass.cpp | 4 ++--
.../new.size_nothrow.replace.pass.cpp | 4 ++--
.../new.size.replace.pass.cpp | 4 ++--
...ize_align_nothrow.replace.indirect.pass.cpp | 8 ++++----
.../new.size_nothrow.replace.indirect.pass.cpp | 4 ++--
.../support/{escape.h => do_not_optimize.h} | 14 +++++++-------
12 files changed, 44 insertions(+), 44 deletions(-)
rename libcxx/test/support/{escape.h => do_not_optimize.h} (63%)
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
index 48ad34f7d91748b..052d3f9228a4669 100644
--- a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
+++ b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
@@ -38,7 +38,7 @@
#include <cstdlib>
#include <new>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
TEST_DIAGNOSTIC_PUSH
@@ -192,13 +192,13 @@ void test_allocator_and_new_match() {
stats.reset();
#if defined(NO_SIZE) && defined(NO_ALIGN)
{
- int* x = support::escape(new int(42));
+ int* x = support::do_not_optimize(new int(42));
delete x;
assert(stats.expect_plain());
}
stats.reset();
{
- AlignedType* a = support::escape(new AlignedType());
+ AlignedType* a = support::do_not_optimize(new AlignedType());
delete a;
assert(stats.expect_plain());
}
@@ -207,14 +207,14 @@ void test_allocator_and_new_match() {
stats.reset();
#if TEST_STD_VER >= 11
{
- int* x = support::escape(new int(42));
+ int* x = support::do_not_optimize(new int(42));
delete x;
assert(stats.expect_plain());
}
#endif
stats.reset();
{
- AlignedType* a = support::escape(new AlignedType());
+ AlignedType* a = support::do_not_optimize(new AlignedType());
delete a;
assert(stats.expect_align(TEST_ALIGNOF(AlignedType)));
}
@@ -222,13 +222,13 @@ void test_allocator_and_new_match() {
#elif defined(NO_ALIGN)
stats.reset();
{
- int* x = support::escape(new int(42));
+ int* x = support::do_not_optimize(new int(42));
delete x;
assert(stats.expect_size(sizeof(int)));
}
stats.reset();
{
- AlignedType* a = support::escape(new AlignedType());
+ AlignedType* a = support::do_not_optimize(new AlignedType());
delete a;
assert(stats.expect_size(sizeof(AlignedType)));
}
@@ -236,13 +236,13 @@ void test_allocator_and_new_match() {
#else
stats.reset();
{
- int* x = support::escape(new int(42));
+ int* x = support::do_not_optimize(new int(42));
delete x;
assert(stats.expect_size(sizeof(int)));
}
stats.reset();
{
- AlignedType* a = support::escape(new AlignedType());
+ AlignedType* a = support::do_not_optimize(new AlignedType());
delete a;
assert(stats.expect_size_align(sizeof(AlignedType),
TEST_ALIGNOF(AlignedType)));
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
index 56264c25575847e..13f6217c521fa8f 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
@@ -20,7 +20,7 @@
#include <cassert>
#include <limits>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
int new_called = 0;
@@ -41,7 +41,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = support::escape(new int[3]);
+ int* x = support::do_not_optimize(new int[3]);
assert(x != nullptr);
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.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
index 1612ecba96ac9b8..9b3d39986484ddd 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
@@ -19,7 +19,7 @@
#include <cassert>
#include <limits>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
int new_called = 0;
@@ -39,7 +39,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = support::escape(new int[3]);
+ int* x = support::do_not_optimize(new int[3]);
assert(x != nullptr);
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.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 370aba01a2c819d..e83996bc82a82f8 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
@@ -29,7 +29,7 @@
#include <cassert>
#include <limits>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
#include "../types.h"
@@ -55,7 +55,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
- OverAligned* x = support::escape(new OverAligned[3]);
+ OverAligned* x = support::do_not_optimize(new OverAligned[3]);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
@@ -66,7 +66,7 @@ int main(int, char**) {
// Test with a type that is right on the verge of being overaligned
{
new_called = delete_called = 0;
- MaxAligned* x = support::escape(new MaxAligned[3]);
+ MaxAligned* x = support::do_not_optimize(new MaxAligned[3]);
assert(x != nullptr);
assert(new_called == 0);
@@ -77,7 +77,7 @@ int main(int, char**) {
// Test with a type that is clearly not overaligned
{
new_called = delete_called = 0;
- int* x = support::escape(new int[3]);
+ int* x = support::do_not_optimize(new int[3]);
assert(x != nullptr);
assert(new_called == 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
index 12b77c4d33c9417..ab9f32221af8731 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
@@ -29,7 +29,7 @@
#include <cassert>
#include <limits>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
#include "../types.h"
@@ -55,7 +55,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
- OverAligned* x = support::escape(new (std::nothrow) OverAligned[3]);
+ OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned[3]);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
@@ -66,7 +66,7 @@ int main(int, char**) {
// Test with a type that is right on the verge of being overaligned
{
new_called = delete_called = 0;
- MaxAligned* x = support::escape(new (std::nothrow) MaxAligned[3]);
+ MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned[3]);
assert(x != nullptr);
assert(new_called == 0);
@@ -77,7 +77,7 @@ int main(int, char**) {
// Test with a type that is clearly not overaligned
{
new_called = delete_called = 0;
- int* x = support::escape(new (std::nothrow) int[3]);
+ int* x = support::do_not_optimize(new (std::nothrow) int[3]);
assert(x != nullptr);
assert(new_called == 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
index 6e4b95a2eea213a..3f5c5c164f99160 100644
--- 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
@@ -26,7 +26,7 @@
#include <cassert>
#include <limits>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
#include "../types.h"
@@ -52,7 +52,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_nothrow_called = delete_called = 0;
- OverAligned* x = support::escape(new (std::nothrow) OverAligned[3]);
+ OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned[3]);
assert(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
@@ -63,7 +63,7 @@ int main(int, char**) {
// Test with a type that is right on the verge of being overaligned
{
new_nothrow_called = delete_called = 0;
- MaxAligned* x = support::escape(new (std::nothrow) MaxAligned[3]);
+ MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned[3]);
assert(x != nullptr);
assert(new_nothrow_called == 0);
@@ -74,7 +74,7 @@ int main(int, char**) {
// Test with a type that is clearly not overaligned
{
new_nothrow_called = delete_called = 0;
- int* x = support::escape(new (std::nothrow) int[3]);
+ int* x = support::do_not_optimize(new (std::nothrow) int[3]);
assert(x != nullptr);
assert(new_nothrow_called == 0);
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
index 2b481c21d5de01d..8b0d801acd1fcc6 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
@@ -24,7 +24,7 @@
#include <cstdlib>
#include <cassert>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
int new_called = 0;
@@ -45,7 +45,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = support::escape(new (std::nothrow) int[3]);
+ int* x = support::do_not_optimize(new (std::nothrow) int[3]);
assert(x != nullptr);
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_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp
index f06940ba3701855..c9e4942d8153166 100644
--- 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
@@ -18,7 +18,7 @@
#include <cstdlib>
#include <cassert>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
int new_nothrow_called = 0;
@@ -36,7 +36,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_nothrow_called = delete_called = 0;
- int* x = support::escape(new (std::nothrow) int[3]);
+ int* x = support::do_not_optimize(new (std::nothrow) int[3]);
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
index f992ad325c0068a..c62268c39027c8d 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
@@ -17,7 +17,7 @@
#include <cstdlib>
#include <cassert>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
int new_called = 0;
@@ -37,7 +37,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = support::escape(new int(3));
+ int* x = support::do_not_optimize(new int(3));
assert(x != nullptr);
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 6575dce91606f6c..5ded20bf0463dc4 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
@@ -28,7 +28,7 @@
#include <cassert>
#include <limits>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
#include "../types.h"
@@ -54,7 +54,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
- OverAligned* x = support::escape(new (std::nothrow) OverAligned);
+ OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
@@ -65,7 +65,7 @@ int main(int, char**) {
// Test with a type that is right on the verge of being overaligned
{
new_called = delete_called = 0;
- MaxAligned* x = support::escape(new (std::nothrow) MaxAligned);
+ MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned);
assert(x != nullptr);
assert(new_called == 0);
@@ -76,7 +76,7 @@ int main(int, char**) {
// Test with a type that is clearly not overaligned
{
new_called = delete_called = 0;
- int* x = support::escape(new (std::nothrow) int);
+ int* x = support::do_not_optimize(new (std::nothrow) int);
assert(x != nullptr);
assert(new_called == 0);
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
index e38376a2ce96e06..e5f91ad44fc0cf3 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
@@ -19,7 +19,7 @@
#include <cstdlib>
#include <cassert>
-#include "escape.h"
+#include "do_not_optimize.h"
#include "test_macros.h"
int new_called = 0;
@@ -40,7 +40,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
int main(int, char**) {
new_called = delete_called = 0;
- int* x = support::escape(new (std::nothrow) int(3));
+ int* x = support::do_not_optimize(new (std::nothrow) int(3));
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
diff --git a/libcxx/test/support/escape.h b/libcxx/test/support/do_not_optimize.h
similarity index 63%
rename from libcxx/test/support/escape.h
rename to libcxx/test/support/do_not_optimize.h
index a5556418a8b2e88..542851a8ea6ae2d 100644
--- a/libcxx/test/support/escape.h
+++ b/libcxx/test/support/do_not_optimize.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef SUPPORT_ESCAPE_H
-#define SUPPORT_ESCAPE_H
+#ifndef SUPPORT_DO_NOT_OPTIMIZE_H
+#define SUPPORT_DO_NOT_OPTIMIZE_H
#include "test_macros.h"
@@ -16,13 +16,13 @@ namespace support {
// This function can be used to hide some objects from compiler optimizations.
//
// For example, this is useful to hide the result of a call to `new` and ensure
-// ensure that the compiler doesn't elide the call to new/delete. Otherwise,
-// elliding calls to new/delete is allowed by the Standard and compilers actually
-// do it when optimizations are enabled.
+// that the compiler doesn't elide the call to new/delete. Otherwise, elliding
+// calls to new/delete is allowed by the Standard and compilers actually do it
+// when optimizations are enabled.
template <class T>
-TEST_CONSTEXPR __attribute__((noinline)) T* escape(T* ptr) TEST_NOEXCEPT {
+TEST_CONSTEXPR __attribute__((noinline)) T* do_not_optimize(T* ptr) TEST_NOEXCEPT {
return ptr;
}
} // namespace support
-#endif // SUPPORT_ESCAPE_H
+#endif // SUPPORT_DO_NOT_OPTIMIZE_H
>From 3d951ebbc01b7554dfb0513c3383ca55d798bcbf Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 16 Nov 2023 15:24:18 -0500
Subject: [PATCH 7/9] Rename CI job to -optimized-speed
---
...{Generic-optimized.cmake => Generic-optimized-speed.cmake} | 0
libcxx/utils/ci/buildkite-pipeline.yml | 2 +-
libcxx/utils/ci/run-buildbot | 4 ++--
3 files changed, 3 insertions(+), 3 deletions(-)
rename libcxx/cmake/caches/{Generic-optimized.cmake => Generic-optimized-speed.cmake} (100%)
diff --git a/libcxx/cmake/caches/Generic-optimized.cmake b/libcxx/cmake/caches/Generic-optimized-speed.cmake
similarity index 100%
rename from libcxx/cmake/caches/Generic-optimized.cmake
rename to libcxx/cmake/caches/Generic-optimized-speed.cmake
diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml
index db11f1cfa178bd7..b147d4199246e03 100644
--- a/libcxx/utils/ci/buildkite-pipeline.yml
+++ b/libcxx/utils/ci/buildkite-pipeline.yml
@@ -704,7 +704,7 @@ steps:
timeout_in_minutes: 120
- label: "Optimized build and test suite"
- command: "libcxx/utils/ci/run-buildbot generic-optimized"
+ command: "libcxx/utils/ci/run-buildbot generic-optimized-speed"
artifact_paths:
- "**/test-results.xml"
- "**/*.abilist"
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index 682713409b31ef3..ae09837140df4df 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -491,9 +491,9 @@ generic-abi-unstable)
generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-abi-unstable.cmake"
check-runtimes
;;
-generic-optimized)
+generic-optimized-speed)
clean
- generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-optimized.cmake"
+ generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-optimized-speed.cmake"
check-runtimes
;;
apple-system)
>From b18b216d32e8e329bece8813f9297d734594d78f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 16 Nov 2023 15:48:41 -0500
Subject: [PATCH 8/9] NFC fix typo
---
libunwind/test/unwind_leaffunction.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libunwind/test/unwind_leaffunction.pass.cpp b/libunwind/test/unwind_leaffunction.pass.cpp
index 6e6d9a0ed80d0ff..cff0969c44a5faf 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -28,7 +28,7 @@ __attribute__((noinline)) _Unwind_Reason_Code frame_handler(struct _Unwind_Conte
(void)arg;
Dl_info info = { 0, 0, 0, 0 };
- // Unwind until the main is reached, above frames deeped on the platform and
+ // Unwind until the main is reached, above frames depend on the platform and
// architecture.
if (dladdr(reinterpret_cast<void *>(_Unwind_GetIP(ctx)), &info) &&
info.dli_sname && !strcmp("main", info.dli_sname)) {
>From 8f9d777ba7c1d322bf8e4a98028a2ee145d1eed7 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 16 Nov 2023 16:06:43 -0500
Subject: [PATCH 9/9] Fix last libunwind test
---
libunwind/test/unwind_leaffunction.pass.cpp | 22 ++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/libunwind/test/unwind_leaffunction.pass.cpp b/libunwind/test/unwind_leaffunction.pass.cpp
index cff0969c44a5faf..bcfb38f11f3fbde 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -24,7 +24,7 @@
#include <unistd.h>
#include <unwind.h>
-__attribute__((noinline)) _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
+_Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
(void)arg;
Dl_info info = { 0, 0, 0, 0 };
@@ -37,24 +37,28 @@ __attribute__((noinline)) _Unwind_Reason_Code frame_handler(struct _Unwind_Conte
return _URC_NO_REASON;
}
-__attribute__((noinline)) void signal_handler(int signum) {
+void signal_handler(int signum) {
(void)signum;
_Unwind_Backtrace(frame_handler, NULL);
_Exit(-1);
}
-__attribute__((noinline)) void crashing_leaf_func(void) {
+__attribute__((noinline)) void crashing_leaf_func(int do_trap) {
// libunwind searches for the address before the return address which points
- // to the trap instruction. NOP guarantees the trap instruction is not the
- // first instruction of the function.
- // We should keep this here for other unwinders that also decrement pc.
- __asm__ __volatile__("nop");
- __builtin_trap();
+ // to the trap instruction. We make the trap conditional and prevent inlining
+ // of the function to ensure that the compiler doesn't remove the `ret` instruction
+ // altogether.
+ //
+ // It's also important that the trap instruction isn't the first instruction in the
+ // function (which it isn't because of the branch) for other unwinders that also
+ // decrement pc.
+ if (do_trap)
+ __builtin_trap();
}
int main(int, char**) {
signal(SIGTRAP, signal_handler);
signal(SIGILL, signal_handler);
- crashing_leaf_func();
+ crashing_leaf_func(1);
return -2;
}
More information about the libcxx-commits
mailing list