From 39dce2b7901008b0ba70387bb47a9a0d19bbe836 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 4 Mar 2016 17:08:17 -0500 Subject: [PATCH] Fix constexpr handling of SAVE_EXPR in loops. * constexpr.c (struct constexpr_ctx): Add save_exprs field. (cxx_eval_loop_expr): Discard SAVE_EXPR values before looping. (cxx_eval_constant_expression) [SAVE_EXPR]: Add it to the set. (cxx_eval_outermost_constant_expr, is_sub_constant_expr): Initialize. From-SVN: r233981 --- gcc/cp/ChangeLog | 5 ++++ gcc/cp/constexpr.c | 27 +++++++++++++++++--- gcc/testsuite/g++.dg/cpp1y/constexpr-loop3.C | 23 +++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-loop3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0f23bd770b7..08c25189649 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2016-03-04 Jason Merrill + * constexpr.c (struct constexpr_ctx): Add save_exprs field. + (cxx_eval_loop_expr): Discard SAVE_EXPR values before looping. + (cxx_eval_constant_expression) [SAVE_EXPR]: Add it to the set. + (cxx_eval_outermost_constant_expr, is_sub_constant_expr): Initialize. + PR c++/70067 * tree.c (strip_typedefs): Handle TYPENAME_TYPE lookup finding the same type. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 5a81469b8ad..4fadc0fd507 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -897,6 +897,9 @@ struct constexpr_ctx { /* Values for any temporaries or local variables within the constant-expression. */ hash_map *values; + /* SAVE_EXPRs that we've seen within the current LOOP_EXPR. NULL if we + aren't inside a loop. */ + hash_set *save_exprs; /* The CONSTRUCTOR we're currently building up for an aggregate initializer. */ tree ctor; @@ -3161,16 +3164,27 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, bool *overflow_p, tree *jump_target) { + constexpr_ctx new_ctx = *ctx; + tree body = TREE_OPERAND (t, 0); while (true) { - cxx_eval_statement_list (ctx, body, + hash_set save_exprs; + new_ctx.save_exprs = &save_exprs; + + cxx_eval_statement_list (&new_ctx, body, non_constant_p, overflow_p, jump_target); if (returns (jump_target) || breaks (jump_target) || *non_constant_p) break; + + /* Forget saved values of SAVE_EXPRs. */ + for (hash_set::iterator iter = save_exprs.begin(); + iter != save_exprs.end(); ++iter) + new_ctx.values->remove (*iter); } if (breaks (jump_target)) *jump_target = NULL_TREE; + return NULL_TREE; } @@ -3452,6 +3466,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, non_constant_p, overflow_p); ctx->values->put (t, r); + if (ctx->save_exprs) + ctx->save_exprs->add (t); } break; @@ -3875,7 +3891,10 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, bool non_constant_p = false; bool overflow_p = false; hash_map map; - constexpr_ctx ctx = { NULL, &map, NULL, NULL, allow_non_constant, strict }; + + constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, + allow_non_constant, strict }; + tree type = initialized_type (t); tree r = t; if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)) @@ -3983,7 +4002,9 @@ is_sub_constant_expr (tree t) bool non_constant_p = false; bool overflow_p = false; hash_map map; - constexpr_ctx ctx = { NULL, &map, NULL, NULL, true, true }; + + constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, true, true }; + cxx_eval_constant_expression (&ctx, t, false, &non_constant_p, &overflow_p); return !non_constant_p && !overflow_p; diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-loop3.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-loop3.C new file mode 100644 index 00000000000..5e7c3c97dc2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-loop3.C @@ -0,0 +1,23 @@ +// { dg-do compile { target c++14 } } + +struct A +{ + int i; +}; + +constexpr bool f() +{ + A ar[4] = { 1, 2, 3, 4 }; + A *ap = ar; + int i = 0; + do + *ap++ = A{i}; + while (++i < 3); + return (ar[0].i == 0 + && ar[1].i == 1 + && ar[2].i == 2 + && ar[3].i == 4); +} + +#define SA(X) static_assert((X),#X) +SA(f()); -- 2.30.2