aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constexpr.c
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-04-02 16:03:18 -0400
committerPatrick Palka <ppalka@redhat.com>2020-04-04 12:15:15 -0400
commit49a86fce1a879a206fb4b27f097910005d968fda (patch)
tree12bed14c9db0a934c281b3c82703588d322faf56 /gcc/cp/constexpr.c
parent37244b217a7329792f4ec48027f63cf5010b0ea8 (diff)
downloadgcc-49a86fce1a879a206fb4b27f097910005d968fda.zip
gcc-49a86fce1a879a206fb4b27f097910005d968fda.tar.gz
gcc-49a86fce1a879a206fb4b27f097910005d968fda.tar.bz2
c++: Refrain from using replace_placeholders in constexpr evaluation [PR94205]
This removes the use of replace_placeholders in cxx_eval_constant_expression (which is causing the new test lambda-this6.C to ICE due to replace_placeholders mutating the shared TARGET_EXPR_INITIAL tree which then trips up the gimplifier). In its place, this patch adds a 'parent' field to constexpr_ctx which is used to store a pointer to an outer constexpr_ctx that refers to another object under construction. With this new field, we can beef up lookup_placeholder to resolve PLACEHOLDER_EXPRs which refer to former objects under construction, which fixes PR94205 without needing to do replace_placeholders. Also we can now respect the CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag when resolving PLACEHOLDER_EXPRs, and doing so fixes the constexpr analogue of PR79937. gcc/cp/ChangeLog: PR c++/94205 PR c++/79937 * constexpr.c (struct constexpr_ctx): New field 'parent'. (cxx_eval_bare_aggregate): Propagate CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag from the original constructor to the reduced constructor. (lookup_placeholder): Prefer to return the outermost matching object by recursively calling lookup_placeholder on the 'parent' context, but don't cross CONSTRUCTOR_PLACEHOLDER_BOUNDARY constructors. (cxx_eval_constant_expression): Link the 'ctx' context to the 'new_ctx' context via 'new_ctx.parent' when being expanded without an explicit target. Don't call replace_placeholders. (cxx_eval_outermost_constant_expr): Initialize 'ctx.parent' to NULL. gcc/testsuite/ChangeLog: PR c++/94205 PR c++/79937 * g++.dg/cpp1y/pr79937-5.C: New test. * g++.dg/cpp1z/lambda-this6.C: New test.
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r--gcc/cp/constexpr.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 8fa1f53..96497ab 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1076,6 +1076,9 @@ struct constexpr_ctx {
tree object;
/* If inside SWITCH_EXPR. */
constexpr_switch_state *css_state;
+ /* The aggregate initialization context inside which this one is nested. This
+ is used by lookup_placeholder to resolve PLACEHOLDER_EXPRs. */
+ const constexpr_ctx *parent;
/* Whether we should error on a non-constant expression or fail quietly.
This flag needs to be here, but some of the others could move to global
@@ -3841,6 +3844,9 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
vec_alloc (*p, vec_safe_length (v));
+ if (CONSTRUCTOR_PLACEHOLDER_BOUNDARY (t))
+ CONSTRUCTOR_PLACEHOLDER_BOUNDARY (ctx->ctor) = 1;
+
unsigned i;
tree index, value;
bool constant_p = true;
@@ -5303,6 +5309,12 @@ lookup_placeholder (const constexpr_ctx *ctx, bool lval, tree type)
if (!ctx)
return NULL_TREE;
+ /* Prefer the outermost matching object, but don't cross
+ CONSTRUCTOR_PLACEHOLDER_BOUNDARY constructors. */
+ if (ctx->ctor && !CONSTRUCTOR_PLACEHOLDER_BOUNDARY (ctx->ctor))
+ if (tree outer_ob = lookup_placeholder (ctx->parent, lval, type))
+ return outer_ob;
+
/* We could use ctx->object unconditionally, but using ctx->ctor when we
can is a minor optimization. */
if (!lval && ctx->ctor && same_type_p (TREE_TYPE (ctx->ctor), type))
@@ -5606,19 +5618,16 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = *p;
break;
}
- tree init = TARGET_EXPR_INITIAL (t);
if ((AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)))
{
- if (ctx->object)
- /* If the initializer contains any PLACEHOLDER_EXPR, we need to
- resolve them before we create a new CONSTRUCTOR for the
- temporary. */
- init = replace_placeholders (init, ctx->object);
-
/* We're being expanded without an explicit target, so start
initializing a new object; expansion with an explicit target
strips the TARGET_EXPR before we get here. */
new_ctx = *ctx;
+ /* Link CTX to NEW_CTX so that lookup_placeholder can resolve
+ any PLACEHOLDER_EXPR within the initializer that refers to the
+ former object under construction. */
+ new_ctx.parent = ctx;
new_ctx.ctor = build_constructor (type, NULL);
CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
new_ctx.object = slot;
@@ -6472,7 +6481,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
bool overflow_p = false;
constexpr_global_ctx global_ctx;
- constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL,
+ constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
allow_non_constant, strict,
manifestly_const_eval || !allow_non_constant,
uid_sensitive };