* [PATCH] c++: FIX_TRUNC_EXPR in tsubst [PR102990]
@ 2022-03-22 23:55 Marek Polacek
2022-03-23 20:35 ` Jason Merrill
0 siblings, 1 reply; 6+ messages in thread
From: Marek Polacek @ 2022-03-22 23:55 UTC (permalink / raw)
To: Jason Merrill, GCC Patches
This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
where it hits gcc_unreachable ().
The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
was introduced in r181478, but it did the wrong thing, whereupon it
was turned into gcc_unreachable () in r258821 (see this thread:
<https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
In a template, we should never create a FIX_TRUNC_EXPR (that's what
conv_unsafe_in_template_p is for). But in this test we are NOT in
a template when we call digest_nsdmi_init which ends up calling
convert_like, converting 1.0e+0 to int, so convert_to_integer_1
gives us a FIX_TRUNC_EXPR.
But then when we get to parsing f's parameters, we are in a template
when processing decltype(Helpers{}), and since r268321, when the
compound literal isn't instantiation-dependent and the type isn't
type-dependent, finish_compound_literal falls back to the normal
processing, so it calls digest_init, which does fold_non_dependent_init
and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
therefore crash in tsubst_copy_and_build.
Either I can tweak p_c_e to say that a FIX_TRUNC_EXPR in a template
is not potentially constant, or I can just remove the whole F_T_E
case, since:
a) we could not have created an IMPLICIT_CONV_EXPR here, and
b) similar code, FLOAT_EXPR, is not handled here, either.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
PR c++/102990
gcc/cp/ChangeLog:
* pt.cc (tsubst_copy_and_build) <case FIX_TRUNC_EXPR>: Remove.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/nsdmi-template22.C: New test.
* g++.dg/cpp0x/nsdmi-template23.C: New test.
---
gcc/cp/pt.cc | 4 ----
gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C | 13 +++++++++++++
gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C | 13 +++++++++++++
3 files changed, 26 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 715eea27577..a3becc19290 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20184,10 +20184,6 @@ tsubst_copy_and_build (tree t,
templated_operator_saved_lookups (t),
complain|decltype_flag));
- case FIX_TRUNC_EXPR:
- /* convert_like should have created an IMPLICIT_CONV_EXPR. */
- gcc_unreachable ();
-
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == LABEL_DECL)
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
new file mode 100644
index 00000000000..4ed2501035c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
@@ -0,0 +1,13 @@
+// PR c++/102990
+// { dg-do compile { target c++11 } }
+
+struct knob_t {
+ /* Let's create a FIX_TRUNC_EXPR. */
+ int value = 1.0;
+};
+
+struct Helpers {
+ knob_t inputs;
+};
+
+template<class> void f(decltype(Helpers{}));
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
new file mode 100644
index 00000000000..240cab4347a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
@@ -0,0 +1,13 @@
+// PR c++/102990
+// { dg-do compile { target c++11 } }
+
+struct knob_t {
+ /* Let's create a FLOAT_EXPR. */
+ double value = 1UL;
+};
+
+struct Helpers {
+ knob_t inputs;
+};
+
+template<class> void f(decltype(Helpers{}));
base-commit: 5d2233f4033dfa37ad88dc2eab138524fe64242e
--
2.35.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: FIX_TRUNC_EXPR in tsubst [PR102990]
2022-03-22 23:55 [PATCH] c++: FIX_TRUNC_EXPR in tsubst [PR102990] Marek Polacek
@ 2022-03-23 20:35 ` Jason Merrill
2022-03-23 23:26 ` Marek Polacek
0 siblings, 1 reply; 6+ messages in thread
From: Jason Merrill @ 2022-03-23 20:35 UTC (permalink / raw)
To: Marek Polacek, GCC Patches
On 3/22/22 19:55, Marek Polacek wrote:
> This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
> where it hits gcc_unreachable ().
>
> The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
> was introduced in r181478, but it did the wrong thing, whereupon it
> was turned into gcc_unreachable () in r258821 (see this thread:
> <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
>
> In a template, we should never create a FIX_TRUNC_EXPR (that's what
> conv_unsafe_in_template_p is for). But in this test we are NOT in
> a template when we call digest_nsdmi_init which ends up calling
> convert_like, converting 1.0e+0 to int, so convert_to_integer_1
> gives us a FIX_TRUNC_EXPR.
>
> But then when we get to parsing f's parameters, we are in a template
> when processing decltype(Helpers{}), and since r268321, when the
> compound literal isn't instantiation-dependent and the type isn't
> type-dependent, finish_compound_literal falls back to the normal
> processing, so it calls digest_init, which does fold_non_dependent_init
> and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
> therefore crash in tsubst_copy_and_build.
Hmm, we shouldn't be doing fold_non_dependent_init on the result of
get_nsdmi. Why does that happen?
> Either I can tweak p_c_e to say that a FIX_TRUNC_EXPR in a template
> is not potentially constant, or I can just remove the whole F_T_E
> case, since:
> a) we could not have created an IMPLICIT_CONV_EXPR here, and
> b) similar code, FLOAT_EXPR, is not handled here, either.
>
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
>
> PR c++/102990
>
> gcc/cp/ChangeLog:
>
> * pt.cc (tsubst_copy_and_build) <case FIX_TRUNC_EXPR>: Remove.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp0x/nsdmi-template22.C: New test.
> * g++.dg/cpp0x/nsdmi-template23.C: New test.
> ---
> gcc/cp/pt.cc | 4 ----
> gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C | 13 +++++++++++++
> gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C | 13 +++++++++++++
> 3 files changed, 26 insertions(+), 4 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 715eea27577..a3becc19290 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -20184,10 +20184,6 @@ tsubst_copy_and_build (tree t,
> templated_operator_saved_lookups (t),
> complain|decltype_flag));
>
> - case FIX_TRUNC_EXPR:
> - /* convert_like should have created an IMPLICIT_CONV_EXPR. */
> - gcc_unreachable ();
> -
> case ADDR_EXPR:
> op1 = TREE_OPERAND (t, 0);
> if (TREE_CODE (op1) == LABEL_DECL)
> diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> new file mode 100644
> index 00000000000..4ed2501035c
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> @@ -0,0 +1,13 @@
> +// PR c++/102990
> +// { dg-do compile { target c++11 } }
> +
> +struct knob_t {
> + /* Let's create a FIX_TRUNC_EXPR. */
> + int value = 1.0;
> +};
> +
> +struct Helpers {
> + knob_t inputs;
> +};
> +
> +template<class> void f(decltype(Helpers{}));
> diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
> new file mode 100644
> index 00000000000..240cab4347a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
> @@ -0,0 +1,13 @@
> +// PR c++/102990
> +// { dg-do compile { target c++11 } }
> +
> +struct knob_t {
> + /* Let's create a FLOAT_EXPR. */
> + double value = 1UL;
> +};
> +
> +struct Helpers {
> + knob_t inputs;
> +};
> +
> +template<class> void f(decltype(Helpers{}));
>
> base-commit: 5d2233f4033dfa37ad88dc2eab138524fe64242e
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: FIX_TRUNC_EXPR in tsubst [PR102990]
2022-03-23 20:35 ` Jason Merrill
@ 2022-03-23 23:26 ` Marek Polacek
2022-03-24 13:32 ` Jason Merrill
0 siblings, 1 reply; 6+ messages in thread
From: Marek Polacek @ 2022-03-23 23:26 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Wed, Mar 23, 2022 at 04:35:32PM -0400, Jason Merrill wrote:
> On 3/22/22 19:55, Marek Polacek wrote:
> > This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
> > where it hits gcc_unreachable ().
> >
> > The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
> > was introduced in r181478, but it did the wrong thing, whereupon it
> > was turned into gcc_unreachable () in r258821 (see this thread:
> > <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
> >
> > In a template, we should never create a FIX_TRUNC_EXPR (that's what
> > conv_unsafe_in_template_p is for). But in this test we are NOT in
> > a template when we call digest_nsdmi_init which ends up calling
> > convert_like, converting 1.0e+0 to int, so convert_to_integer_1
> > gives us a FIX_TRUNC_EXPR.
> >
> > But then when we get to parsing f's parameters, we are in a template
> > when processing decltype(Helpers{}), and since r268321, when the
> > compound literal isn't instantiation-dependent and the type isn't
> > type-dependent, finish_compound_literal falls back to the normal
> > processing, so it calls digest_init, which does fold_non_dependent_init
> > and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
> > therefore crash in tsubst_copy_and_build.
>
> Hmm, we shouldn't be doing fold_non_dependent_init on the result of
> get_nsdmi. Why does that happen?
OK, so we have decltype(Helpers{}), finish_compound_literal gets
Helpers{}, it's not type-dependent, so:
- call digest_init (type=Helpers, init={})
init is BRACE_ENCLOSED_INITIALIZER_P, type is !TYPE_NON_AGGREGATE_CLASS
so go down to...
- process_init_constructor_record (type=Helpers, init={})
- we walk the fields of Helpers, there's 'inputs' of type knob_t
type_build_ctor_call (knob_t) is true, we want to default-init this
field
- create a {} as the init for default-initialization
- call massage_init_elt (type=knob_t, init={}) to adjust the init
- we do so by calling digest_init_r (type=knob_t, init={})
- here we again call process_init_constructor_record, walk knob_t's
fields, see the field 'value', it has a DECL_INITIAL, so call
get_nsdmi, that returns the FIX_TRUNC_EXPR we've created before
- so digesting {} for knob_t produced
init = {.value=(int) NON_LVALUE_EXPR <1.0e+0>}
- then we call fold_non_dependent_init on this init, and die
Do we have a mechanism to avoid folding get_nsdmi's trees that I've missed?
> > Either I can tweak p_c_e to say that a FIX_TRUNC_EXPR in a template
> > is not potentially constant, or I can just remove the whole F_T_E
> > case, since:
> > a) we could not have created an IMPLICIT_CONV_EXPR here, and
> > b) similar code, FLOAT_EXPR, is not handled here, either.
> >
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
> >
> > PR c++/102990
> >
> > gcc/cp/ChangeLog:
> >
> > * pt.cc (tsubst_copy_and_build) <case FIX_TRUNC_EXPR>: Remove.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/cpp0x/nsdmi-template22.C: New test.
> > * g++.dg/cpp0x/nsdmi-template23.C: New test.
> > ---
> > gcc/cp/pt.cc | 4 ----
> > gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C | 13 +++++++++++++
> > gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C | 13 +++++++++++++
> > 3 files changed, 26 insertions(+), 4 deletions(-)
> > create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> > create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
> >
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 715eea27577..a3becc19290 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -20184,10 +20184,6 @@ tsubst_copy_and_build (tree t,
> > templated_operator_saved_lookups (t),
> > complain|decltype_flag));
> > - case FIX_TRUNC_EXPR:
> > - /* convert_like should have created an IMPLICIT_CONV_EXPR. */
> > - gcc_unreachable ();
> > -
> > case ADDR_EXPR:
> > op1 = TREE_OPERAND (t, 0);
> > if (TREE_CODE (op1) == LABEL_DECL)
> > diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> > new file mode 100644
> > index 00000000000..4ed2501035c
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> > @@ -0,0 +1,13 @@
> > +// PR c++/102990
> > +// { dg-do compile { target c++11 } }
> > +
> > +struct knob_t {
> > + /* Let's create a FIX_TRUNC_EXPR. */
> > + int value = 1.0;
> > +};
> > +
> > +struct Helpers {
> > + knob_t inputs;
> > +};
> > +
> > +template<class> void f(decltype(Helpers{}));
> > diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
> > new file mode 100644
> > index 00000000000..240cab4347a
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
> > @@ -0,0 +1,13 @@
> > +// PR c++/102990
> > +// { dg-do compile { target c++11 } }
> > +
> > +struct knob_t {
> > + /* Let's create a FLOAT_EXPR. */
> > + double value = 1UL;
> > +};
> > +
> > +struct Helpers {
> > + knob_t inputs;
> > +};
> > +
> > +template<class> void f(decltype(Helpers{}));
> >
> > base-commit: 5d2233f4033dfa37ad88dc2eab138524fe64242e
>
Marek
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: FIX_TRUNC_EXPR in tsubst [PR102990]
2022-03-23 23:26 ` Marek Polacek
@ 2022-03-24 13:32 ` Jason Merrill
2022-03-24 17:03 ` [PATCH v2] " Marek Polacek
0 siblings, 1 reply; 6+ messages in thread
From: Jason Merrill @ 2022-03-24 13:32 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On 3/23/22 19:26, Marek Polacek wrote:
> On Wed, Mar 23, 2022 at 04:35:32PM -0400, Jason Merrill wrote:
>> On 3/22/22 19:55, Marek Polacek wrote:
>>> This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
>>> where it hits gcc_unreachable ().
>>>
>>> The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
>>> was introduced in r181478, but it did the wrong thing, whereupon it
>>> was turned into gcc_unreachable () in r258821 (see this thread:
>>> <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
>>>
>>> In a template, we should never create a FIX_TRUNC_EXPR (that's what
>>> conv_unsafe_in_template_p is for). But in this test we are NOT in
>>> a template when we call digest_nsdmi_init which ends up calling
>>> convert_like, converting 1.0e+0 to int, so convert_to_integer_1
>>> gives us a FIX_TRUNC_EXPR.
>>>
>>> But then when we get to parsing f's parameters, we are in a template
>>> when processing decltype(Helpers{}), and since r268321, when the
>>> compound literal isn't instantiation-dependent and the type isn't
>>> type-dependent, finish_compound_literal falls back to the normal
>>> processing, so it calls digest_init, which does fold_non_dependent_init
>>> and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
>>> therefore crash in tsubst_copy_and_build.
>>
>> Hmm, we shouldn't be doing fold_non_dependent_init on the result of
>> get_nsdmi. Why does that happen?
>
> OK, so we have decltype(Helpers{}), finish_compound_literal gets
> Helpers{}, it's not type-dependent, so:
>
> - call digest_init (type=Helpers, init={})
> init is BRACE_ENCLOSED_INITIALIZER_P, type is !TYPE_NON_AGGREGATE_CLASS
> so go down to...
> - process_init_constructor_record (type=Helpers, init={})
> - we walk the fields of Helpers, there's 'inputs' of type knob_t
> type_build_ctor_call (knob_t) is true, we want to default-init this
> field
> - create a {} as the init for default-initialization
> - call massage_init_elt (type=knob_t, init={}) to adjust the init
> - we do so by calling digest_init_r (type=knob_t, init={})
> - here we again call process_init_constructor_record, walk knob_t's
> fields, see the field 'value', it has a DECL_INITIAL, so call
> get_nsdmi, that returns the FIX_TRUNC_EXPR we've created before
> - so digesting {} for knob_t produced
> init = {.value=(int) NON_LVALUE_EXPR <1.0e+0>}
> - then we call fold_non_dependent_init on this init, and die
Maybe we shouldn't call fold_non_dependent_init on a CONSTRUCTOR here,
since presumably we already called it on elements that needed it in the
recursive digest_init_r.
> Do we have a mechanism to avoid folding get_nsdmi's trees that I've missed?
>
>>> Either I can tweak p_c_e to say that a FIX_TRUNC_EXPR in a template
>>> is not potentially constant, or I can just remove the whole F_T_E
>>> case, since:
>>> a) we could not have created an IMPLICIT_CONV_EXPR here, and
>>> b) similar code, FLOAT_EXPR, is not handled here, either.
>>>
>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
>>>
>>> PR c++/102990
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> * pt.cc (tsubst_copy_and_build) <case FIX_TRUNC_EXPR>: Remove.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> * g++.dg/cpp0x/nsdmi-template22.C: New test.
>>> * g++.dg/cpp0x/nsdmi-template23.C: New test.
>>> ---
>>> gcc/cp/pt.cc | 4 ----
>>> gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C | 13 +++++++++++++
>>> gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C | 13 +++++++++++++
>>> 3 files changed, 26 insertions(+), 4 deletions(-)
>>> create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
>>> create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
>>>
>>> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
>>> index 715eea27577..a3becc19290 100644
>>> --- a/gcc/cp/pt.cc
>>> +++ b/gcc/cp/pt.cc
>>> @@ -20184,10 +20184,6 @@ tsubst_copy_and_build (tree t,
>>> templated_operator_saved_lookups (t),
>>> complain|decltype_flag));
>>> - case FIX_TRUNC_EXPR:
>>> - /* convert_like should have created an IMPLICIT_CONV_EXPR. */
>>> - gcc_unreachable ();
>>> -
>>> case ADDR_EXPR:
>>> op1 = TREE_OPERAND (t, 0);
>>> if (TREE_CODE (op1) == LABEL_DECL)
>>> diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
>>> new file mode 100644
>>> index 00000000000..4ed2501035c
>>> --- /dev/null
>>> +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
>>> @@ -0,0 +1,13 @@
>>> +// PR c++/102990
>>> +// { dg-do compile { target c++11 } }
>>> +
>>> +struct knob_t {
>>> + /* Let's create a FIX_TRUNC_EXPR. */
>>> + int value = 1.0;
>>> +};
>>> +
>>> +struct Helpers {
>>> + knob_t inputs;
>>> +};
>>> +
>>> +template<class> void f(decltype(Helpers{}));
>>> diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
>>> new file mode 100644
>>> index 00000000000..240cab4347a
>>> --- /dev/null
>>> +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
>>> @@ -0,0 +1,13 @@
>>> +// PR c++/102990
>>> +// { dg-do compile { target c++11 } }
>>> +
>>> +struct knob_t {
>>> + /* Let's create a FLOAT_EXPR. */
>>> + double value = 1UL;
>>> +};
>>> +
>>> +struct Helpers {
>>> + knob_t inputs;
>>> +};
>>> +
>>> +template<class> void f(decltype(Helpers{}));
>>>
>>> base-commit: 5d2233f4033dfa37ad88dc2eab138524fe64242e
>>
>
> Marek
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2] c++: FIX_TRUNC_EXPR in tsubst [PR102990]
2022-03-24 13:32 ` Jason Merrill
@ 2022-03-24 17:03 ` Marek Polacek
2022-03-24 17:11 ` Jason Merrill
0 siblings, 1 reply; 6+ messages in thread
From: Marek Polacek @ 2022-03-24 17:03 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Thu, Mar 24, 2022 at 09:32:19AM -0400, Jason Merrill wrote:
> On 3/23/22 19:26, Marek Polacek wrote:
> > On Wed, Mar 23, 2022 at 04:35:32PM -0400, Jason Merrill wrote:
> > > On 3/22/22 19:55, Marek Polacek wrote:
> > > > This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
> > > > where it hits gcc_unreachable ().
> > > >
> > > > The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
> > > > was introduced in r181478, but it did the wrong thing, whereupon it
> > > > was turned into gcc_unreachable () in r258821 (see this thread:
> > > > <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
> > > >
> > > > In a template, we should never create a FIX_TRUNC_EXPR (that's what
> > > > conv_unsafe_in_template_p is for). But in this test we are NOT in
> > > > a template when we call digest_nsdmi_init which ends up calling
> > > > convert_like, converting 1.0e+0 to int, so convert_to_integer_1
> > > > gives us a FIX_TRUNC_EXPR.
> > > >
> > > > But then when we get to parsing f's parameters, we are in a template
> > > > when processing decltype(Helpers{}), and since r268321, when the
> > > > compound literal isn't instantiation-dependent and the type isn't
> > > > type-dependent, finish_compound_literal falls back to the normal
> > > > processing, so it calls digest_init, which does fold_non_dependent_init
> > > > and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
> > > > therefore crash in tsubst_copy_and_build.
> > >
> > > Hmm, we shouldn't be doing fold_non_dependent_init on the result of
> > > get_nsdmi. Why does that happen?
> >
> > OK, so we have decltype(Helpers{}), finish_compound_literal gets
> > Helpers{}, it's not type-dependent, so:
> >
> > - call digest_init (type=Helpers, init={})
> > init is BRACE_ENCLOSED_INITIALIZER_P, type is !TYPE_NON_AGGREGATE_CLASS
> > so go down to...
> > - process_init_constructor_record (type=Helpers, init={})
> > - we walk the fields of Helpers, there's 'inputs' of type knob_t
> > type_build_ctor_call (knob_t) is true, we want to default-init this
> > field
> > - create a {} as the init for default-initialization
> > - call massage_init_elt (type=knob_t, init={}) to adjust the init
> > - we do so by calling digest_init_r (type=knob_t, init={})
> > - here we again call process_init_constructor_record, walk knob_t's
> > fields, see the field 'value', it has a DECL_INITIAL, so call
> > get_nsdmi, that returns the FIX_TRUNC_EXPR we've created before
> > - so digesting {} for knob_t produced
> > init = {.value=(int) NON_LVALUE_EXPR <1.0e+0>}
> > - then we call fold_non_dependent_init on this init, and die
>
> Maybe we shouldn't call fold_non_dependent_init on a CONSTRUCTOR here, since
> presumably we already called it on elements that needed it in the recursive
> digest_init_r.
Ah, that works. It's still a bit weird that we don't treat FLOAT_EXPR and
FIX_TRUNC_EXPR the same.
I've tried to remove the call to fold_non_dependent_init in massage_init_elt
to see what breaks...a lot. So it has to stay at least in this form.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
Thanks,
-- >8 --
This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
where it hits gcc_unreachable ().
The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
was introduced in r181478, but it did the wrong thing, whereupon it
was turned into gcc_unreachable () in r258821 (see this thread:
<https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
In a template, we should never create a FIX_TRUNC_EXPR (that's what
conv_unsafe_in_template_p is for). But in this test we are NOT in
a template when we call digest_nsdmi_init which ends up calling
convert_like, converting 1.0e+0 to int, so convert_to_integer_1
gives us a FIX_TRUNC_EXPR.
But then when we get to parsing f's parameters, we are in a template
when processing decltype(Helpers{}), and since r268321, when the
compound literal isn't instantiation-dependent and the type isn't
type-dependent, finish_compound_literal falls back to the normal
processing, so it calls digest_init, which does fold_non_dependent_init
and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
therefore crash in tsubst_copy_and_build.
The fateful call to fold_non_dependent_init comes from massage_init_elt,
We shouldn't be calling f_n_d_i on the result of get_nsdmi. This we can
avoid by eschewing calling f_n_d_i on CONSTRUCTORs; their elements have
already been folded.
PR c++/102990
gcc/cp/ChangeLog:
* typeck2.cc (massage_init_elt): Avoid folding CONSTRUCTORs.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/nsdmi-template22.C: New test.
* g++.dg/cpp0x/nsdmi-template23.C: New test.
---
gcc/cp/typeck2.cc | 13 +++++++++----
gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C | 13 +++++++++++++
gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C | 13 +++++++++++++
3 files changed, 35 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index a4c825fc34d..cebe6acf487 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1433,10 +1433,15 @@ massage_init_elt (tree type, tree init, int nested, int flags,
new_flags |= LOOKUP_AGGREGATE_PAREN_INIT;
init = digest_init_r (type, init, nested ? 2 : 1, new_flags, complain);
/* When we defer constant folding within a statement, we may want to
- defer this folding as well. */
- tree t = fold_non_dependent_init (init, complain);
- if (TREE_CONSTANT (t))
- init = t;
+ defer this folding as well. Don't call this on CONSTRUCTORs because
+ their elements have already been folded, and we must avoid folding
+ the result of get_nsdmi. */
+ if (TREE_CODE (init) != CONSTRUCTOR)
+ {
+ tree t = fold_non_dependent_init (init, complain);
+ if (TREE_CONSTANT (t))
+ init = t;
+ }
return init;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
new file mode 100644
index 00000000000..4ed2501035c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
@@ -0,0 +1,13 @@
+// PR c++/102990
+// { dg-do compile { target c++11 } }
+
+struct knob_t {
+ /* Let's create a FIX_TRUNC_EXPR. */
+ int value = 1.0;
+};
+
+struct Helpers {
+ knob_t inputs;
+};
+
+template<class> void f(decltype(Helpers{}));
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
new file mode 100644
index 00000000000..240cab4347a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
@@ -0,0 +1,13 @@
+// PR c++/102990
+// { dg-do compile { target c++11 } }
+
+struct knob_t {
+ /* Let's create a FLOAT_EXPR. */
+ double value = 1UL;
+};
+
+struct Helpers {
+ knob_t inputs;
+};
+
+template<class> void f(decltype(Helpers{}));
base-commit: fb488cba571539b6644e8f99f1dd997cdb4c82c1
--
2.35.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2] c++: FIX_TRUNC_EXPR in tsubst [PR102990]
2022-03-24 17:03 ` [PATCH v2] " Marek Polacek
@ 2022-03-24 17:11 ` Jason Merrill
0 siblings, 0 replies; 6+ messages in thread
From: Jason Merrill @ 2022-03-24 17:11 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On 3/24/22 13:03, Marek Polacek wrote:
> On Thu, Mar 24, 2022 at 09:32:19AM -0400, Jason Merrill wrote:
>> On 3/23/22 19:26, Marek Polacek wrote:
>>> On Wed, Mar 23, 2022 at 04:35:32PM -0400, Jason Merrill wrote:
>>>> On 3/22/22 19:55, Marek Polacek wrote:
>>>>> This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
>>>>> where it hits gcc_unreachable ().
>>>>>
>>>>> The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
>>>>> was introduced in r181478, but it did the wrong thing, whereupon it
>>>>> was turned into gcc_unreachable () in r258821 (see this thread:
>>>>> <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
>>>>>
>>>>> In a template, we should never create a FIX_TRUNC_EXPR (that's what
>>>>> conv_unsafe_in_template_p is for). But in this test we are NOT in
>>>>> a template when we call digest_nsdmi_init which ends up calling
>>>>> convert_like, converting 1.0e+0 to int, so convert_to_integer_1
>>>>> gives us a FIX_TRUNC_EXPR.
>>>>>
>>>>> But then when we get to parsing f's parameters, we are in a template
>>>>> when processing decltype(Helpers{}), and since r268321, when the
>>>>> compound literal isn't instantiation-dependent and the type isn't
>>>>> type-dependent, finish_compound_literal falls back to the normal
>>>>> processing, so it calls digest_init, which does fold_non_dependent_init
>>>>> and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
>>>>> therefore crash in tsubst_copy_and_build.
>>>>
>>>> Hmm, we shouldn't be doing fold_non_dependent_init on the result of
>>>> get_nsdmi. Why does that happen?
>>>
>>> OK, so we have decltype(Helpers{}), finish_compound_literal gets
>>> Helpers{}, it's not type-dependent, so:
>>>
>>> - call digest_init (type=Helpers, init={})
>>> init is BRACE_ENCLOSED_INITIALIZER_P, type is !TYPE_NON_AGGREGATE_CLASS
>>> so go down to...
>>> - process_init_constructor_record (type=Helpers, init={})
>>> - we walk the fields of Helpers, there's 'inputs' of type knob_t
>>> type_build_ctor_call (knob_t) is true, we want to default-init this
>>> field
>>> - create a {} as the init for default-initialization
>>> - call massage_init_elt (type=knob_t, init={}) to adjust the init
>>> - we do so by calling digest_init_r (type=knob_t, init={})
>>> - here we again call process_init_constructor_record, walk knob_t's
>>> fields, see the field 'value', it has a DECL_INITIAL, so call
>>> get_nsdmi, that returns the FIX_TRUNC_EXPR we've created before
>>> - so digesting {} for knob_t produced
>>> init = {.value=(int) NON_LVALUE_EXPR <1.0e+0>}
>>> - then we call fold_non_dependent_init on this init, and die
>>
>> Maybe we shouldn't call fold_non_dependent_init on a CONSTRUCTOR here, since
>> presumably we already called it on elements that needed it in the recursive
>> digest_init_r.
>
> Ah, that works. It's still a bit weird that we don't treat FLOAT_EXPR and
> FIX_TRUNC_EXPR the same.
>
> I've tried to remove the call to fold_non_dependent_init in massage_init_elt
> to see what breaks...a lot. So it has to stay at least in this form.
>
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
OK.
> Thanks,
>
> -- >8 --
> This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
> where it hits gcc_unreachable ().
>
> The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
> was introduced in r181478, but it did the wrong thing, whereupon it
> was turned into gcc_unreachable () in r258821 (see this thread:
> <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
>
> In a template, we should never create a FIX_TRUNC_EXPR (that's what
> conv_unsafe_in_template_p is for). But in this test we are NOT in
> a template when we call digest_nsdmi_init which ends up calling
> convert_like, converting 1.0e+0 to int, so convert_to_integer_1
> gives us a FIX_TRUNC_EXPR.
>
> But then when we get to parsing f's parameters, we are in a template
> when processing decltype(Helpers{}), and since r268321, when the
> compound literal isn't instantiation-dependent and the type isn't
> type-dependent, finish_compound_literal falls back to the normal
> processing, so it calls digest_init, which does fold_non_dependent_init
> and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
> therefore crash in tsubst_copy_and_build.
>
> The fateful call to fold_non_dependent_init comes from massage_init_elt,
> We shouldn't be calling f_n_d_i on the result of get_nsdmi. This we can
> avoid by eschewing calling f_n_d_i on CONSTRUCTORs; their elements have
> already been folded.
>
> PR c++/102990
>
> gcc/cp/ChangeLog:
>
> * typeck2.cc (massage_init_elt): Avoid folding CONSTRUCTORs.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp0x/nsdmi-template22.C: New test.
> * g++.dg/cpp0x/nsdmi-template23.C: New test.
> ---
> gcc/cp/typeck2.cc | 13 +++++++++----
> gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C | 13 +++++++++++++
> gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C | 13 +++++++++++++
> 3 files changed, 35 insertions(+), 4 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
>
> diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
> index a4c825fc34d..cebe6acf487 100644
> --- a/gcc/cp/typeck2.cc
> +++ b/gcc/cp/typeck2.cc
> @@ -1433,10 +1433,15 @@ massage_init_elt (tree type, tree init, int nested, int flags,
> new_flags |= LOOKUP_AGGREGATE_PAREN_INIT;
> init = digest_init_r (type, init, nested ? 2 : 1, new_flags, complain);
> /* When we defer constant folding within a statement, we may want to
> - defer this folding as well. */
> - tree t = fold_non_dependent_init (init, complain);
> - if (TREE_CONSTANT (t))
> - init = t;
> + defer this folding as well. Don't call this on CONSTRUCTORs because
> + their elements have already been folded, and we must avoid folding
> + the result of get_nsdmi. */
> + if (TREE_CODE (init) != CONSTRUCTOR)
> + {
> + tree t = fold_non_dependent_init (init, complain);
> + if (TREE_CONSTANT (t))
> + init = t;
> + }
> return init;
> }
>
> diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> new file mode 100644
> index 00000000000..4ed2501035c
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> @@ -0,0 +1,13 @@
> +// PR c++/102990
> +// { dg-do compile { target c++11 } }
> +
> +struct knob_t {
> + /* Let's create a FIX_TRUNC_EXPR. */
> + int value = 1.0;
> +};
> +
> +struct Helpers {
> + knob_t inputs;
> +};
> +
> +template<class> void f(decltype(Helpers{}));
> diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
> new file mode 100644
> index 00000000000..240cab4347a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
> @@ -0,0 +1,13 @@
> +// PR c++/102990
> +// { dg-do compile { target c++11 } }
> +
> +struct knob_t {
> + /* Let's create a FLOAT_EXPR. */
> + double value = 1UL;
> +};
> +
> +struct Helpers {
> + knob_t inputs;
> +};
> +
> +template<class> void f(decltype(Helpers{}));
>
> base-commit: fb488cba571539b6644e8f99f1dd997cdb4c82c1
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-03-24 17:11 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-22 23:55 [PATCH] c++: FIX_TRUNC_EXPR in tsubst [PR102990] Marek Polacek
2022-03-23 20:35 ` Jason Merrill
2022-03-23 23:26 ` Marek Polacek
2022-03-24 13:32 ` Jason Merrill
2022-03-24 17:03 ` [PATCH v2] " Marek Polacek
2022-03-24 17:11 ` 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).