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

Reply via email to