[gcc r11-2998] c++: Disable -frounding-math during manifestly constant evaluation [PR96862]

Jakub Jelinek jakub@gcc.gnu.org
Thu Sep 3 18:12:45 GMT 2020


https://gcc.gnu.org/g:6641d6d3fe79113f8d9f3ced355aea79bffda822

commit r11-2998-g6641d6d3fe79113f8d9f3ced355aea79bffda822
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Sep 3 20:11:43 2020 +0200

    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.

Diff:
---
 gcc/cp/constexpr.c                           |  2 ++
 gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C | 20 ++++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 8ee0f2abe1a..2a5051c7b43 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6680,6 +6680,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
 			allow_non_constant, strict,
 			manifestly_const_eval || !allow_non_constant };
 
+  /* Turn off -frounding-math for manifestly constant evaluation.  */
+  warning_sentinel rm (flag_rounding_math, ctx.manifestly_const_eval);
   tree type = initialized_type (t);
   tree r = t;
   bool is_consteval = false;
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C
new file mode 100644
index 00000000000..0b5c2e81bd1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C
@@ -0,0 +1,20 @@
+// PR c++/96862
+// { dg-do compile { target c++17 } }
+// { dg-additional-options "-frounding-math" }
+
+constexpr double a = 0x1.0p+100 + 0x1.0p-100;
+const double b = 0x1.0p+100 + 0x1.0p-100;
+const double &&c = 0x1.0p+100 + 0x1.0p-100;
+static_assert (0x1.0p+100 + 0x1.0p-100 == 0x1.0p+100, "");
+
+void
+foo ()
+{
+  constexpr double d = 0x1.0p+100 + 0x1.0p-100;
+  const double e = 0x1.0p+100 + 0x1.0p-100;
+  const double &&f = 0x1.0p+100 + 0x1.0p-100;
+  static_assert (0x1.0p+100 + 0x1.0p-100 == 0x1.0p+100, "");
+}
+
+const double &g = a;
+const double &h = b;


More information about the Gcc-cvs mailing list