diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -757,6 +757,12 @@ # define _LIBCPP_CONSTEXPR constexpr #endif +#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS +# define _LIBCPP_CONSTEXPR_WHEN_NONLEGACY +#else +# define _LIBCPP_CONSTEXPR_WHEN_NONLEGACY _LIBCPP_CONSTEXPR +#endif + #ifndef __cpp_consteval # define _LIBCPP_CONSTEVAL _LIBCPP_CONSTEXPR #else @@ -1160,6 +1166,12 @@ # define _LIBCPP_CONSTINIT #endif +#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS +# define _LIBCPP_CONSTINIT_WHEN_NONLEGACY +#else +# define _LIBCPP_CONSTINIT_WHEN_NONLEGACY _LIBCPP_CONSTINIT +#endif + #if __has_attribute(diagnose_if) && !defined(_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS) # define _LIBCPP_DIAGNOSE_WARNING(...) \ __attribute__((diagnose_if(__VA_ARGS__, "warning"))) diff --git a/libcxx/src/future.cpp b/libcxx/src/future.cpp --- a/libcxx/src/future.cpp +++ b/libcxx/src/future.cpp @@ -59,8 +59,17 @@ const error_category& future_category() noexcept { - static __future_error_category __f; - return __f; + union FutureErrorHelper { + struct { + __future_error_category new_future_error_category; + } future_error_category; + _LIBCPP_CONSTEXPR_WHEN_NONLEGACY explicit FutureErrorHelper() + : future_error_category() {} + ~FutureErrorHelper() {} + }; + _LIBCPP_NO_DESTROY _LIBCPP_CONSTINIT_WHEN_NONLEGACY + static FutureErrorHelper __f; + return __f.future_error_category.new_future_error_category; } future_error::future_error(error_code __ec) diff --git a/libcxx/src/ios.cpp b/libcxx/src/ios.cpp --- a/libcxx/src/ios.cpp +++ b/libcxx/src/ios.cpp @@ -52,8 +52,17 @@ const error_category& iostream_category() noexcept { - static __iostream_category s; - return s; + union IostreamErrorHelper { + struct { + __iostream_category new_iostream_error_category; + } iostream_error_category; + _LIBCPP_CONSTEXPR_WHEN_NONLEGACY explicit IostreamErrorHelper() + : iostream_error_category() {} + ~IostreamErrorHelper() {} + }; + _LIBCPP_NO_DESTROY _LIBCPP_CONSTINIT_WHEN_NONLEGACY + static IostreamErrorHelper s; + return s.iostream_error_category.new_iostream_error_category; } // ios_base::failure diff --git a/libcxx/src/system_error.cpp b/libcxx/src/system_error.cpp --- a/libcxx/src/system_error.cpp +++ b/libcxx/src/system_error.cpp @@ -163,8 +163,17 @@ const error_category& generic_category() noexcept { - static __generic_error_category s; - return s; + union GenericErrorHelper { + struct { + __generic_error_category new_generic_error_category; + } generic_error_category; + _LIBCPP_CONSTEXPR_WHEN_NONLEGACY explicit GenericErrorHelper() + : generic_error_category() {} + ~GenericErrorHelper() {} + }; + _LIBCPP_NO_DESTROY _LIBCPP_CONSTINIT_WHEN_NONLEGACY + static GenericErrorHelper s; + return s.generic_error_category.new_generic_error_category; } class _LIBCPP_HIDDEN __system_error_category @@ -205,8 +214,17 @@ const error_category& system_category() noexcept { - static __system_error_category s; - return s; + union SystemErrorHelper { + struct { + __system_error_category new_system_error_category; + } system_error_category; + _LIBCPP_CONSTEXPR_WHEN_NONLEGACY explicit SystemErrorHelper() + : system_error_category() {} + ~SystemErrorHelper() {} + }; + _LIBCPP_NO_DESTROY _LIBCPP_CONSTINIT_WHEN_NONLEGACY + static SystemErrorHelper s; + return s.system_error_category.new_system_error_category; } // error_condition diff --git a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp --- a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp +++ b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp @@ -22,6 +22,14 @@ #include "test_macros.h" +struct A { + const std::error_category* ec; + ~A() { + std::string str = ec->name(); + assert(str == "generic") ; + } +} a; + void test_message_for_bad_value() { errno = E2BIG; // something that message will never generate const std::error_category& e_cat1 = std::generic_category(); @@ -44,5 +52,9 @@ test_message_for_bad_value(); } + a.ec = &std::generic_category(); + std::string m2 = a.ec->name(); + assert(m2 == "generic"); + return 0; } diff --git a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp --- a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp +++ b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp @@ -22,6 +22,14 @@ #include "test_macros.h" +struct A { + const std::error_category* ec; + ~A() { + std::string str = ec->name(); + assert(str == "system") ; + } +} a; + void test_message_for_bad_value() { errno = E2BIG; // something that message will never generate const std::error_category& e_cat1 = std::system_category(); @@ -48,5 +56,9 @@ test_message_for_bad_value(); } + a.ec = &std::system_category(); + std::string m = a.ec->name(); + assert(m == "system"); + return 0; } diff --git a/libcxx/test/std/input.output/iostreams.base/std.ios.manip/error.reporting/iostream_category.pass.cpp b/libcxx/test/std/input.output/iostreams.base/std.ios.manip/error.reporting/iostream_category.pass.cpp --- a/libcxx/test/std/input.output/iostreams.base/std.ios.manip/error.reporting/iostream_category.pass.cpp +++ b/libcxx/test/std/input.output/iostreams.base/std.ios.manip/error.reporting/iostream_category.pass.cpp @@ -16,11 +16,23 @@ #include "test_macros.h" +struct A { + const std::error_category* ec; + ~A() { + std::string str = ec->name(); + assert(str == "iostream") ; + } +} a; + int main(int, char**) { const std::error_category& e_cat1 = std::iostream_category(); std::string m1 = e_cat1.name(); assert(m1 == "iostream"); + a.ec = &std::iostream_category(); + std::string m2 = a.ec->name(); + assert(m2 == "iostream"); + return 0; } diff --git a/libcxx/test/std/thread/futures/futures.errors/future_category.pass.cpp b/libcxx/test/std/thread/futures/futures.errors/future_category.pass.cpp --- a/libcxx/test/std/thread/futures/futures.errors/future_category.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.errors/future_category.pass.cpp @@ -18,10 +18,20 @@ #include "test_macros.h" +struct A { + const std::error_category* ec; + ~A() { + assert(std::strcmp(ec->name(), "future") == 0); + } +} a; + int main(int, char**) { const std::error_category& ec = std::future_category(); assert(std::strcmp(ec.name(), "future") == 0); + a.ec = &std::future_category(); + assert(std::strcmp(a.ec->name(), "future") == 0); + return 0; }