OK.
On Mon, Jul 18, 2016 at 5:07 PM, Jakub Jelinek <ja...@redhat.com> wrote: > On Mon, Jul 18, 2016 at 02:42:43PM -0400, Jason Merrill wrote: >> Ah, I guess we need to check cxx_dialect in cxx_eval_store_expression, >> not just in potential_constant_expression. > > Here is an updated version, bootstrapped/regtested on x86_64-linux and > i686-linux, ok for trunk? > > 2016-07-18 Jakub Jelinek <ja...@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. > > * g++.dg/cpp0x/constexpr-50060.C: New test. > * g++.dg/cpp1y/constexpr-50060.C: New test. > > --- gcc/cp/constexpr.c.jj 2016-07-18 20:42:51.163955883 +0200 > +++ gcc/cp/constexpr.c 2016-07-18 20:55:47.246152938 +0200 > @@ -1105,7 +1105,7 @@ cxx_eval_builtin_function_call (const co > 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 co > > 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 > --- gcc/testsuite/g++.dg/cpp0x/constexpr-50060.C.jj 2016-07-18 > 21:03:12.505532831 +0200 > +++ gcc/testsuite/g++.dg/cpp0x/constexpr-50060.C 2016-07-18 > 21:05:41.306655422 +0200 > @@ -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 } } } > --- gcc/testsuite/g++.dg/cpp1y/constexpr-50060.C.jj 2016-07-18 > 20:46:00.992553765 +0200 > +++ gcc/testsuite/g++.dg/cpp1y/constexpr-50060.C 2016-07-18 > 20:46:00.992553765 +0200 > @@ -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, ""); > > > Jakub