[4/6] libstdc++: Adjust fast_float's over/underflow behavior for conformnace

Message ID 20220116180652.3694791-4-ppalka@redhat.com
State Committed
Headers
Series [1/6,v2] libstdc++: Directly implement hexfloat std::from_chars for binary32/64 |

Commit Message

Patrick Palka Jan. 16, 2022, 6:06 p.m. UTC
  This makes fast_float handle the situation where std::from_chars is
specified to return result_out_of_range, i.e. when the parsed value
is outside the representable range of the floating-point type.

This adjusts fast_float's behavior in case of over/underflow: instead of
returning errc{} and setting value to +-0 or +-infinity, return
result_out_of_range and don't modify value, as per [charconv.from.chars]/1.

libstdc++-v3/ChangeLog:

	* src/c++17/fast_float/LOCAL_PATCHES: Update.
	* src/c++17/fast_float/fast_float.h (from_chars_advanced): In
	case of over/underflow, return errc::result_out_of_range and don't
	modify 'value'.
---
 libstdc++-v3/src/c++17/fast_float/LOCAL_PATCHES | 1 +
 libstdc++-v3/src/c++17/fast_float/fast_float.h  | 9 +++++++++
 2 files changed, 10 insertions(+)
  

Comments

Jonathan Wakely Jan. 17, 2022, 10:49 a.m. UTC | #1
On Sun, 16 Jan 2022 at 18:12, Patrick Palka via Libstdc++ <
libstdc++@gcc.gnu.org> wrote:

> This makes fast_float handle the situation where std::from_chars is
> specified to return result_out_of_range, i.e. when the parsed value
> is outside the representable range of the floating-point type.
>
> This adjusts fast_float's behavior in case of over/underflow: instead of
> returning errc{} and setting value to +-0 or +-infinity, return
> result_out_of_range and don't modify value, as per [charconv.from.chars]/1.
>
> libstdc++-v3/ChangeLog:
>
>         * src/c++17/fast_float/LOCAL_PATCHES: Update.
>         * src/c++17/fast_float/fast_float.h (from_chars_advanced): In
>         case of over/underflow, return errc::result_out_of_range and don't
>         modify 'value'.
>
>
Typo in the commit summary line "conformnace".

OK for trunk.

Please report this as an issue to the upstream project, if you didn't
already (and if they haven't documented this as an intentional deviation
from the standard).
  
Patrick Palka Jan. 17, 2022, 8:05 p.m. UTC | #2
On Mon, Jan 17, 2022 at 5:49 AM Jonathan Wakely <jwakely@redhat.com> wrote:
>
>
>
> On Sun, 16 Jan 2022 at 18:12, Patrick Palka via Libstdc++ <libstdc++@gcc.gnu.org> wrote:
>>
>> This makes fast_float handle the situation where std::from_chars is
>> specified to return result_out_of_range, i.e. when the parsed value
>> is outside the representable range of the floating-point type.
>>
>> This adjusts fast_float's behavior in case of over/underflow: instead of
>> returning errc{} and setting value to +-0 or +-infinity, return
>> result_out_of_range and don't modify value, as per [charconv.from.chars]/1.
>>
>> libstdc++-v3/ChangeLog:
>>
>>         * src/c++17/fast_float/LOCAL_PATCHES: Update.
>>         * src/c++17/fast_float/fast_float.h (from_chars_advanced): In
>>         case of over/underflow, return errc::result_out_of_range and don't
>>         modify 'value'.
>>
>
> Typo in the commit summary line "conformnace".
>
> OK for trunk.
>
> Please report this as an issue to the upstream project, if you didn't already (and if they haven't documented this as an intentional deviation from the standard).

This behavior difference isn't documented AFAICT, so I reported the
issue upstream at https://github.com/fastfloat/fast_float/issues/120
  

Patch

diff --git a/libstdc++-v3/src/c++17/fast_float/LOCAL_PATCHES b/libstdc++-v3/src/c++17/fast_float/LOCAL_PATCHES
index e9d7bba6195..1f90f9d1d85 100644
--- a/libstdc++-v3/src/c++17/fast_float/LOCAL_PATCHES
+++ b/libstdc++-v3/src/c++17/fast_float/LOCAL_PATCHES
@@ -1 +1,2 @@ 
 r12-????
+r12-????
diff --git a/libstdc++-v3/src/c++17/fast_float/fast_float.h b/libstdc++-v3/src/c++17/fast_float/fast_float.h
index c908719ec3a..97d28940944 100644
--- a/libstdc++-v3/src/c++17/fast_float/fast_float.h
+++ b/libstdc++-v3/src/c++17/fast_float/fast_float.h
@@ -2884,6 +2884,15 @@  from_chars_result from_chars_advanced(const char *first, const char *last,
   // If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa) and we have an invalid power (am.power2 < 0),
   // then we need to go the long way around again. This is very uncommon.
   if(am.power2 < 0) { am = digit_comp<T>(pns, am); }
+
+  if((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || am.power2 == binary_format<T>::infinite_power()) {
+    // In case of over/underflow, return result_out_of_range and don't modify value,
+    // as per [charconv.from.chars]/1.  Note that LWG 3081 wants to modify value in
+    // this case too.
+    answer.ec = std::errc::result_out_of_range;
+    return answer;
+  }
+
   to_float(pns.negative, am, value);
   return answer;
 }