c++: Disable -frounding-math during manifestly constant evaluation [PR96862]
authorJakub Jelinek <jakub@redhat.com>
Thu, 3 Sep 2020 18:11:43 +0000 (20:11 +0200)
committerJakub Jelinek <jakub@redhat.com>
Thu, 3 Sep 2020 18:11:43 +0000 (20:11 +0200)
commit6641d6d3fe79113f8d9f3ced355aea79bffda822
tree17816f5c34c8176c1c30bf7eb28180e5c36c9d83
parent032a4b42cc5f2105f622690ce2552f1c30e1d227
c++: Disable -frounding-math during manifestly constant evaluation [PR96862]

As discussed in the PR, fold-const.c punts on floating point constant
evaluation if the result is inexact and -frounding-math is turned on.
      /* Don't constant fold this floating point operation if the
         result may dependent upon the run-time rounding mode and
         flag_rounding_math is set, or if GCC's software emulation
         is unable to accurately represent the result.  */
      if ((flag_rounding_math
           || (MODE_COMPOSITE_P (mode) && !flag_unsafe_math_optimizations))
          && (inexact || !real_identical (&result, &value)))
        return NULL_TREE;
Jonathan said that we should be evaluating them anyway, e.g. conceptually
as if they are done with the default rounding mode before user had a chance
to change that, and e.g. in C in initializers it is also ignored.
In fact, fold-const.c for C initializers turns off various other options:

/* Perform constant folding and related simplification of initializer
   expression EXPR.  These behave identically to "fold_buildN" but ignore
   potential run-time traps and exceptions that fold must preserve.  */

  int saved_signaling_nans = flag_signaling_nans;\
  int saved_trapping_math = flag_trapping_math;\
  int saved_rounding_math = flag_rounding_math;\
  int saved_trapv = flag_trapv;\
  int saved_folding_initializer = folding_initializer;\
  flag_signaling_nans = 0;\
  flag_trapping_math = 0;\
  flag_rounding_math = 0;\
  flag_trapv = 0;\
  folding_initializer = 1;

  flag_signaling_nans = saved_signaling_nans;\
  flag_trapping_math = saved_trapping_math;\
  flag_rounding_math = saved_rounding_math;\
  flag_trapv = saved_trapv;\
  folding_initializer = saved_folding_initializer;

So, shall cxx_eval_outermost_constant_expr instead turn off all those
options (then warning_sentinel wouldn't be the right thing to use, but given
the 8 or how many return stmts in cxx_eval_outermost_constant_expr, we'd
need a RAII class for this.  Not sure about the folding_initializer, that
one is affecting complex multiplication and division constant evaluation
somehow.

2020-09-03  Jakub Jelinek  <jakub@redhat.com>

PR c++/96862
* constexpr.c (cxx_eval_outermost_constant_expr): Temporarily disable
flag_rounding_math during manifestly constant evaluation.

* g++.dg/cpp1z/constexpr-96862.C: New test.
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C [new file with mode: 0644]