* C++ PATCH for c++/80095, ICE with this pointer in NSDMI
@ 2017-03-29 17:08 Marek Polacek
2017-03-29 19:11 ` Jason Merrill
0 siblings, 1 reply; 5+ messages in thread
From: Marek Polacek @ 2017-03-29 17:08 UTC (permalink / raw)
To: GCC Patches, Jason Merrill
Here we have a reference initialization with NSDMI and *this. We are crashing
because a PLACEHOLDER_EXPR crept into the gimplifier.
This happens since r218653 where set_up_extended_ref_temp was changed to
use split_nonconstant_init. As a consequence, cp_gimplify_init_expr might
now be receiving
D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
instead of
D.2051 = {.p = (void *) &<PLACEHOLDER_EXPR struct A>}
where the RHS was a CONSTRUCTOR. It no longer is, so replace_placeholders is
not called anymore. It occurred to me that we should use the same check as in
store_init_value (i.e. check that the object to be used in the substitution is
a class), but given what split_nonconstant_init might produce, handle
COMPONENT_REFs specially.
Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?
2017-03-29 Marek Polacek <polacek@redhat.com>
PR c++/80095 - ICE with this pointer in NSDMI.
* cp-gimplify.c (cp_gimplify_init_expr): Call replace_placeholders
when TO is a class.
* g++.dg/cpp1y/nsdmi-aggr8.C: New test.
diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c
index 354ae1a..e530daf 100644
--- gcc/cp/cp-gimplify.c
+++ gcc/cp/cp-gimplify.c
@@ -496,7 +496,16 @@ cp_gimplify_init_expr (tree *expr_p)
TREE_TYPE (from) = void_type_node;
}
- if (cxx_dialect >= cxx14 && TREE_CODE (sub) == CONSTRUCTOR)
+ /* split_nonconstant_init might've produced something like
+ D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
+ in which case we want to substitute the placeholder with
+ D.2051. */
+ tree op0 = to;
+ while (TREE_CODE (op0) == COMPONENT_REF)
+ op0 = TREE_OPERAND (op0, 0);
+ tree type = TREE_TYPE (op0);
+
+ if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
/* Handle aggregate NSDMI. */
replace_placeholders (sub, to);
diff --git gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
index e69de29..8c99ffb 100644
--- gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
+++ gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
@@ -0,0 +1,16 @@
+// PR c++/80095
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+ void* p = this;
+};
+
+void
+foo ()
+{
+ const A& a = A{};
+ A&& a2 = A{};
+ const A& a3{};
+ A&& a4{};
+}
Marek
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: C++ PATCH for c++/80095, ICE with this pointer in NSDMI
2017-03-29 17:08 C++ PATCH for c++/80095, ICE with this pointer in NSDMI Marek Polacek
@ 2017-03-29 19:11 ` Jason Merrill
2017-03-29 21:51 ` Marek Polacek
0 siblings, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2017-03-29 19:11 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On Wed, Mar 29, 2017 at 12:38 PM, Marek Polacek <polacek@redhat.com> wrote:
> Here we have a reference initialization with NSDMI and *this. We are crashing
> because a PLACEHOLDER_EXPR crept into the gimplifier.
>
> This happens since r218653 where set_up_extended_ref_temp was changed to
> use split_nonconstant_init. As a consequence, cp_gimplify_init_expr might
> now be receiving
>
> D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
>
> instead of
>
> D.2051 = {.p = (void *) &<PLACEHOLDER_EXPR struct A>}
>
> where the RHS was a CONSTRUCTOR. It no longer is, so replace_placeholders is
> not called anymore. It occurred to me that we should use the same check as in
> store_init_value (i.e. check that the object to be used in the substitution is
> a class), but given what split_nonconstant_init might produce, handle
> COMPONENT_REFs specially.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?
>
> 2017-03-29 Marek Polacek <polacek@redhat.com>
>
> PR c++/80095 - ICE with this pointer in NSDMI.
> * cp-gimplify.c (cp_gimplify_init_expr): Call replace_placeholders
> when TO is a class.
>
> * g++.dg/cpp1y/nsdmi-aggr8.C: New test.
>
> diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c
> index 354ae1a..e530daf 100644
> --- gcc/cp/cp-gimplify.c
> +++ gcc/cp/cp-gimplify.c
> @@ -496,7 +496,16 @@ cp_gimplify_init_expr (tree *expr_p)
> TREE_TYPE (from) = void_type_node;
> }
>
> - if (cxx_dialect >= cxx14 && TREE_CODE (sub) == CONSTRUCTOR)
> + /* split_nonconstant_init might've produced something like
> + D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
> + in which case we want to substitute the placeholder with
> + D.2051. */
> + tree op0 = to;
> + while (TREE_CODE (op0) == COMPONENT_REF)
> + op0 = TREE_OPERAND (op0, 0);
> + tree type = TREE_TYPE (op0);
> +
> + if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
How about doing this checking in replace_placeholders, instead? That
is, if the object isn't a (member of a) class, just return.
Jason
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: C++ PATCH for c++/80095, ICE with this pointer in NSDMI
2017-03-29 19:11 ` Jason Merrill
@ 2017-03-29 21:51 ` Marek Polacek
2017-04-05 9:49 ` Marek Polacek
0 siblings, 1 reply; 5+ messages in thread
From: Marek Polacek @ 2017-03-29 21:51 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Wed, Mar 29, 2017 at 02:56:51PM -0400, Jason Merrill wrote:
> On Wed, Mar 29, 2017 at 12:38 PM, Marek Polacek <polacek@redhat.com> wrote:
> > Here we have a reference initialization with NSDMI and *this. We are crashing
> > because a PLACEHOLDER_EXPR crept into the gimplifier.
> >
> > This happens since r218653 where set_up_extended_ref_temp was changed to
> > use split_nonconstant_init. As a consequence, cp_gimplify_init_expr might
> > now be receiving
> >
> > D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
> >
> > instead of
> >
> > D.2051 = {.p = (void *) &<PLACEHOLDER_EXPR struct A>}
> >
> > where the RHS was a CONSTRUCTOR. It no longer is, so replace_placeholders is
> > not called anymore. It occurred to me that we should use the same check as in
> > store_init_value (i.e. check that the object to be used in the substitution is
> > a class), but given what split_nonconstant_init might produce, handle
> > COMPONENT_REFs specially.
> >
> > Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?
> >
> > 2017-03-29 Marek Polacek <polacek@redhat.com>
> >
> > PR c++/80095 - ICE with this pointer in NSDMI.
> > * cp-gimplify.c (cp_gimplify_init_expr): Call replace_placeholders
> > when TO is a class.
> >
> > * g++.dg/cpp1y/nsdmi-aggr8.C: New test.
> >
> > diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c
> > index 354ae1a..e530daf 100644
> > --- gcc/cp/cp-gimplify.c
> > +++ gcc/cp/cp-gimplify.c
> > @@ -496,7 +496,16 @@ cp_gimplify_init_expr (tree *expr_p)
> > TREE_TYPE (from) = void_type_node;
> > }
> >
> > - if (cxx_dialect >= cxx14 && TREE_CODE (sub) == CONSTRUCTOR)
> > + /* split_nonconstant_init might've produced something like
> > + D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
> > + in which case we want to substitute the placeholder with
> > + D.2051. */
> > + tree op0 = to;
> > + while (TREE_CODE (op0) == COMPONENT_REF)
> > + op0 = TREE_OPERAND (op0, 0);
> > + tree type = TREE_TYPE (op0);
> > +
> > + if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
>
> How about doing this checking in replace_placeholders, instead? That
> is, if the object isn't a (member of a) class, just return.
Sure. I also moved the C++14 check into replace_placeholders, although maybe
I shouldn't have.
Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?
2017-03-29 Marek Polacek <polacek@redhat.com>
PR c++/80095
* call.c (build_over_call): Don't check cxx_dialect.
* cp-gimplify.c (cp_gimplify_init_expr): Don't check cxx_dialect nor
whether SUB is a CONSTRUCTOR.
* init.c (build_new_1): Don't check cxx_dialect.
* tree.c (replace_placeholders): Add a function comment. Return if
not in C++14, or if the object isn't a (member of a) class.
* typeck2.c (store_init_value): Don't check cxx_dialect nor whether
TYPE is CLASS_TYPE_P.
* g++.dg/cpp1y/nsdmi-aggr8.C: New test.
diff --git gcc/cp/call.c gcc/cp/call.c
index 803fbd4..c15b8e4 100644
--- gcc/cp/call.c
+++ gcc/cp/call.c
@@ -8047,9 +8047,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
arg = cp_build_indirect_ref (arg, RO_NULL, complain);
val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
- if (cxx_dialect >= cxx14)
- /* Handle NSDMI that refer to the object being initialized. */
- replace_placeholders (arg, to);
+ /* Handle NSDMI that refer to the object being initialized. */
+ replace_placeholders (arg, to);
}
else
{
diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c
index 354ae1a..3f91c35 100644
--- gcc/cp/cp-gimplify.c
+++ gcc/cp/cp-gimplify.c
@@ -496,9 +496,8 @@ cp_gimplify_init_expr (tree *expr_p)
TREE_TYPE (from) = void_type_node;
}
- if (cxx_dialect >= cxx14 && TREE_CODE (sub) == CONSTRUCTOR)
- /* Handle aggregate NSDMI. */
- replace_placeholders (sub, to);
+ /* Handle aggregate NSDMI. */
+ replace_placeholders (sub, to);
if (t == sub)
break;
diff --git gcc/cp/init.c gcc/cp/init.c
index 7732795..6a70955 100644
--- gcc/cp/init.c
+++ gcc/cp/init.c
@@ -3373,8 +3373,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
object being initialized, replace them now and don't try to
preevaluate. */
bool had_placeholder = false;
- if (cxx_dialect >= cxx14
- && !processing_template_decl
+ if (!processing_template_decl
&& TREE_CODE (init_expr) == INIT_EXPR)
TREE_OPERAND (init_expr, 1)
= replace_placeholders (TREE_OPERAND (init_expr, 1),
diff --git gcc/cp/tree.c gcc/cp/tree.c
index 2757af6..9939135 100644
--- gcc/cp/tree.c
+++ gcc/cp/tree.c
@@ -2813,9 +2813,23 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_)
return NULL_TREE;
}
+/* Replace PLACEHOLDER_EXPRs in EXP with object OBJ. SEEN_P is set if
+ a PLACEHOLDER_EXPR has been encountered. */
+
tree
replace_placeholders (tree exp, tree obj, bool *seen_p)
{
+ /* This is only relevant for C++14. */
+ if (cxx_dialect < cxx14)
+ return exp;
+
+ /* If the object isn't a (member of a) class, do nothing. */
+ tree op0 = obj;
+ while (TREE_CODE (op0) == COMPONENT_REF)
+ op0 = TREE_OPERAND (op0, 0);
+ if (!CLASS_TYPE_P (strip_array_types (TREE_TYPE (op0))))
+ return exp;
+
tree *tp = &exp;
replace_placeholders_t data = { obj, false };
if (TREE_CODE (exp) == TARGET_EXPR)
diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c
index 58a01c9..67fbaea 100644
--- gcc/cp/typeck2.c
+++ gcc/cp/typeck2.c
@@ -836,9 +836,8 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
}
value = cp_fully_fold (value);
- if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
- /* Handle aggregate NSDMI in non-constant initializers, too. */
- value = replace_placeholders (value, decl);
+ /* Handle aggregate NSDMI in non-constant initializers, too. */
+ value = replace_placeholders (value, decl);
/* DECL may change value; purge caches. */
clear_cv_and_fold_caches ();
diff --git gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
index e69de29..8c99ffb 100644
--- gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
+++ gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
@@ -0,0 +1,16 @@
+// PR c++/80095
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+ void* p = this;
+};
+
+void
+foo ()
+{
+ const A& a = A{};
+ A&& a2 = A{};
+ const A& a3{};
+ A&& a4{};
+}
Marek
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: C++ PATCH for c++/80095, ICE with this pointer in NSDMI
2017-03-29 21:51 ` Marek Polacek
@ 2017-04-05 9:49 ` Marek Polacek
2017-04-07 17:03 ` Jason Merrill
0 siblings, 1 reply; 5+ messages in thread
From: Marek Polacek @ 2017-04-05 9:49 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
Ping.
On Wed, Mar 29, 2017 at 11:32:39PM +0200, Marek Polacek wrote:
> On Wed, Mar 29, 2017 at 02:56:51PM -0400, Jason Merrill wrote:
> > On Wed, Mar 29, 2017 at 12:38 PM, Marek Polacek <polacek@redhat.com> wrote:
> > > Here we have a reference initialization with NSDMI and *this. We are crashing
> > > because a PLACEHOLDER_EXPR crept into the gimplifier.
> > >
> > > This happens since r218653 where set_up_extended_ref_temp was changed to
> > > use split_nonconstant_init. As a consequence, cp_gimplify_init_expr might
> > > now be receiving
> > >
> > > D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
> > >
> > > instead of
> > >
> > > D.2051 = {.p = (void *) &<PLACEHOLDER_EXPR struct A>}
> > >
> > > where the RHS was a CONSTRUCTOR. It no longer is, so replace_placeholders is
> > > not called anymore. It occurred to me that we should use the same check as in
> > > store_init_value (i.e. check that the object to be used in the substitution is
> > > a class), but given what split_nonconstant_init might produce, handle
> > > COMPONENT_REFs specially.
> > >
> > > Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?
> > >
> > > 2017-03-29 Marek Polacek <polacek@redhat.com>
> > >
> > > PR c++/80095 - ICE with this pointer in NSDMI.
> > > * cp-gimplify.c (cp_gimplify_init_expr): Call replace_placeholders
> > > when TO is a class.
> > >
> > > * g++.dg/cpp1y/nsdmi-aggr8.C: New test.
> > >
> > > diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c
> > > index 354ae1a..e530daf 100644
> > > --- gcc/cp/cp-gimplify.c
> > > +++ gcc/cp/cp-gimplify.c
> > > @@ -496,7 +496,16 @@ cp_gimplify_init_expr (tree *expr_p)
> > > TREE_TYPE (from) = void_type_node;
> > > }
> > >
> > > - if (cxx_dialect >= cxx14 && TREE_CODE (sub) == CONSTRUCTOR)
> > > + /* split_nonconstant_init might've produced something like
> > > + D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
> > > + in which case we want to substitute the placeholder with
> > > + D.2051. */
> > > + tree op0 = to;
> > > + while (TREE_CODE (op0) == COMPONENT_REF)
> > > + op0 = TREE_OPERAND (op0, 0);
> > > + tree type = TREE_TYPE (op0);
> > > +
> > > + if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
> >
> > How about doing this checking in replace_placeholders, instead? That
> > is, if the object isn't a (member of a) class, just return.
>
> Sure. I also moved the C++14 check into replace_placeholders, although maybe
> I shouldn't have.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?
>
> 2017-03-29 Marek Polacek <polacek@redhat.com>
>
> PR c++/80095
> * call.c (build_over_call): Don't check cxx_dialect.
> * cp-gimplify.c (cp_gimplify_init_expr): Don't check cxx_dialect nor
> whether SUB is a CONSTRUCTOR.
> * init.c (build_new_1): Don't check cxx_dialect.
> * tree.c (replace_placeholders): Add a function comment. Return if
> not in C++14, or if the object isn't a (member of a) class.
> * typeck2.c (store_init_value): Don't check cxx_dialect nor whether
> TYPE is CLASS_TYPE_P.
>
> * g++.dg/cpp1y/nsdmi-aggr8.C: New test.
>
> diff --git gcc/cp/call.c gcc/cp/call.c
> index 803fbd4..c15b8e4 100644
> --- gcc/cp/call.c
> +++ gcc/cp/call.c
> @@ -8047,9 +8047,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
> {
> arg = cp_build_indirect_ref (arg, RO_NULL, complain);
> val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
> - if (cxx_dialect >= cxx14)
> - /* Handle NSDMI that refer to the object being initialized. */
> - replace_placeholders (arg, to);
> + /* Handle NSDMI that refer to the object being initialized. */
> + replace_placeholders (arg, to);
> }
> else
> {
> diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c
> index 354ae1a..3f91c35 100644
> --- gcc/cp/cp-gimplify.c
> +++ gcc/cp/cp-gimplify.c
> @@ -496,9 +496,8 @@ cp_gimplify_init_expr (tree *expr_p)
> TREE_TYPE (from) = void_type_node;
> }
>
> - if (cxx_dialect >= cxx14 && TREE_CODE (sub) == CONSTRUCTOR)
> - /* Handle aggregate NSDMI. */
> - replace_placeholders (sub, to);
> + /* Handle aggregate NSDMI. */
> + replace_placeholders (sub, to);
>
> if (t == sub)
> break;
> diff --git gcc/cp/init.c gcc/cp/init.c
> index 7732795..6a70955 100644
> --- gcc/cp/init.c
> +++ gcc/cp/init.c
> @@ -3373,8 +3373,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
> object being initialized, replace them now and don't try to
> preevaluate. */
> bool had_placeholder = false;
> - if (cxx_dialect >= cxx14
> - && !processing_template_decl
> + if (!processing_template_decl
> && TREE_CODE (init_expr) == INIT_EXPR)
> TREE_OPERAND (init_expr, 1)
> = replace_placeholders (TREE_OPERAND (init_expr, 1),
> diff --git gcc/cp/tree.c gcc/cp/tree.c
> index 2757af6..9939135 100644
> --- gcc/cp/tree.c
> +++ gcc/cp/tree.c
> @@ -2813,9 +2813,23 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_)
> return NULL_TREE;
> }
>
> +/* Replace PLACEHOLDER_EXPRs in EXP with object OBJ. SEEN_P is set if
> + a PLACEHOLDER_EXPR has been encountered. */
> +
> tree
> replace_placeholders (tree exp, tree obj, bool *seen_p)
> {
> + /* This is only relevant for C++14. */
> + if (cxx_dialect < cxx14)
> + return exp;
> +
> + /* If the object isn't a (member of a) class, do nothing. */
> + tree op0 = obj;
> + while (TREE_CODE (op0) == COMPONENT_REF)
> + op0 = TREE_OPERAND (op0, 0);
> + if (!CLASS_TYPE_P (strip_array_types (TREE_TYPE (op0))))
> + return exp;
> +
> tree *tp = &exp;
> replace_placeholders_t data = { obj, false };
> if (TREE_CODE (exp) == TARGET_EXPR)
> diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c
> index 58a01c9..67fbaea 100644
> --- gcc/cp/typeck2.c
> +++ gcc/cp/typeck2.c
> @@ -836,9 +836,8 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
> }
> value = cp_fully_fold (value);
>
> - if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
> - /* Handle aggregate NSDMI in non-constant initializers, too. */
> - value = replace_placeholders (value, decl);
> + /* Handle aggregate NSDMI in non-constant initializers, too. */
> + value = replace_placeholders (value, decl);
>
> /* DECL may change value; purge caches. */
> clear_cv_and_fold_caches ();
> diff --git gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
> index e69de29..8c99ffb 100644
> --- gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
> +++ gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
> @@ -0,0 +1,16 @@
> +// PR c++/80095
> +// { dg-do compile { target c++14 } }
> +
> +struct A
> +{
> + void* p = this;
> +};
> +
> +void
> +foo ()
> +{
> + const A& a = A{};
> + A&& a2 = A{};
> + const A& a3{};
> + A&& a4{};
> +}
>
> Marek
Marek
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: C++ PATCH for c++/80095, ICE with this pointer in NSDMI
2017-04-05 9:49 ` Marek Polacek
@ 2017-04-07 17:03 ` Jason Merrill
0 siblings, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2017-04-07 17:03 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
OK, thanks.
On Wed, Apr 5, 2017 at 5:49 AM, Marek Polacek <polacek@redhat.com> wrote:
> Ping.
>
> On Wed, Mar 29, 2017 at 11:32:39PM +0200, Marek Polacek wrote:
>> On Wed, Mar 29, 2017 at 02:56:51PM -0400, Jason Merrill wrote:
>> > On Wed, Mar 29, 2017 at 12:38 PM, Marek Polacek <polacek@redhat.com> wrote:
>> > > Here we have a reference initialization with NSDMI and *this. We are crashing
>> > > because a PLACEHOLDER_EXPR crept into the gimplifier.
>> > >
>> > > This happens since r218653 where set_up_extended_ref_temp was changed to
>> > > use split_nonconstant_init. As a consequence, cp_gimplify_init_expr might
>> > > now be receiving
>> > >
>> > > D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
>> > >
>> > > instead of
>> > >
>> > > D.2051 = {.p = (void *) &<PLACEHOLDER_EXPR struct A>}
>> > >
>> > > where the RHS was a CONSTRUCTOR. It no longer is, so replace_placeholders is
>> > > not called anymore. It occurred to me that we should use the same check as in
>> > > store_init_value (i.e. check that the object to be used in the substitution is
>> > > a class), but given what split_nonconstant_init might produce, handle
>> > > COMPONENT_REFs specially.
>> > >
>> > > Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?
>> > >
>> > > 2017-03-29 Marek Polacek <polacek@redhat.com>
>> > >
>> > > PR c++/80095 - ICE with this pointer in NSDMI.
>> > > * cp-gimplify.c (cp_gimplify_init_expr): Call replace_placeholders
>> > > when TO is a class.
>> > >
>> > > * g++.dg/cpp1y/nsdmi-aggr8.C: New test.
>> > >
>> > > diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c
>> > > index 354ae1a..e530daf 100644
>> > > --- gcc/cp/cp-gimplify.c
>> > > +++ gcc/cp/cp-gimplify.c
>> > > @@ -496,7 +496,16 @@ cp_gimplify_init_expr (tree *expr_p)
>> > > TREE_TYPE (from) = void_type_node;
>> > > }
>> > >
>> > > - if (cxx_dialect >= cxx14 && TREE_CODE (sub) == CONSTRUCTOR)
>> > > + /* split_nonconstant_init might've produced something like
>> > > + D.2051.p = (void *) &<PLACEHOLDER_EXPR struct A>
>> > > + in which case we want to substitute the placeholder with
>> > > + D.2051. */
>> > > + tree op0 = to;
>> > > + while (TREE_CODE (op0) == COMPONENT_REF)
>> > > + op0 = TREE_OPERAND (op0, 0);
>> > > + tree type = TREE_TYPE (op0);
>> > > +
>> > > + if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
>> >
>> > How about doing this checking in replace_placeholders, instead? That
>> > is, if the object isn't a (member of a) class, just return.
>>
>> Sure. I also moved the C++14 check into replace_placeholders, although maybe
>> I shouldn't have.
>>
>> Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?
>>
>> 2017-03-29 Marek Polacek <polacek@redhat.com>
>>
>> PR c++/80095
>> * call.c (build_over_call): Don't check cxx_dialect.
>> * cp-gimplify.c (cp_gimplify_init_expr): Don't check cxx_dialect nor
>> whether SUB is a CONSTRUCTOR.
>> * init.c (build_new_1): Don't check cxx_dialect.
>> * tree.c (replace_placeholders): Add a function comment. Return if
>> not in C++14, or if the object isn't a (member of a) class.
>> * typeck2.c (store_init_value): Don't check cxx_dialect nor whether
>> TYPE is CLASS_TYPE_P.
>>
>> * g++.dg/cpp1y/nsdmi-aggr8.C: New test.
>>
>> diff --git gcc/cp/call.c gcc/cp/call.c
>> index 803fbd4..c15b8e4 100644
>> --- gcc/cp/call.c
>> +++ gcc/cp/call.c
>> @@ -8047,9 +8047,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
>> {
>> arg = cp_build_indirect_ref (arg, RO_NULL, complain);
>> val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
>> - if (cxx_dialect >= cxx14)
>> - /* Handle NSDMI that refer to the object being initialized. */
>> - replace_placeholders (arg, to);
>> + /* Handle NSDMI that refer to the object being initialized. */
>> + replace_placeholders (arg, to);
>> }
>> else
>> {
>> diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c
>> index 354ae1a..3f91c35 100644
>> --- gcc/cp/cp-gimplify.c
>> +++ gcc/cp/cp-gimplify.c
>> @@ -496,9 +496,8 @@ cp_gimplify_init_expr (tree *expr_p)
>> TREE_TYPE (from) = void_type_node;
>> }
>>
>> - if (cxx_dialect >= cxx14 && TREE_CODE (sub) == CONSTRUCTOR)
>> - /* Handle aggregate NSDMI. */
>> - replace_placeholders (sub, to);
>> + /* Handle aggregate NSDMI. */
>> + replace_placeholders (sub, to);
>>
>> if (t == sub)
>> break;
>> diff --git gcc/cp/init.c gcc/cp/init.c
>> index 7732795..6a70955 100644
>> --- gcc/cp/init.c
>> +++ gcc/cp/init.c
>> @@ -3373,8 +3373,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>> object being initialized, replace them now and don't try to
>> preevaluate. */
>> bool had_placeholder = false;
>> - if (cxx_dialect >= cxx14
>> - && !processing_template_decl
>> + if (!processing_template_decl
>> && TREE_CODE (init_expr) == INIT_EXPR)
>> TREE_OPERAND (init_expr, 1)
>> = replace_placeholders (TREE_OPERAND (init_expr, 1),
>> diff --git gcc/cp/tree.c gcc/cp/tree.c
>> index 2757af6..9939135 100644
>> --- gcc/cp/tree.c
>> +++ gcc/cp/tree.c
>> @@ -2813,9 +2813,23 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_)
>> return NULL_TREE;
>> }
>>
>> +/* Replace PLACEHOLDER_EXPRs in EXP with object OBJ. SEEN_P is set if
>> + a PLACEHOLDER_EXPR has been encountered. */
>> +
>> tree
>> replace_placeholders (tree exp, tree obj, bool *seen_p)
>> {
>> + /* This is only relevant for C++14. */
>> + if (cxx_dialect < cxx14)
>> + return exp;
>> +
>> + /* If the object isn't a (member of a) class, do nothing. */
>> + tree op0 = obj;
>> + while (TREE_CODE (op0) == COMPONENT_REF)
>> + op0 = TREE_OPERAND (op0, 0);
>> + if (!CLASS_TYPE_P (strip_array_types (TREE_TYPE (op0))))
>> + return exp;
>> +
>> tree *tp = &exp;
>> replace_placeholders_t data = { obj, false };
>> if (TREE_CODE (exp) == TARGET_EXPR)
>> diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c
>> index 58a01c9..67fbaea 100644
>> --- gcc/cp/typeck2.c
>> +++ gcc/cp/typeck2.c
>> @@ -836,9 +836,8 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
>> }
>> value = cp_fully_fold (value);
>>
>> - if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
>> - /* Handle aggregate NSDMI in non-constant initializers, too. */
>> - value = replace_placeholders (value, decl);
>> + /* Handle aggregate NSDMI in non-constant initializers, too. */
>> + value = replace_placeholders (value, decl);
>>
>> /* DECL may change value; purge caches. */
>> clear_cv_and_fold_caches ();
>> diff --git gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
>> index e69de29..8c99ffb 100644
>> --- gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
>> +++ gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr8.C
>> @@ -0,0 +1,16 @@
>> +// PR c++/80095
>> +// { dg-do compile { target c++14 } }
>> +
>> +struct A
>> +{
>> + void* p = this;
>> +};
>> +
>> +void
>> +foo ()
>> +{
>> + const A& a = A{};
>> + A&& a2 = A{};
>> + const A& a3{};
>> + A&& a4{};
>> +}
>>
>> Marek
>
> Marek
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-04-07 17:03 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-29 17:08 C++ PATCH for c++/80095, ICE with this pointer in NSDMI Marek Polacek
2017-03-29 19:11 ` Jason Merrill
2017-03-29 21:51 ` Marek Polacek
2017-04-05 9:49 ` Marek Polacek
2017-04-07 17:03 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).