sepavloff added inline comments.

================
Comment at: clang/lib/Parse/ParseDecl.cpp:2290
+          // rounding mode.
+          if (VD->isFileVarDecl() || VD->isConstexpr() ||
+              (!getLangOpts().CPlusPlus && VD->isStaticLocal())) {
----------------
rsmith wrote:
> It's far from clear to me that this is correct in C++. In principle, for a 
> dynamic initializer, the rounding mode could have been set by an earlier 
> initializer.
> 
> Perhaps we can make an argument that, due to the permission to interleave 
> initializers from different TUs, every dynamic initializer must leave the 
> program in the default rounding mode, but I don't think even that makes this 
> approach correct, because an initializer could do this:
> 
> ```
> double d;
> double e = (fesetround(...), d = some calculation, fesetround(...default...), 
> d);
> ```
> 
> I think we can only do this in C and will need something different for C++.
> 
> (I think this also has problems in C++ due to constexpr functions: it's not 
> the case that all floating point operations that will be evaluated as part of 
> the initializer lexically appear within it.)
I changed the code to confine it with C and constexpr only. Hopefully this 
would be enough to enable build of SPECS attempted by @mibintc 
(https://reviews.llvm.org/D87528#2295015). However in long-term perspective we 
should return to this code.

The intent was to align behavior of C and C++. If an initializer is valid in C, 
then it should produce the same code in C++. If the source code like
```
float appx_coeffs_fp32[3 * 256] = {
    SEGMENT_BIAS + 1.4426950216,
…
```
produces compact table in C mode and huge initialization code in C++, it would 
be strange from user viewpoint and would not give any advantage.

C in C2x presents pretty consistent model, provided that `#pragma STDC 
FENV_ROUND FE_DYNAMIC` does not set constant rounding mode. Initializers for 
variables with static allocation are always evaluated in constant rounding mode 
and user can chose the mode using pragma FENV_ROUND.

When extending this model to C++ we must solve the problem of dynamic 
initialization. It obviously occurs in runtime rounding mode, so changing 
between static and dynamic initialization may change semantics. If however 
dynamic initialization of global variable occurs in constant rounding mode 
(changing FP control modes in initializers without restoring them is UB), 
static and dynamic initialization would be semantically equivalent.

We cannot apply the same rule to local static variables, as they are treated 
differently in C and C++. So the code:
```
float func_01(float x) {
  #pragma STDC FENV_ACCESS ON
  static float val = 1.0/3.0;
  return val;
}
```
Would be compiled differently in C and C++.



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88498

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to