re PR middle-end/50060 (intrinsics not folded by the middle-end)
authorJakub Jelinek <jakub@redhat.com>
Wed, 20 Jul 2016 14:00:02 +0000 (16:00 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 20 Jul 2016 14:00:02 +0000 (16:00 +0200)
PR c++/50060
* constexpr.c (cxx_eval_builtin_function_call): Pass false as lval
when evaluating call arguments.  Use fold_builtin_call_array instead
of fold_build_call_array_loc, return t if it returns NULL.  Otherwise
check the result with potential_constant_expression and call
cxx_eval_constant_expression on it.

* g++.dg/cpp0x/constexpr-50060.C: New test.
* g++.dg/cpp1y/constexpr-50060.C: New test.

From-SVN: r238520

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-50060.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-50060.C [new file with mode: 0644]

index 417cb82b3ee9683e63852d3421dfbc14311266c2..7b9032022e0a347f0e8bb1ac982cb4d0b02b7fc1 100644 (file)
@@ -1,3 +1,12 @@
+2016-07-20  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/50060
+       * constexpr.c (cxx_eval_builtin_function_call): Pass false as lval
+       when evaluating call arguments.  Use fold_builtin_call_array instead
+       of fold_build_call_array_loc, return t if it returns NULL.  Otherwise
+       check the result with potential_constant_expression and call
+       cxx_eval_constant_expression on it.
+
 2016-07-19  Jason Merrill  <jason@redhat.com>
 
        PR c++/67164
index 91d14a55b4ff0c6b7c7789d167a3d08e9c5490dc..346fdfad90868234c3e8a5a6086dac44cb18b305 100644 (file)
@@ -1105,7 +1105,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
   for (i = 0; i < nargs; ++i)
     {
       args[i] = cxx_eval_constant_expression (&new_ctx, CALL_EXPR_ARG (t, i),
-                                             lval, &dummy1, &dummy2);
+                                             false, &dummy1, &dummy2);
       if (bi_const_p)
        /* For __built_in_constant_p, fold all expressions with constant values
           even if they aren't C++ constant-expressions.  */
@@ -1114,13 +1114,31 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
 
   bool save_ffbcp = force_folding_builtin_constant_p;
   force_folding_builtin_constant_p = true;
-  new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
-                                       CALL_EXPR_FN (t), nargs, args);
-  /* Fold away the NOP_EXPR from fold_builtin_n.  */
-  new_call = fold (new_call);
+  new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t),
+                                     CALL_EXPR_FN (t), nargs, args);
   force_folding_builtin_constant_p = save_ffbcp;
-  VERIFY_CONSTANT (new_call);
-  return new_call;
+  if (new_call == NULL)
+    {
+      if (!*non_constant_p && !ctx->quiet)
+       {
+         new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
+                                          CALL_EXPR_FN (t), nargs, args);
+         error ("%q+E is not a constant expression", new_call);
+       }
+      *non_constant_p = true;
+      return t;
+    }
+
+  if (!potential_constant_expression (new_call))
+    {
+      if (!*non_constant_p && !ctx->quiet)
+       error ("%q+E is not a constant expression", new_call);
+      *non_constant_p = true;
+      return t;
+    }
+
+  return cxx_eval_constant_expression (&new_ctx, new_call, lval,
+                                      non_constant_p, overflow_p);
 }
 
 /* TEMP is the constant value of a temporary object of type TYPE.  Adjust
index 41b09e268db30f879e23c3edcd3d1132dfe097ba..41042eb2aa89f1fbe62067a40ecd1721151e00d1 100644 (file)
@@ -1,3 +1,9 @@
+2016-07-20  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/50060
+       * g++.dg/cpp0x/constexpr-50060.C: New test.
+       * g++.dg/cpp1y/constexpr-50060.C: New test.
+
 2016-07-20  Martin Liska  <mliska@suse.cz>
 
        * gfortran.dg/graphite/pr71898.f90: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-50060.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-50060.C
new file mode 100644 (file)
index 0000000..ee1c221
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/50060
+// { dg-do compile { target c++11 } }
+
+extern "C" double frexp (double, int *);
+
+struct S
+{
+  constexpr S (double a) : y {}, x (frexp (a, &y)) {}  // { dg-error "is not a constant expression" "S" { target { ! c++14 } } }
+  double x;
+  int y;
+};
+
+struct T
+{
+  constexpr T (double a) : y {}, x ((y = 1, 0.8125)) {}        // { dg-error "is not a constant-expression" "T" { target { ! c++14 } } }
+  double x;
+  int y;
+};
+
+static_assert (S (6.5).x == 0.8125, "");       // { dg-error "non-constant condition for static assertion|in constexpr expansion" "" { target { ! c++14 } } }
+static_assert (T (6.5).x == 0.8125, "");       // { dg-error "non-constant condition for static assertion|called in a constant expression" "" { target { ! c++14 } } }
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-50060.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-50060.C
new file mode 100644 (file)
index 0000000..4ac27a3
--- /dev/null
@@ -0,0 +1,100 @@
+// PR c++/50060
+// { dg-do compile { target c++14 } }
+
+// sincos and lgamma_r aren't available in -std=c++14,
+// only in -std=gnu++14.  Use __builtin_* in that case.
+extern "C" void sincos (double, double *, double *);
+extern "C" double frexp (double, int *);
+extern "C" double modf (double, double *);
+extern "C" double remquo (double, double, int *);
+extern "C" double lgamma_r (double, int *);
+
+constexpr double
+f0 (double x)
+{
+  double y {};
+  double z {};
+  __builtin_sincos (x, &y, &z);
+  return y;
+}
+
+constexpr double
+f1 (double x)
+{
+  double y {};
+  double z {};
+  __builtin_sincos (x, &y, &z);
+  return z;
+}
+
+constexpr double
+f2 (double x)
+{
+  int y {};
+  return frexp (x, &y);
+}
+
+constexpr int
+f3 (double x)
+{
+  int y {};
+  frexp (x, &y);
+  return y;
+}
+
+constexpr double
+f4 (double x)
+{
+  double y {};
+  return modf (x, &y);
+}
+
+constexpr double
+f5 (double x)
+{
+  double y {};
+  modf (x, &y);
+  return y;
+}
+
+constexpr double
+f6 (double x, double y)
+{
+  int z {};
+  return remquo (x, y, &z);
+}
+
+constexpr int
+f7 (double x, double y)
+{
+  int z {};
+  remquo (x, y, &z);
+  return z;
+}
+
+constexpr double
+f8 (double x)
+{
+  int y {};
+  return __builtin_lgamma_r (x, &y);
+}
+
+constexpr int
+f9 (double x)
+{
+  int y {};
+  __builtin_lgamma_r (x, &y);
+  return y;
+}
+
+static_assert (f0 (0.0) == 0.0, "");
+static_assert (f1 (0.0) == 1.0, "");
+static_assert (f2 (6.5) == 0.8125, "");
+static_assert (f3 (6.5) == 3, "");
+static_assert (f4 (-7.25) == -0.25, "");
+static_assert (f5 (-7.25) == -7.0, "");
+static_assert (f6 (3.0, 2.0) == -1.0, "");
+static_assert (f7 (3.0, 2.0) == 2, "");
+static_assert (f8 (0.75) >= 0.20 && f8 (0.75) <= 0.21, "");
+static_assert (f8 (0.75) >= 0.20 && f8 (0.75) <= 0.21, "");
+static_assert (f9 (0.75) == 1, "");