diff --git a/stl/inc/xlocnum b/stl/inc/xlocnum index a14c070a63..1bc6413b0d 100644 --- a/stl/inc/xlocnum +++ b/stl/inc/xlocnum @@ -1376,7 +1376,7 @@ protected: const auto _Ngen = static_cast(_CSTD sprintf_s( &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 0, _Iosbase.flags()), static_cast(_Precision), _Val)); - return _Fput_v2(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, (_STD isnan)(_Val)); + return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, (_STD isfinite)(_Val)); } virtual _OutIt __CLR_OR_THIS_CALL do_put( @@ -1400,7 +1400,7 @@ protected: const auto _Ngen = static_cast(_CSTD sprintf_s( &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 'L', _Iosbase.flags()), static_cast(_Precision), _Val)); - return _Fput_v2(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, (_STD isnan)(_Val)); + return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, (_STD isfinite)(_Val)); } #pragma warning(pop) @@ -1463,12 +1463,12 @@ private: _OutIt __CLRCALL_OR_CDECL _Fput(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const char* _Buf, size_t _Count) const { // TRANSITION, ABI: preserved for binary compatibility - return _Fput_v2(_Dest, _Iosbase, _Fill, _Buf, _Count, false); + return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf, _Count, true); } template // TRANSITION, ABI - _OutIt _Fput_v2(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const char* _Buf, size_t _Count, - bool _Is_nan_val) const { // put formatted floating-point to _Dest + _OutIt _Fput_v3(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const char* _Buf, size_t _Count, + bool _Is_finite_val) const { // put formatted floating-point to _Dest auto _Prefix = static_cast(0 < _Count && (*_Buf == '+' || *_Buf == '-')); const char* _Exps; if ((_Iosbase.flags() & ios_base::floatfield) != ios_base::hexfloat) { @@ -1497,7 +1497,7 @@ private: _Groupstring[_Poff] = _Punct_fac.decimal_point(); } - if (!_Is_nan_val) { + if (_Is_finite_val) { size_t _Off = _Poff == _Count ? _Eoff : _Poff; const char* _Pg = &_Grouping[0]; while (*_Pg != CHAR_MAX && '\0' < *_Pg && static_cast(*_Pg) < _Off - _Prefix) { diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 224f1ffeca..7b912c8a6b 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -775,7 +775,6 @@ std/localization/locale.categories/category.monetary/locale.money.put/locale.mon std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_string_en_US.pass.cpp FAIL std/localization/locale.categories/category.monetary/locale.moneypunct/locale.moneypunct.members/decimal_point.pass.cpp FAIL std/localization/locale.categories/category.monetary/locale.moneypunct/locale.moneypunct.members/thousands_sep.pass.cpp FAIL -std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp FAIL std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_monthname_wide.pass.cpp FAIL std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_monthname.pass.cpp FAIL std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_one.pass.cpp FAIL diff --git a/tests/std/tests/Dev11_0496153_locale_ctor/test.cpp b/tests/std/tests/Dev11_0496153_locale_ctor/test.cpp index c7ac08d39e..73659075e5 100644 --- a/tests/std/tests/Dev11_0496153_locale_ctor/test.cpp +++ b/tests/std/tests/Dev11_0496153_locale_ctor/test.cpp @@ -10,16 +10,23 @@ using namespace std; -// The following monstrosity avoids activating the test code for _DLL compiles -// that use a non-default value of _ITERATOR_DEBUG_LEVEL (_ITERATOR_DEBUG_LEVEL -// defaults to "0" for release builds and "2" for _DEBUG). -#if defined(_DLL) && (_ITERATOR_DEBUG_LEVEL == 1 || (defined(_DEBUG) != (_ITERATOR_DEBUG_LEVEL == 2))) -#define ENABLE_TEST 0 +// Because std::string crosses the DLL boundary via overridden virtual functions, +// we can test custom facets only when: +// * linking statically, or +// * linking dynamically with IDL set to its default value (so the user code and the DLL match). +#ifdef _DEBUG +#define DEFAULT_IDL 2 #else -#define ENABLE_TEST 1 -#endif // defined(_DLL) && (_ITERATOR_DEBUG_LEVEL == 1 || (defined(_DEBUG) != (_ITERATOR_DEBUG_LEVEL == 2))) +#define DEFAULT_IDL 0 +#endif -#if ENABLE_TEST +#if !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL +#define TEST_CUSTOM_FACET 1 +#else +#define TEST_CUSTOM_FACET 0 +#endif + +#if TEST_CUSTOM_FACET void test_Dev11_496153_locale_ctor_should_not_throw() noexcept { const locale loc(setlocale(LC_ALL, nullptr)); @@ -39,11 +46,11 @@ void test_VSO_159700_locale_should_support_user_defined_facets() { str << 1.5f; assert("locale didn't support user-defined facets" && str.str() == "1,5"); } -#endif // ENABLE_TEST +#endif // TEST_CUSTOM_FACET int main() { -#if ENABLE_TEST +#if TEST_CUSTOM_FACET test_Dev11_496153_locale_ctor_should_not_throw(); test_VSO_159700_locale_should_support_user_defined_facets(); -#endif // ENABLE_TEST +#endif // TEST_CUSTOM_FACET } diff --git a/tests/std/tests/GH_003867_output_nan/test.cpp b/tests/std/tests/GH_003867_output_nan/test.cpp index a0c56d286a..e36c6779fc 100644 --- a/tests/std/tests/GH_003867_output_nan/test.cpp +++ b/tests/std/tests/GH_003867_output_nan/test.cpp @@ -5,16 +5,53 @@ #include #include #include +#include using namespace std; +// Because std::string crosses the DLL boundary via overridden virtual functions, +// we can test custom facets only when: +// * linking statically, or +// * linking dynamically with IDL set to its default value (so the user code and the DLL match). +#ifdef _DEBUG +#define DEFAULT_IDL 2 +#else +#define DEFAULT_IDL 0 +#endif + +#if !defined(_DLL) || _ITERATOR_DEBUG_LEVEL == DEFAULT_IDL +#define TEST_CUSTOM_FACET 1 +#else +#define TEST_CUSTOM_FACET 0 +#endif + +#if TEST_CUSTOM_FACET +struct groups_of_1 : numpunct { + // The standard char specialization of std::numpunct::do_thousands_sep returns ',' + string do_grouping() const override { + return "\1"; + } // groups of 1 digit +}; +#endif // TEST_CUSTOM_FACET + template void test_gh_3867() { // GH-3867 Writing NaN to the output stream with a set locale results in a weird output - ostringstream s; - s.imbue(locale("en-US")); - s << -numeric_limits::quiet_NaN(); - assert(s.str() == "-nan(ind)"); + { + ostringstream s; + s.imbue(locale("en-US")); + s << -numeric_limits::quiet_NaN(); + assert(s.str() == "-nan(ind)"); + } + +#if TEST_CUSTOM_FACET + { + ostringstream s; + s.imbue(locale(s.getloc(), new groups_of_1)); + s << -numeric_limits::infinity(); + assert(s.str() == "-inf"); + } +#endif // TEST_CUSTOM_FACET } int main() {