From 770390b31c29091eabd039fa4513e595ac41023c Mon Sep 17 00:00:00 2001 From: Claudio DeSouza Date: Mon, 21 Jul 2025 12:02:08 +0100 Subject: [PATCH] Avod exit-time destructors in macros when possible This change attemps to reduce the introduction of exit-time destructors by gtest/gmock whenever it is possible, to just skip the destructor during termination. This is useful for codebases that aim to comply with clang's `-Wexit-time-destructors`. However, this change does not attempt to make all of gtest/gmock complaint with this warning, but limits itself to what merely affects user code. Bug: https://github.com/google/googletest/issues/4803 --- googlemock/include/gmock/internal/gmock-port.h | 3 ++- googletest/include/gtest/gtest-typed-test.h | 4 ++-- googletest/include/gtest/internal/gtest-internal.h | 6 ++++++ googletest/include/gtest/internal/gtest-port.h | 9 ++++++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/googlemock/include/gmock/internal/gmock-port.h b/googlemock/include/gmock/internal/gmock-port.h index 42d36d2f1..59ac19b4c 100644 --- a/googlemock/include/gmock/internal/gmock-port.h +++ b/googlemock/include/gmock/internal/gmock-port.h @@ -111,7 +111,8 @@ static_assert(true, "no-op to require trailing semicolon") #define GMOCK_DEFINE_string_(name, default_val, doc) \ namespace testing { \ - GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val); \ + GTEST_API_ GMOCK_NODESTRUCTOR \ + ::std::string GMOCK_FLAG(name) = (default_val); \ } \ static_assert(true, "no-op to require trailing semicolon") diff --git a/googletest/include/gtest/gtest-typed-test.h b/googletest/include/gtest/gtest-typed-test.h index 442e00bd3..13366bb53 100644 --- a/googletest/include/gtest/gtest-typed-test.h +++ b/googletest/include/gtest/gtest-typed-test.h @@ -256,8 +256,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); // The variables defined in the type-parameterized test macros are // static as typically these macros are used in a .h file that can be // #included in multiple translation units linked together. -#define TYPED_TEST_SUITE_P(SuiteName) \ - static ::testing::internal::TypedTestSuitePState \ +#define TYPED_TEST_SUITE_P(SuiteName) \ + GTEST_NODESTRUCTOR static ::testing::internal::TypedTestSuitePState \ GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName) // Legacy API is deprecated but still available diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index 808d89be9..77d540123 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -1514,4 +1514,10 @@ class NeverThrown { test_suite_name, test_name)>); \ void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() +#ifdef __clang__ +#define GTEST_NODESTRUCTOR [[clang::no_destroy]] +#else +#define GTEST_NODESTRUCTOR +#endif + #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h index 06a5a8e6f..2b4a361a4 100644 --- a/googletest/include/gtest/internal/gtest-port.h +++ b/googletest/include/gtest/internal/gtest-port.h @@ -2229,6 +2229,12 @@ using TimeInMillis = int64_t; // Represents time in milliseconds. #define GTEST_FLAG(name) FLAGS_gtest_##name #endif // !defined(GTEST_FLAG) +#ifdef __clang__ +#define GMOCK_NODESTRUCTOR [[clang::no_destroy]] +#else +#define GMOCK_NODESTRUCTOR +#endif + // Pick a command line flags implementation. #ifdef GTEST_INTERNAL_HAS_ABSL_FLAGS @@ -2271,7 +2277,8 @@ using TimeInMillis = int64_t; // Represents time in milliseconds. static_assert(true, "no-op to require trailing semicolon") #define GTEST_DEFINE_string_(name, default_val, doc) \ namespace testing { \ - GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val); \ + GTEST_API_ GTEST_NODESTRUCTOR \ + ::std::string GTEST_FLAG(name) = (default_val); \ } \ static_assert(true, "no-op to require trailing semicolon")