Commit 4cd3e7df by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/86524 (std::less with pointer arguments not usable in static_assert in…

re PR c++/86524 (std::less with pointer arguments not usable in static_assert in constexpr function)

	PR c++/86524
	PR c++/88446
	* cp-tree.h (cp_fold_maybe_rvalue, cp_fold_rvalue): Declare.
	(fold_non_dependent_expr): Add manifestly_const_eval argument.
	* constexpr.c (cxx_eval_builtin_function_call): Evaluate
	__builtin_constant_p if ctx->manifestly_const_eval even in constexpr
	functions.  Don't reuse dummy{1,2} vars between different arguments.
	Use cp_fold_rvalue instead of cp_fully_fold.  Fix comment typo.
	(fold_non_dependent_expr): Add manifestly_const_eval argument, pass
	it through to cxx_eval_outermost_constant_expr and
	maybe_constant_value.
	* cp-gimplify.c (cp_fold_maybe_rvalue, cp_fold_rvalue): No longer
	static.
	* semantics.c (finish_static_assert): Call fold_non_dependent_expr
	with true as manifestly_const_eval.

	* g++.dg/cpp1y/constexpr-86524.C: New test.
	* g++.dg/cpp2a/is-constant-evaluated4.C: New test.
	* g++.dg/cpp2a/is-constant-evaluated5.C: New test.
	* g++.dg/cpp2a/is-constant-evaluated6.C: New test.

From-SVN: r267341
parent dca00617
2018-12-21 Jakub Jelinek <jakub@redhat.com>
PR c++/86524
PR c++/88446
* cp-tree.h (cp_fold_maybe_rvalue, cp_fold_rvalue): Declare.
(fold_non_dependent_expr): Add manifestly_const_eval argument.
* constexpr.c (cxx_eval_builtin_function_call): Evaluate
__builtin_constant_p if ctx->manifestly_const_eval even in constexpr
functions. Don't reuse dummy{1,2} vars between different arguments.
Use cp_fold_rvalue instead of cp_fully_fold. Fix comment typo.
(fold_non_dependent_expr): Add manifestly_const_eval argument, pass
it through to cxx_eval_outermost_constant_expr and
maybe_constant_value.
* cp-gimplify.c (cp_fold_maybe_rvalue, cp_fold_rvalue): No longer
static.
* semantics.c (finish_static_assert): Call fold_non_dependent_expr
with true as manifestly_const_eval.
2018-12-20 Marek Polacek <polacek@redhat.com>
PR c++/88196 - ICE with class non-type template parameter.
......
......@@ -1197,7 +1197,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
/* If we aren't requiring a constant expression, defer __builtin_constant_p
in a constexpr function until we have values for the parameters. */
if (bi_const_p
&& ctx->quiet
&& !ctx->manifestly_const_eval
&& current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
{
......@@ -1222,7 +1222,6 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
return constant false for a non-constant argument. */
constexpr_ctx new_ctx = *ctx;
new_ctx.quiet = true;
bool dummy1 = false, dummy2 = false;
for (i = 0; i < nargs; ++i)
{
args[i] = CALL_EXPR_ARG (t, i);
......@@ -1231,12 +1230,16 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
of the builtin, verify it here. */
if (!builtin_valid_in_constant_expr_p (fun)
|| potential_constant_expression (args[i]))
args[i] = cxx_eval_constant_expression (&new_ctx, args[i], false,
&dummy1, &dummy2);
{
bool dummy1 = false, dummy2 = false;
args[i] = cxx_eval_constant_expression (&new_ctx, args[i], false,
&dummy1, &dummy2);
}
if (bi_const_p)
/* For __built_in_constant_p, fold all expressions with constant values
/* For __builtin_constant_p, fold all expressions with constant values
even if they aren't C++ constant-expressions. */
args[i] = cp_fully_fold (args[i]);
args[i] = cp_fold_rvalue (args[i]);
}
bool save_ffbcp = force_folding_builtin_constant_p;
......@@ -5340,6 +5343,7 @@ clear_cv_and_fold_caches (void)
(t, complain) followed by maybe_constant_value but is more efficient,
because it calls instantiation_dependent_expression_p and
potential_constant_expression at most once.
The manifestly_const_eval argument is passed to maybe_constant_value.
Callers should generally pass their active complain, or if they are in a
non-template, diagnosing context, they can use the default of
......@@ -5350,7 +5354,8 @@ clear_cv_and_fold_caches (void)
tree
fold_non_dependent_expr (tree t,
tsubst_flags_t complain /* = tf_warning_or_error */)
tsubst_flags_t complain /* = tf_warning_or_error */,
bool manifestly_const_eval /* = false */)
{
if (t == NULL_TREE)
return NULL_TREE;
......@@ -5380,7 +5385,8 @@ fold_non_dependent_expr (tree t,
return t;
}
tree r = cxx_eval_outermost_constant_expr (t, true, true, false,
tree r = cxx_eval_outermost_constant_expr (t, true, true,
manifestly_const_eval,
NULL_TREE);
/* cp_tree_equal looks through NOPs, so allow them. */
gcc_checking_assert (r == t
......@@ -5398,7 +5404,7 @@ fold_non_dependent_expr (tree t,
return t;
}
return maybe_constant_value (t);
return maybe_constant_value (t, NULL_TREE, manifestly_const_eval);
}
/* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather
......
......@@ -2118,7 +2118,7 @@ cxx_omp_disregard_value_expr (tree decl, bool shared)
/* Fold expression X which is used as an rvalue if RVAL is true. */
static tree
tree
cp_fold_maybe_rvalue (tree x, bool rval)
{
while (true)
......@@ -2141,7 +2141,7 @@ cp_fold_maybe_rvalue (tree x, bool rval)
/* Fold expression X which is used as an rvalue. */
static tree
tree
cp_fold_rvalue (tree x)
{
return cp_fold_maybe_rvalue (x, true);
......
......@@ -7543,6 +7543,8 @@ extern void cxx_omp_finish_clause (tree, gimple_seq *);
extern bool cxx_omp_privatize_by_reference (const_tree);
extern bool cxx_omp_disregard_value_expr (tree, bool);
extern void cp_fold_function (tree);
extern tree cp_fold_maybe_rvalue (tree, bool);
extern tree cp_fold_rvalue (tree);
extern tree cp_fully_fold (tree);
extern tree cp_fully_fold_init (tree);
extern void clear_fold_cache (void);
......@@ -7668,7 +7670,9 @@ extern tree cxx_constant_value (tree, tree = NULL_TREE);
extern tree cxx_constant_init (tree, tree = NULL_TREE);
extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error);
extern tree fold_non_dependent_expr (tree,
tsubst_flags_t = tf_warning_or_error,
bool = false);
extern tree fold_simple (tree);
extern bool is_sub_constant_expr (tree);
extern bool reduced_constant_expression_p (tree);
......
......@@ -9225,7 +9225,8 @@ finish_static_assert (tree condition, tree message, location_t location,
/* Fold the expression and convert it to a boolean value. */
condition = perform_implicit_conversion_flags (boolean_type_node, condition,
complain, LOOKUP_NORMAL);
condition = fold_non_dependent_expr (condition, complain);
condition = fold_non_dependent_expr (condition, complain,
/*manifestly_const_eval=*/true);
if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
/* Do nothing; the condition is satisfied. */
......
2018-12-21 Jakub Jelinek <jakub@redhat.com>
PR c++/86524
PR c++/88446
* g++.dg/cpp1y/constexpr-86524.C: New test.
* g++.dg/cpp2a/is-constant-evaluated4.C: New test.
* g++.dg/cpp2a/is-constant-evaluated5.C: New test.
* g++.dg/cpp2a/is-constant-evaluated6.C: New test.
PR middle-end/85594
PR middle-end/88553
* gcc.dg/gomp/pr85594.c: New test.
......
// PR c++/86524
// { dg-do run { target c++14 } }
// { dg-options "-O2" }
extern "C" void abort ();
typedef __UINTPTR_TYPE__ uintptr_t;
constexpr bool
foo (const int *x, const int *y)
{
if (__builtin_constant_p (x < y))
return x < y;
return (uintptr_t) x < (uintptr_t) y;
}
void
bar ()
{
constexpr int x = 0;
static_assert (!(&x < &x));
static_assert (!foo (&x, &x));
}
constexpr void
baz ()
{
constexpr int x = 0;
static_assert (!(&x < &x));
static_assert (!foo (&x, &x));
}
int i, j;
int
main ()
{
bar ();
baz ();
if (!(foo (&i, &j) ^ foo (&j, &i)))
abort ();
}
// P0595R2
// { dg-do compile { target c++14 } }
namespace std {
constexpr inline bool
is_constant_evaluated () noexcept
{
return __builtin_is_constant_evaluated ();
}
}
constexpr int
foo () noexcept
{
return std::is_constant_evaluated () ? 5 : 12;
}
static_assert (std::is_constant_evaluated (), "");
static_assert (foo () == 5, "");
// PR c++/86524
// { dg-do run { target c++14 } }
// { dg-options "-O2" }
extern "C" void abort ();
typedef __UINTPTR_TYPE__ uintptr_t;
constexpr bool
foo (const int *x, const int *y)
{
if (__builtin_is_constant_evaluated ())
return x < y;
return (uintptr_t) x < (uintptr_t) y;
}
void
bar ()
{
constexpr int x = 0;
static_assert (!(&x < &x));
static_assert (!foo (&x, &x));
}
constexpr void
baz ()
{
constexpr int x = 0;
static_assert (!(&x < &x));
static_assert (!foo (&x, &x));
}
int i, j;
int
main ()
{
bar ();
baz ();
if (!(foo (&i, &j) ^ foo (&j, &i)))
abort ();
}
// P0595R2
// { dg-do compile { target c++14 } }
namespace std {
constexpr inline bool
is_constant_evaluated () noexcept
{
return __builtin_is_constant_evaluated ();
}
}
int a;
constexpr bool
foo (int x)
{
return __builtin_constant_p (x);
}
constexpr bool
bar (int x)
{
return __builtin_constant_p (x + a);
}
static_assert (__builtin_constant_p (0) + 2 * std::is_constant_evaluated () == 3, "");
static_assert (__builtin_constant_p (a) + 2 * std::is_constant_evaluated () == 2, "");
static_assert (foo (0) + 2 * std::is_constant_evaluated () == 3, "");
static_assert (bar (0) + 2 * std::is_constant_evaluated () == 2, "");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment