Index: libcxx/src/future.cpp =================================================================== --- libcxx/src/future.cpp +++ libcxx/src/future.cpp @@ -64,11 +64,26 @@ #pragma GCC diagnostic pop #endif +namespace { + +union FutureErrorHelper { + struct { + __future_error_category new_future_error_category; + } future_error_category; + _LIBCPP_CONSTEXPR_AFTER_CXX11 FutureErrorHelper() : future_error_category() {} + ~FutureErrorHelper(){}; +}; + +} // end namespace + const error_category& future_category() _NOEXCEPT { - static __future_error_category __f; - return __f; +#if _LIBCPP_STD_VER > 11 + _LIBCPP_SAFE_STATIC +#endif + static FutureErrorHelper __f; + return __f.future_error_category.new_future_error_category; } future_error::future_error(error_code __ec) Index: libcxx/src/ios.cpp =================================================================== --- libcxx/src/ios.cpp +++ libcxx/src/ios.cpp @@ -65,11 +65,26 @@ return string("unspecified iostream_category error"); } +namespace { + +union IostreamErrorHelper { + struct { + __iostream_category new_iostream_error_category; + } iostream_error; + _LIBCPP_CONSTEXPR_AFTER_CXX11 IostreamErrorHelper() : iostream_error() {} + ~IostreamErrorHelper(){}; +}; + +} // end namespace + const error_category& iostream_category() _NOEXCEPT { - static __iostream_category s; - return s; +#if _LIBCPP_STD_VER > 11 + _LIBCPP_SAFE_STATIC +#endif + static IostreamErrorHelper s; + return s.iostream_error.new_iostream_error_category; } // ios_base::failure Index: libcxx/src/system_error.cpp =================================================================== --- libcxx/src/system_error.cpp +++ libcxx/src/system_error.cpp @@ -161,13 +161,6 @@ return __do_message::message(ev); } -const error_category& -generic_category() _NOEXCEPT -{ - static __generic_error_category s; - return s; -} - class _LIBCPP_HIDDEN __system_error_category : public __do_message { @@ -203,11 +196,37 @@ return error_condition(ev, generic_category()); } +namespace { + +union GenericAndSystemErrorHelper { + struct { + __generic_error_category new_generic_error_category; + __system_error_category new_system_error_category; + } errors; + _LIBCPP_CONSTEXPR_AFTER_CXX11 GenericAndSystemErrorHelper() : errors() {} + ~GenericAndSystemErrorHelper(){}; +}; + +} // end namespace + +const error_category& +generic_category() _NOEXCEPT +{ +#if _LIBCPP_STD_VER > 11 + _LIBCPP_SAFE_STATIC +#endif + static GenericAndSystemErrorHelper s; + return s.errors.new_generic_error_category; +} + const error_category& system_category() _NOEXCEPT { - static __system_error_category s; - return s; +#if _LIBCPP_STD_VER > 11 + _LIBCPP_SAFE_STATIC +#endif + static GenericAndSystemErrorHelper s; + return s.errors.new_system_error_category; } // error_condition Index: libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp =================================================================== --- libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp +++ libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp @@ -27,6 +27,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; } Index: libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp =================================================================== --- libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp +++ libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp @@ -27,6 +27,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; } Index: libcxx/test/std/input.output/iostreams.base/std.ios.manip/error.reporting/iostream_category.pass.cpp =================================================================== --- libcxx/test/std/input.output/iostreams.base/std.ios.manip/error.reporting/iostream_category.pass.cpp +++ 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; } Index: libcxx/test/std/thread/futures/futures.errors/future_category.pass.cpp =================================================================== --- libcxx/test/std/thread/futures/futures.errors/future_category.pass.cpp +++ 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; }