diff --git a/libcxx/src/future.cpp b/libcxx/src/future.cpp --- a/libcxx/src/future.cpp +++ b/libcxx/src/future.cpp @@ -7,6 +7,9 @@ //===----------------------------------------------------------------------===// #include <__config> +#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS +# define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS +#endif #ifndef _LIBCPP_HAS_NO_THREADS @@ -59,8 +62,30 @@ const error_category& future_category() noexcept { - static __future_error_category __f; - return __f; +#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS) + union FutureErrorHelper { + struct { + __future_error_category new_future_error_category; + } future_error_category; + explicit FutureErrorHelper() + : future_error_category() {} + ~FutureErrorHelper() {} + }; + _LIBCPP_NO_DESTROY + static FutureErrorHelper __f; +#else + union FutureErrorHelper { + struct { + __future_error_category new_future_error_category; + } future_error_category; + _LIBCPP_CONSTEXPR explicit FutureErrorHelper() + : future_error_category() {} + ~FutureErrorHelper() {} + }; + _LIBCPP_NO_DESTROY _LIBCPP_CONSTINIT + static FutureErrorHelper __f; +#endif + 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 @@ -7,6 +7,10 @@ //===----------------------------------------------------------------------===// #include <__config> +#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS +# define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS +#endif + #include <__locale> #include #include @@ -52,8 +56,29 @@ const error_category& iostream_category() noexcept { - static __iostream_category s; - return s; +#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS) + union IostreamErrorHelper { + struct { + __iostream_category new_iostream_error_category; + } iostream_error_category; + explicit IostreamErrorHelper() + : iostream_error_category() {} + ~IostreamErrorHelper() {} + }; + _LIBCPP_NO_DESTROY static IostreamErrorHelper s; +#else + union IostreamErrorHelper { + struct { + __iostream_category new_iostream_error_category; + } iostream_error_category; + _LIBCPP_CONSTEXPR explicit IostreamErrorHelper() + : iostream_error_category() {} + ~IostreamErrorHelper() {} + }; + _LIBCPP_NO_DESTROY _LIBCPP_CONSTINIT + static IostreamErrorHelper s; +#endif + 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 @@ -167,8 +167,28 @@ const error_category& generic_category() noexcept { - static __generic_error_category s; - return s; +#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS) + union GenericErrorHelper { + struct { + __generic_error_category new_generic_error_category; + } generic_error_category; + explicit GenericErrorHelper() + : generic_error_category() {} + ~GenericErrorHelper() {} + }; + _LIBCPP_NO_DESTROY static GenericErrorHelper s; +#else + union GenericErrorHelper { + struct { + __generic_error_category new_generic_error_category; + } generic_error_category; + _LIBCPP_CONSTEXPR explicit GenericErrorHelper() + : generic_error_category() {} + ~GenericErrorHelper() {} + }; + _LIBCPP_NO_DESTROY _LIBCPP_CONSTINIT static GenericErrorHelper s; +#endif + return s.generic_error_category.new_generic_error_category; } class _LIBCPP_HIDDEN __system_error_category @@ -209,8 +229,29 @@ const error_category& system_category() noexcept { - static __system_error_category s; - return s; +#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS) + union SystemErrorHelper { + struct { + __system_error_category new_system_error_category; + } system_error_category; + explicit SystemErrorHelper() + : system_error_category() {} + ~SystemErrorHelper() {} + }; + _LIBCPP_NO_DESTROY static SystemErrorHelper s; +#else + union SystemErrorHelper { + struct { + __system_error_category new_system_error_category; + } system_error_category; + _LIBCPP_CONSTEXPR explicit SystemErrorHelper() + : system_error_category() {} + ~SystemErrorHelper() {} + }; + _LIBCPP_NO_DESTROY _LIBCPP_CONSTINIT + static SystemErrorHelper s; +#endif + 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,27 +22,40 @@ #include "test_macros.h" +struct A { + const std::error_category* ec; + ~A() { + std::string str = ec->name(); + assert(str == "generic") ; + } +}; +static A a; + void test_message_for_bad_value() { - errno = E2BIG; // something that message will never generate - const std::error_category& e_cat1 = std::generic_category(); - const std::string msg = e_cat1.message(-1); - // Exact message format varies by platform. - #if defined(_AIX) - LIBCPP_ASSERT(msg.rfind("Error -1 occurred", 0) == 0); - #else - LIBCPP_ASSERT(msg.rfind("Unknown error", 0) == 0); - #endif - assert(errno == E2BIG); + errno = E2BIG; // something that message will never generate + const std::error_category& e_cat1 = std::generic_category(); + const std::string msg = e_cat1.message(-1); + // Exact message format varies by platform. + #if defined(_AIX) + LIBCPP_ASSERT(msg.rfind("Error -1 occurred", 0) == 0); + #else + LIBCPP_ASSERT(msg.rfind("Unknown error", 0) == 0); + #endif + assert(errno == E2BIG); } int main(int, char**) { - const std::error_category& e_cat1 = std::generic_category(); - std::string m1 = e_cat1.name(); - assert(m1 == "generic"); - { - test_message_for_bad_value(); - } + const std::error_category& e_cat1 = std::generic_category(); + std::string m1 = e_cat1.name(); + assert(m1 == "generic"); + { + 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,31 +22,44 @@ #include "test_macros.h" +struct A { + const std::error_category* ec; + ~A() { + std::string str = ec->name(); + assert(str == "system") ; + } +}; +static A a; + void test_message_for_bad_value() { - errno = E2BIG; // something that message will never generate - const std::error_category& e_cat1 = std::system_category(); - const std::string msg = e_cat1.message(-1); - // Exact message format varies by platform. - #if defined(_AIX) - LIBCPP_ASSERT(msg.rfind("Error -1 occurred", 0) == 0); - #else - LIBCPP_ASSERT(msg.rfind("Unknown error", 0) == 0); - #endif - assert(errno == E2BIG); + errno = E2BIG; // something that message will never generate + const std::error_category& e_cat1 = std::system_category(); + const std::string msg = e_cat1.message(-1); + // Exact message format varies by platform. + #if defined(_AIX) + LIBCPP_ASSERT(msg.rfind("Error -1 occurred", 0) == 0); + #else + LIBCPP_ASSERT(msg.rfind("Unknown error", 0) == 0); + #endif + assert(errno == E2BIG); } int main(int, char**) { - const std::error_category& e_cat1 = std::system_category(); - std::error_condition e_cond = e_cat1.default_error_condition(5); - assert(e_cond.value() == 5); - assert(e_cond.category() == std::generic_category()); - e_cond = e_cat1.default_error_condition(5000); - assert(e_cond.value() == 5000); - assert(e_cond.category() == std::system_category()); - { - test_message_for_bad_value(); - } + const std::error_category& e_cat1 = std::system_category(); + std::error_condition e_cond = e_cat1.default_error_condition(5); + assert(e_cond.value() == 5); + assert(e_cond.category() == std::generic_category()); + e_cond = e_cat1.default_error_condition(5000); + assert(e_cond.value() == 5000); + assert(e_cond.category() == std::system_category()); + { + 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,24 @@ #include "test_macros.h" +struct A { + const std::error_category* ec; + ~A() { + std::string str = ec->name(); + assert(str == "iostream") ; + } +}; +static A a; + int main(int, char**) { - const std::error_category& e_cat1 = std::iostream_category(); - std::string m1 = e_cat1.name(); - assert(m1 == "iostream"); + 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,21 @@ #include "test_macros.h" +struct A { + const std::error_category* ec; + ~A() { + assert(std::strcmp(ec->name(), "future") == 0); + } +}; +static A a; + int main(int, char**) { - const std::error_category& ec = std::future_category(); - assert(std::strcmp(ec.name(), "future") == 0); + 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; }