From 89262ec6bdb835436ecfa715397bae078035fe9e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 8 Mar 2017 20:01:18 -0500 Subject: [PATCH] PR c++/79797 - ICE with self-reference in array DMI. * constexpr.c (lookup_placeholder): Split out... (cxx_eval_constant_expression): ...from here. From-SVN: r245986 --- gcc/cp/ChangeLog | 6 +++ gcc/cp/constexpr.c | 59 +++++++++++++++--------- gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr7.C | 12 +++++ 3 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr7.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 47add3250d5..5bd83227ff7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2017-03-08 Jason Merrill + + PR c++/79797 - ICE with self-reference in array DMI. + * constexpr.c (lookup_placeholder): Split out... + (cxx_eval_constant_expression): ...from here. + 2017-03-07 Jakub Jelinek PR c/79834 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index f114da0d9a7..2510e23e61b 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3827,6 +3827,35 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t, return NULL_TREE; } +/* Find the object of TYPE under initialization in CTX. */ + +static tree +lookup_placeholder (const constexpr_ctx *ctx, bool lval, tree type) +{ + if (!ctx || !ctx->ctor || (lval && !ctx->object)) + return NULL_TREE; + + /* We could use ctx->object unconditionally, but using ctx->ctor when we + can is a minor optimization. */ + if (!lval && same_type_p (TREE_TYPE (ctx->ctor), type)) + return ctx->ctor; + + /* Since an object cannot have a field of its own type, we can search outward + from ctx->object to find the unique containing object of TYPE. */ + tree ob = ctx->object; + while (ob) + { + if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (ob), type)) + break; + if (handled_component_p (ob)) + ob = TREE_OPERAND (ob, 0); + else + ob = NULL_TREE; + } + + return ob; +} + /* Attempt to reduce the expression T to a constant value. On failure, issue diagnostic and return error_mark_node. */ /* FIXME unify with c_fully_fold */ @@ -4468,27 +4497,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, break; case PLACEHOLDER_EXPR: - if (!ctx || !ctx->ctor || (lval && !ctx->object) - || !(same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (t), TREE_TYPE (ctx->ctor)))) - { - /* A placeholder without a referent. We can get here when - checking whether NSDMIs are noexcept, or in massage_init_elt; - just say it's non-constant for now. */ - gcc_assert (ctx->quiet); - *non_constant_p = true; - break; - } - else - { - /* Use of the value or address of the current object. We could - use ctx->object unconditionally, but using ctx->ctor when we - can is a minor optimization. */ - tree ctor = lval ? ctx->object : ctx->ctor; - return cxx_eval_constant_expression - (ctx, ctor, lval, - non_constant_p, overflow_p); - } + /* Use of the value or address of the current object. */ + if (tree ctor = lookup_placeholder (ctx, lval, TREE_TYPE (t))) + return cxx_eval_constant_expression (ctx, ctor, lval, + non_constant_p, overflow_p); + /* A placeholder without a referent. We can get here when + checking whether NSDMIs are noexcept, or in massage_init_elt; + just say it's non-constant for now. */ + gcc_assert (ctx->quiet); + *non_constant_p = true; break; case EXIT_EXPR: diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr7.C b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr7.C new file mode 100644 index 00000000000..2134ac9ec8b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr7.C @@ -0,0 +1,12 @@ +// PR c++/79797 +// { dg-do compile { target c++14 } } + +struct A +{ + A* x[1]{(A*)this}; +}; + +extern constexpr A a{}; + +#define SA(X) static_assert ((X), #X) +SA (a.x[0] == &a);