diff options
author | Jason Merrill <jason@redhat.com> | 2016-03-04 17:08:17 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-03-04 17:08:17 -0500 |
commit | 39dce2b7901008b0ba70387bb47a9a0d19bbe836 (patch) | |
tree | 7a6b28f37f7bbf989c2627fb453fe70b47529760 /gcc/cp | |
parent | 602045546463f33fb426f6f623ece65fb41b907e (diff) | |
download | gcc-39dce2b7901008b0ba70387bb47a9a0d19bbe836.zip gcc-39dce2b7901008b0ba70387bb47a9a0d19bbe836.tar.gz gcc-39dce2b7901008b0ba70387bb47a9a0d19bbe836.tar.bz2 |
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
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 27 |
2 files changed, 29 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0f23bd7..08c2518 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2016-03-04 Jason Merrill <jason@redhat.com> + * 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 5a81469..4fadc0f 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<tree,tree> *values; + /* SAVE_EXPRs that we've seen within the current LOOP_EXPR. NULL if we + aren't inside a loop. */ + hash_set<tree> *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<tree> 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<tree>::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<tree,tree> 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 <tree, tree> 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; |