[PATCH] D89360: Treat constant contexts as being in the default rounding mode.

Serge Pavlov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 15 07:34:22 PDT 2020


sepavloff added a comment.

In D89360#2330522 <https://reviews.llvm.org/D89360#2330522>, @rsmith wrote:

> In D89360#2329856 <https://reviews.llvm.org/D89360#2329856>, @sepavloff wrote:
>
>> I would propose to consider solution in D88498 <https://reviews.llvm.org/D88498>. It tries to fix the real reason of the malfunction - using dynamic rounding mode for evaluation of global variable initializers.
>
> That is not the real reason for the malfunction. If you narrowly look at C, you can convince yourself otherwise, but that's only because global variable initializers are the only place where we need to evaluate floating-point constant expressions in C. In C++, this problem affects all contexts where constant evaluation might happen (array bounds, bit-field widths, and a whole host of others).

You are right, the solution in D88498 <https://reviews.llvm.org/D88498> was more a workaround, as it was focused on initializers only. The updated version applies dynamic rounding to function bodies only, I hope it could solve the problem of other contexts.



================
Comment at: clang/test/SemaCXX/rounding-math.cpp:9
+
+constexpr int f(int n) { return int(n * (1.0 / 3.0)); }
+
----------------
rsmith wrote:
> rsmith wrote:
> > sepavloff wrote:
> > > This code requires additional solution. The function body is built using dynamic rounding mode, which breaks its constexprness. We can avoid this kind of errors if we assume that body of a constexpr function is parsed using constant rounding mode (in this example it is the default mode). It makes parsing constexpr function different from non-constexpr ones, but enables convenient use:
> > > ```
> > > constexpr int add(float x, float y) { return x + y; }
> > > 
> > > #pragma STDC FENV_ROUND FE_UPWARD
> > > int a2 = add(2.0F, 0x1.000002p0F);
> > > 
> > > #pragma STDC FENV_ROUND FE_DOWNWARD
> > > int a3 = add(2.0F, 0x1.000002p0F);
> > > ```
> > > If calls of constexpr functions are processes with FP options acting in the call site, a call to constexpr function becomes equivalent to execution of statements of its body.
> > I don't understand what you mean by "breaks its constexprness". Using a dynamic rounding mode for the body of the function is exactly what we want here. When the function is called in a manifestly constant evaluated context, we should use the default rounding mode, and when it's called at runtime, we use the appropriate dynamic rounding mode; if we try to constant evaluate it outside of a manifestly constant evaluated constant, we deem it non-constant.
> > 
> > When `constexpr` function is called at runtime, it's a completely normal function with normal semantics. It would be wrong to use the default rounding mode when parsing its body.
> To be clear: in your example with `add`, both `a2` and `a3` should be initialized to the same value, which should be rounded with the default rounding mode. Per ISO18661, `FENV_ROUND` only affects operations in its lexical scope, not functions called within those operations, and per the regular C++ rules, `constexpr` functions behave like regular functions, not like macros.
I incorrectly identified the reason why some call was rejected in constant evaluated context. Please ignore this statement. I am sorry.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89360/new/

https://reviews.llvm.org/D89360



More information about the cfe-commits mailing list