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

Reply via email to