diff --git a/stl/inc/xlocnum b/stl/inc/xlocnum index afe27df46d..cb0ddec757 100644 --- a/stl/inc/xlocnum +++ b/stl/inc/xlocnum @@ -1371,10 +1371,13 @@ protected: } _Buf.resize(_Bufsize + 50); // add fudge factor + const bool _Is_finite = (_STD isfinite)(_Val); + const auto _Adjusted_flags = // TRANSITION, DevCom-10519861 + _Is_finite ? _Iosbase.flags() : _Iosbase.flags() & ~ios_base::showpoint; const auto _Ngen = static_cast(_CSTD sprintf_s( - &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 0, _Iosbase.flags()), static_cast(_Precision), _Val)); + &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 0, _Adjusted_flags), static_cast(_Precision), _Val)); - return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, (_STD isfinite)(_Val)); + return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, _Is_finite); } virtual _OutIt __CLR_OR_THIS_CALL do_put( @@ -1395,10 +1398,13 @@ protected: } _Buf.resize(_Bufsize + 50); // add fudge factor + const bool _Is_finite = (_STD isfinite)(_Val); + const auto _Adjusted_flags = // TRANSITION, DevCom-10519861 + _Is_finite ? _Iosbase.flags() : _Iosbase.flags() & ~ios_base::showpoint; const auto _Ngen = static_cast(_CSTD sprintf_s( - &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 'L', _Iosbase.flags()), static_cast(_Precision), _Val)); + &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 'L', _Adjusted_flags), static_cast(_Precision), _Val)); - return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, (_STD isfinite)(_Val)); + return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, _Is_finite); } #pragma warning(pop) diff --git a/tests/std/tests/GH_003867_output_nan/test.cpp b/tests/std/tests/GH_003867_output_nan/test.cpp index e36c6779fc..059ed13cca 100644 --- a/tests/std/tests/GH_003867_output_nan/test.cpp +++ b/tests/std/tests/GH_003867_output_nan/test.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include +#include #include #include #include @@ -54,8 +55,56 @@ void test_gh_3867() { #endif // TEST_CUSTOM_FACET } +// Also test GH-4210: With setprecision(0) showpoint fixed, a bogus '.' is emitted for infinity and NaN + +template +void test_output_nonfinite_value(const FloatingPoint x) { + const auto s1 = [x] { + ostringstream os; + os << setprecision(0) << showpoint << fixed; + os << x; + return os.str(); + }(); + const auto s2 = [x] { + ostringstream os; + os << setprecision(0) << noshowpoint << fixed; + os << x; + return os.str(); + }(); + assert(s1 == s2); + + const auto s3 = [x] { + ostringstream os; + os << setprecision(0) << showpoint << fixed << showpos; + os << x; + return os.str(); + }(); + const auto s4 = [x] { + ostringstream os; + os << setprecision(0) << noshowpoint << fixed << showpos; + os << x; + return os.str(); + }(); + assert(s3 == s4); +} + +template +void test_gh_4210() { + constexpr auto inf_val = numeric_limits::infinity(); + constexpr auto nan_val = numeric_limits::quiet_NaN(); + + test_output_nonfinite_value(inf_val); + test_output_nonfinite_value(-inf_val); + test_output_nonfinite_value(nan_val); + test_output_nonfinite_value(-nan_val); +} + int main() { test_gh_3867(); test_gh_3867(); test_gh_3867(); + + test_gh_4210(); + test_gh_4210(); + test_gh_4210(); }