From: jason Date: Tue, 18 Jun 2019 16:08:29 +0000 (+0000) Subject: * constexpr.c (cxx_eval_store_expression): Delay target evaluation. X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fgcc.git;a=commitdiff_plain;h=ca612e6a63d8771e4e37b41a166d9f8675ef061a * constexpr.c (cxx_eval_store_expression): Delay target evaluation. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@272431 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1071a52a5586..7bd47cf4b569 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2019-06-18 Jason Merrill + + * constexpr.c (cxx_eval_store_expression): Delay target evaluation. + 2019-06-18 Jason Merrill * constexpr.c (eval_and_check_array_index): Split out from... diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 7c733d78b5b6..22f4fa0d3511 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);