3689. num_get overflow determination unclear and incorrect

Section: 28.3.4.3.2.3 [facet.num.get.virtuals] Status: New Submitter: Hubert Tong Opened: 2022-03-28 Last modified: 2022-05-17

Priority: 3

View other active issues in [facet.num.get.virtuals].

View all other issues in [facet.num.get.virtuals].

View all issues with New status.

Discussion:

28.3.4.3.2.3 [facet.num.get.virtuals] stage 3 specifies that "by the rules of" various strto* functions, sequences of chars are converted to a numeric value (producing the "converted value" that is referred to).

It then goes on to specify various error cases when the "field represents a value" that is outside the range of representable values. Clearly, the value that would be returned from the appropriate strto* function is not outside the range of representable values for long long, unsigned long long, float, double, and long double; therefore (unless if we expect no range-related errors for those types), the field "represents a value" other than the "converted value".

Issue 1: It is too subtle to have two distinct values without calling more attention to them by giving them names aside from the prose descriptions.

If the field "represents" a value other than the value that would be returned from the appropriate strto* function, then what value does the field "represent"? Note that, strictly speaking, it is the process that results in the converted value that the wording says is obtained "by the rules of" the strto* functions, which is not the same thing as saying that the value represented is interpreted "by the rules of" the strto* functions.

If the field "represents" the mathematical value, then for unsigned integer types, all negative values cannot be represented. This does not match existing practice.

If negative integer values are interpreted using the rules of the strto* functions by obtaining the magnitude and then having it "negated (in the return type)", then the return type of strtoull is unsigned long long, meaning (where unsigned long long is 64-bit) that "-18446744073709551615" is 1 (even when converting to unsigned integer types of less width). That does not match existing practice. It is also worth noting that negating in the return type does not work well if the magnitude is not representable as a positive value in the return type (e.g., for signed integer types and their most negative representable values).

Issue 2: The effect of the minus sign with respect to unsigned integer types can reasonably be interpreted in ways that do not match existing practice (and are presumably unintended). The interpretation that works better for unsigned long long does not work as well for signed long long.

If the field does not "represent" the mathematical value, then for floating-point types, it is unclear whether the minus sign takes effect before or after any possible rounding. For literals, the minus sign takes effect after rounding.

Issue 3: The effect of the minus sign with respect to floating-point types is unclear.

Lastly, for floating-point types with signed infinities, there are no finite values outside the range of representable values; therefore, conversions of all finite values to such types are specified to "succeed". That does not match existing implementation practice.

Issue 4: The conditions for identifying range-related errors for conversions to floating-point types do not match the conditions that constitute overflow for floating-point types. There is implementation divergence: libc++ appears to check for floating-point overflow; libstdc++ appears to check for infinities.

[2022-05-17; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution: