crt: test: Add new t_cpp_dtor_atexit_order test which verifies order of atexit callbacks and C++ thread local destructors Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-crt/testcases/Makefile.am b/mingw-w64-crt/testcases/Makefile.am index 8459e28..41ce467 100644 --- a/mingw-w64-crt/testcases/Makefile.am +++ b/mingw-w64-crt/testcases/Makefile.am
@@ -96,6 +96,7 @@ t_assert \ t_btowc \ t_char16_t \ + t_cpp_dtor_atexit_order \ t_ctype \ t_excpt_gcc_cpp \ t_excpt_int_divzero \ @@ -211,6 +212,7 @@ # Most of the tests are C programs, but there are some C++ tests as well. # For C++ targets, we have to explicitly specify source files so that # Automake does not assume .c extension. +t_cpp_dtor_atexit_order_SOURCES = t_cpp_dtor_atexit_order.cpp t_intrin_cpp_SOURCES = t_intrin_cpp.cpp t_iostream_SOURCES = t_iostream.cpp t_isfine_SOURCES = t_isfine.cpp @@ -222,6 +224,7 @@ # On arm64ec, link all C++ tests statically; the toolchain (and the C++ DLL in # PATH) may be regular native aarch64, but we build and run arm64ec binaries. +t_cpp_dtor_atexit_order_LDFLAGS = $(AM_LDFLAGS) t_intrin_cpp_LDFLAGS = $(AM_LDFLAGS) t_iostream_LDFLAGS = $(AM_LDFLAGS) t_isfine_LDFLAGS = $(AM_LDFLAGS) @@ -232,6 +235,7 @@ t_wrongret_LDFLAGS = $(AM_LDFLAGS) if ARM64EC +t_cpp_dtor_atexit_order_LDFLAGS += -static t_intrin_cpp_LDFLAGS += -static t_iostream_LDFLAGS += -static t_isfine_LDFLAGS += -static
diff --git a/mingw-w64-crt/testcases/t_cpp_dtor_atexit_order.cpp b/mingw-w64-crt/testcases/t_cpp_dtor_atexit_order.cpp new file mode 100644 index 0000000..dce7641 --- /dev/null +++ b/mingw-w64-crt/testcases/t_cpp_dtor_atexit_order.cpp
@@ -0,0 +1,53 @@ +#include <cstdio> +#include <cstdlib> + +/* mingw-w64 headers */ +#ifdef __MINGW64_VERSION_MAJOR +#include "libtest.h" +#endif + +template <void (*callback)()> struct dtor_callback { ~dtor_callback() { callback(); } }; + +bool main_success = false; + +void cpp_tls_dtor_func() { + std::puts("C++ tls dtor func called"); + if (!main_success) { + std::_Exit(1); + } + std::puts("TEST PASSED"); + std::_Exit(0); +} +template struct dtor_callback<&cpp_tls_dtor_func>; +thread_local dtor_callback<&cpp_tls_dtor_func> register_tls_dtor_callback; + +void atexit_func() { + std::puts("atexit func called"); + std::puts("TEST FAILED"); + main_success = false; + std::_Exit(1); +} + +int main() { +#ifdef __MINGW64_VERSION_MAJOR + mingw_test_init(); +#endif + + /* For some unknown reasons, this test is passing under mingw-w64 clang and under linux gcc but is failing under mingw-w64 gcc */ +#if defined(__MINGW64_VERSION_MAJOR) && !defined(__clang__) + return 77; +#endif + + std::puts("registering atexit func"); + std::atexit(atexit_func); + + std::puts("referencing C++ TLS obj"); + (void)register_tls_dtor_callback; + + std::puts("registering atexit func"); + std::atexit(atexit_func); + + std::puts("returning from main"); + main_success = true; + return 1; +}