On Tue, 21 Sep 2021, Jason Merrill via Gcc-patches wrote:
On Tue, Sep 21, 2021 at 4:30 PM Joseph Myers <jos...@codesourcery.com>
wrote:
On Tue, 21 Sep 2021, Jakub Jelinek via Gcc-patches wrote:
On Tue, Sep 21, 2021 at 02:15:59PM +0100, Roger Sayle wrote:
Can you double check? Integer division by zero is undefined, but
isn't floating point
division by zero defined by the appropriate IEEE standards?
https://eel.is/c++draft/expr.mul#4 doesn't make the division by zero
behavior conditional on integral types.
C has similar wording.
The position for C is that Annex F semantics take precedence over all the
ways in which floating-point arithmetic has undefined behavior in the main
body of the standard. So floating-point overflow and division by zero are
fully defined in the presence of Annex F support, while out-of-range
conversions from floating point to integer types produce an unspecified
value (not necessarily the same unspecified value for different executions
of the conversion in the abstract machine - as discussed in bug 93806, GCC
can get that wrong and act as if a single execution of such a conversion
in the abstract machine produces more than one result).
In C, as specified in Annex F, initializers for floating-point objects
with static or thread storage duration are evaluated with exceptions
discarded and the default rounding mode in effect; 7.0 / 0.0 is a fully
valid initializer for such an object to initialize it to positive
infinity. As I understand it, the question for this thread is whether C++
constexpr should have a similar rule to C static initializers (which ought
to apply to 1.0 / 3.0, raising inexact, just as much as to 7.0 / 0.0).
The C rules seem to be
F.8.2 Translation
During translation the IEC 60559 default modes are in effect:
— The rounding direction mode is rounding to nearest.
— The rounding precision mode (if supported) is set so that results are
not shortened.
— Trapping or stopping (if supported) is disabled on all floating-point
exceptions.
Recommended practice:
The implementation should produce a diagnostic message for each
translation-time floating-point exception, other than “inexact”; the
implementation should then proceed with the translation of the program.
I think following the same rules for C++ would be appropriate in a
I agree that looking at the C standard is more interesting, C++ is very
bad at specifying anything float related.
diagnosing context: warn and continue. In a template argument deduction
(SFINAE) context, where errors become silent substitution failures, it's
probably better to treat them as non-constant.
I am trying to imagine a sfinae example affected by whether 1./0. is
constant. Does that mean A<0.,__builtin_inf()> would fail to use the
specialization in
template<double a,double d>struct A{};
template<double a>struct A<a,1/a>{};
? I don't like that, I believe it should use the specialization. With
ieee754, 1./0. is perfectly well defined as +inf, the only question is
whether it should also set a flag at runtime, which is not relevant in a
manifestly consteval context (fetestexcept, etc are not constexpr, that
should be enough to catch mistakes). If some user wants to forbid
FE_DIVBYZERO, FE_INEXACT, FE_INVALID, FE_OVERFLOW or FE_UNDERFLOW in
compile-time operations, that looks like it could be part of a separate
compiler flag or pragma, like C's FENV_ROUND can affect the rounding mode
in static initializers (of course C++ templates make pragmas less
convenient).
--
Marc Glisse