Commit d0aa42d2 by Jason Merrill Committed by Jason Merrill

* constexpr.c (cxx_eval_store_expression): Delay target evaluation.

From-SVN: r272431
parent 043666e0
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.
......
......@@ -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);
......
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