diff options
author | Jason Merrill <jason@redhat.com> | 2019-06-18 12:08:29 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2019-06-18 12:08:29 -0400 |
commit | d0aa42d276497d762934da72d7ad6d3d4b5551fc (patch) | |
tree | 19dfd17c9aa5d02407078e9c1bc4455940fd9676 | |
parent | 043666e0955d64ed538f2a5511f9fdc5484b657a (diff) | |
download | gcc-d0aa42d276497d762934da72d7ad6d3d4b5551fc.zip gcc-d0aa42d276497d762934da72d7ad6d3d4b5551fc.tar.gz gcc-d0aa42d276497d762934da72d7ad6d3d4b5551fc.tar.bz2 |
* constexpr.c (cxx_eval_store_expression): Delay target evaluation.
From-SVN: r272431
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 49 |
2 files changed, 37 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1071a52..7bd47cf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2019-06-18 Jason Merrill <jason@redhat.com> + * constexpr.c (cxx_eval_store_expression): Delay target evaluation. + +2019-06-18 Jason Merrill <jason@redhat.com> + * constexpr.c (eval_and_check_array_index): Split out from... (cxx_eval_array_reference): ...here. (cxx_eval_store_expression): Use it here, too. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 7c733d7..22f4fa0 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3747,22 +3747,18 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, if (*non_constant_p) return t; } - target = cxx_eval_constant_expression (ctx, target, - true, - non_constant_p, overflow_p); - if (*non_constant_p) - return t; - if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target), type)) + bool evaluated = false; + if (lval) { - /* For initialization of an empty base, the original target will be - *(base*)this, which the above evaluation resolves to the object - argument, which has the derived type rather than the base type. In - this situation, just evaluate the initializer and return, since - there's no actual data to store. */ - gcc_assert (is_empty_class (type)); - return cxx_eval_constant_expression (ctx, init, false, - non_constant_p, overflow_p); + /* If we want to return a reference to the target, we need to evaluate it + as a whole; otherwise, only evaluate the innermost piece to avoid + building up unnecessary *_REFs. */ + target = cxx_eval_constant_expression (ctx, target, true, + non_constant_p, overflow_p); + evaluated = true; + if (*non_constant_p) + return t; } /* Find the underlying variable. */ @@ -3792,7 +3788,17 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, break; default: - object = probe; + if (evaluated) + object = probe; + else + { + probe = cxx_eval_constant_expression (ctx, probe, true, + non_constant_p, overflow_p); + evaluated = true; + if (*non_constant_p) + return t; + } + break; } } @@ -3948,7 +3954,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, new_ctx.object = target; init = cxx_eval_constant_expression (&new_ctx, init, false, non_constant_p, overflow_p); - if (target == object) + if (ctors->is_empty()) /* The hash table might have moved since the get earlier. */ valp = ctx->values->get (object); } @@ -3961,6 +3967,17 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, { /* An outer ctx->ctor might be pointing to *valp, so replace its contents. */ + if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init), + TREE_TYPE (*valp))) + { + /* For initialization of an empty base, the original target will be + *(base*)this, evaluation of which resolves to the object + argument, which has the derived type rather than the base type. In + this situation, just evaluate the initializer and return, since + there's no actual data to store. */ + gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval); + return init; + } CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init); TREE_CONSTANT (*valp) = TREE_CONSTANT (init); TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init); |