c++: ICE with __has_unique_object_representations [PR115476]

Message ID 20240618143157.31204-1-polacek@redhat.com
State Committed
Commit fc382a373e6824bb998007d1dcb0805b0cf4b8e8
Headers
Series c++: ICE with __has_unique_object_representations [PR115476] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Marek Polacek June 18, 2024, 2:31 p.m. UTC
  Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14/13?

-- >8 --
Here we started to ICE with r13-25: in check_trait_type, for "X[]" we
return true here:

  if (kind == 1 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
    return true; // Array of unknown bound. Don't care about completeness.

and then end up crashing in record_has_unique_obj_representations:

4836	  if (cur != wi::to_offset (sz))

because sz is null.

https://eel.is/c++draft/type.traits#tab:meta.unary.prop-row-47-column-3-sentence-1
says that the preconditions for __has_unique_object_representations are:
"T shall be a complete type, cv void, or an array of unknown bound" and
that "For an array type T, the same result as
has_unique_object_representations_v<remove_all_extents_t<T>>" so T[]
should be treated as T.  So we should use kind==2 for the trait.

	PR c++/115476

gcc/cp/ChangeLog:

	* semantics.cc (finish_trait_expr)
	<case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS>: Move below to call
	check_trait_type with kind==2.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp1z/has-unique-obj-representations4.C: New test.
---
 gcc/cp/semantics.cc                              |  2 +-
 .../cpp1z/has-unique-obj-representations4.C      | 16 ++++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C


base-commit: 7f9be55a4630134a237219af9cc8143e02080380
  

Comments

Jason Merrill June 25, 2024, 2:12 a.m. UTC | #1
On 6/18/24 10:31, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14/13?

Makes sense to me, though probably the [meta.unary.prop] table should be 
adjusted in the same way.  Jonathan, what do you think?

> -- >8 --
> Here we started to ICE with r13-25: in check_trait_type, for "X[]" we
> return true here:
> 
>    if (kind == 1 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
>      return true; // Array of unknown bound. Don't care about completeness.
> 
> and then end up crashing in record_has_unique_obj_representations:
> 
> 4836	  if (cur != wi::to_offset (sz))
> 
> because sz is null.
> 
> https://eel.is/c++draft/type.traits#tab:meta.unary.prop-row-47-column-3-sentence-1
> says that the preconditions for __has_unique_object_representations are:
> "T shall be a complete type, cv void, or an array of unknown bound" and
> that "For an array type T, the same result as
> has_unique_object_representations_v<remove_all_extents_t<T>>" so T[]
> should be treated as T.  So we should use kind==2 for the trait.
> 
> 	PR c++/115476
> 
> gcc/cp/ChangeLog:
> 
> 	* semantics.cc (finish_trait_expr)
> 	<case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS>: Move below to call
> 	check_trait_type with kind==2.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp1z/has-unique-obj-representations4.C: New test.
> ---
>   gcc/cp/semantics.cc                              |  2 +-
>   .../cpp1z/has-unique-obj-representations4.C      | 16 ++++++++++++++++
>   2 files changed, 17 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
> 
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 08f5f245e7d..42251b6764b 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12966,7 +12966,6 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>       case CPTK_HAS_NOTHROW_COPY:
>       case CPTK_HAS_TRIVIAL_COPY:
>       case CPTK_HAS_TRIVIAL_DESTRUCTOR:
> -    case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
>         if (!check_trait_type (type1))
>   	return error_mark_node;
>         break;
> @@ -12976,6 +12975,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>       case CPTK_IS_STD_LAYOUT:
>       case CPTK_IS_TRIVIAL:
>       case CPTK_IS_TRIVIALLY_COPYABLE:
> +    case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
>         if (!check_trait_type (type1, /* kind = */ 2))
>   	return error_mark_node;
>         break;
> diff --git a/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
> new file mode 100644
> index 00000000000..d6949dc7005
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
> @@ -0,0 +1,16 @@
> +// PR c++/115476
> +// { dg-do compile { target c++11 } }
> +
> +struct X;
> +static_assert(__has_unique_object_representations(X), "");	  // { dg-error "invalid use of incomplete type" }
> +static_assert(__has_unique_object_representations(X[]), "");  // { dg-error "invalid use of incomplete type" }
> +static_assert(__has_unique_object_representations(X[1]), "");  // { dg-error "invalid use of incomplete type" }
> +static_assert(__has_unique_object_representations(X[][1]), "");  // { dg-error "invalid use of incomplete type" }
> +
> +struct X {
> +  int x;
> +};
> +static_assert(__has_unique_object_representations(X), "");
> +static_assert(__has_unique_object_representations(X[]), "");
> +static_assert(__has_unique_object_representations(X[1]), "");
> +static_assert(__has_unique_object_representations(X[][1]), "");
> 
> base-commit: 7f9be55a4630134a237219af9cc8143e02080380
  
Jonathan Wakely June 25, 2024, 11:15 a.m. UTC | #2
On Tue, 25 Jun 2024 at 03:12, Jason Merrill <jason@redhat.com> wrote:
>
> On 6/18/24 10:31, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14/13?
>
> Makes sense to me, though probably the [meta.unary.prop] table should be
> adjusted in the same way.  Jonathan, what do you think?

Just to make sure I understand correctly, the suggestion is to change
the precondition for the trait to something like:

"remove_all_extents_t<T> shall be a complete type or cv void."

i.e. if T is incomplete then T[] cannot be used with the trait, right?

>
> > -- >8 --
> > Here we started to ICE with r13-25: in check_trait_type, for "X[]" we
> > return true here:
> >
> >    if (kind == 1 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
> >      return true; // Array of unknown bound. Don't care about completeness.
> >
> > and then end up crashing in record_has_unique_obj_representations:
> >
> > 4836    if (cur != wi::to_offset (sz))
> >
> > because sz is null.
> >
> > https://eel.is/c++draft/type.traits#tab:meta.unary.prop-row-47-column-3-sentence-1
> > says that the preconditions for __has_unique_object_representations are:
> > "T shall be a complete type, cv void, or an array of unknown bound" and
> > that "For an array type T, the same result as
> > has_unique_object_representations_v<remove_all_extents_t<T>>" so T[]
> > should be treated as T.  So we should use kind==2 for the trait.
> >
> >       PR c++/115476
> >
> > gcc/cp/ChangeLog:
> >
> >       * semantics.cc (finish_trait_expr)
> >       <case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS>: Move below to call
> >       check_trait_type with kind==2.
> >
> > gcc/testsuite/ChangeLog:
> >
> >       * g++.dg/cpp1z/has-unique-obj-representations4.C: New test.
> > ---
> >   gcc/cp/semantics.cc                              |  2 +-
> >   .../cpp1z/has-unique-obj-representations4.C      | 16 ++++++++++++++++
> >   2 files changed, 17 insertions(+), 1 deletion(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
> >
> > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > index 08f5f245e7d..42251b6764b 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -12966,7 +12966,6 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
> >       case CPTK_HAS_NOTHROW_COPY:
> >       case CPTK_HAS_TRIVIAL_COPY:
> >       case CPTK_HAS_TRIVIAL_DESTRUCTOR:
> > -    case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
> >         if (!check_trait_type (type1))
> >       return error_mark_node;
> >         break;
> > @@ -12976,6 +12975,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
> >       case CPTK_IS_STD_LAYOUT:
> >       case CPTK_IS_TRIVIAL:
> >       case CPTK_IS_TRIVIALLY_COPYABLE:
> > +    case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
> >         if (!check_trait_type (type1, /* kind = */ 2))
> >       return error_mark_node;
> >         break;
> > diff --git a/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
> > new file mode 100644
> > index 00000000000..d6949dc7005
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
> > @@ -0,0 +1,16 @@
> > +// PR c++/115476
> > +// { dg-do compile { target c++11 } }
> > +
> > +struct X;
> > +static_assert(__has_unique_object_representations(X), "");     // { dg-error "invalid use of incomplete type" }
> > +static_assert(__has_unique_object_representations(X[]), "");  // { dg-error "invalid use of incomplete type" }
> > +static_assert(__has_unique_object_representations(X[1]), "");  // { dg-error "invalid use of incomplete type" }
> > +static_assert(__has_unique_object_representations(X[][1]), "");  // { dg-error "invalid use of incomplete type" }
> > +
> > +struct X {
> > +  int x;
> > +};
> > +static_assert(__has_unique_object_representations(X), "");
> > +static_assert(__has_unique_object_representations(X[]), "");
> > +static_assert(__has_unique_object_representations(X[1]), "");
> > +static_assert(__has_unique_object_representations(X[][1]), "");
> >
> > base-commit: 7f9be55a4630134a237219af9cc8143e02080380
>
  
Jason Merrill June 25, 2024, 3:17 p.m. UTC | #3
On 6/25/24 07:15, Jonathan Wakely wrote:
> On Tue, 25 Jun 2024 at 03:12, Jason Merrill <jason@redhat.com> wrote:
>>
>> On 6/18/24 10:31, Marek Polacek wrote:
>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14/13?
>>
>> Makes sense to me, though probably the [meta.unary.prop] table should be
>> adjusted in the same way.  Jonathan, what do you think?
> 
> Just to make sure I understand correctly, the suggestion is to change
> the precondition for the trait to something like:
> 
> "remove_all_extents_t<T> shall be a complete type or cv void."
> 
> i.e. if T is incomplete then T[] cannot be used with the trait, right?

Yes.

Jason

>>
>>> -- >8 --
>>> Here we started to ICE with r13-25: in check_trait_type, for "X[]" we
>>> return true here:
>>>
>>>     if (kind == 1 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
>>>       return true; // Array of unknown bound. Don't care about completeness.
>>>
>>> and then end up crashing in record_has_unique_obj_representations:
>>>
>>> 4836    if (cur != wi::to_offset (sz))
>>>
>>> because sz is null.
>>>
>>> https://eel.is/c++draft/type.traits#tab:meta.unary.prop-row-47-column-3-sentence-1
>>> says that the preconditions for __has_unique_object_representations are:
>>> "T shall be a complete type, cv void, or an array of unknown bound" and
>>> that "For an array type T, the same result as
>>> has_unique_object_representations_v<remove_all_extents_t<T>>" so T[]
>>> should be treated as T.  So we should use kind==2 for the trait.
>>>
>>>        PR c++/115476
>>>
>>> gcc/cp/ChangeLog:
>>>
>>>        * semantics.cc (finish_trait_expr)
>>>        <case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS>: Move below to call
>>>        check_trait_type with kind==2.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>>        * g++.dg/cpp1z/has-unique-obj-representations4.C: New test.
>>> ---
>>>    gcc/cp/semantics.cc                              |  2 +-
>>>    .../cpp1z/has-unique-obj-representations4.C      | 16 ++++++++++++++++
>>>    2 files changed, 17 insertions(+), 1 deletion(-)
>>>    create mode 100644 gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
>>>
>>> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
>>> index 08f5f245e7d..42251b6764b 100644
>>> --- a/gcc/cp/semantics.cc
>>> +++ b/gcc/cp/semantics.cc
>>> @@ -12966,7 +12966,6 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>>>        case CPTK_HAS_NOTHROW_COPY:
>>>        case CPTK_HAS_TRIVIAL_COPY:
>>>        case CPTK_HAS_TRIVIAL_DESTRUCTOR:
>>> -    case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
>>>          if (!check_trait_type (type1))
>>>        return error_mark_node;
>>>          break;
>>> @@ -12976,6 +12975,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>>>        case CPTK_IS_STD_LAYOUT:
>>>        case CPTK_IS_TRIVIAL:
>>>        case CPTK_IS_TRIVIALLY_COPYABLE:
>>> +    case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
>>>          if (!check_trait_type (type1, /* kind = */ 2))
>>>        return error_mark_node;
>>>          break;
>>> diff --git a/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
>>> new file mode 100644
>>> index 00000000000..d6949dc7005
>>> --- /dev/null
>>> +++ b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
>>> @@ -0,0 +1,16 @@
>>> +// PR c++/115476
>>> +// { dg-do compile { target c++11 } }
>>> +
>>> +struct X;
>>> +static_assert(__has_unique_object_representations(X), "");     // { dg-error "invalid use of incomplete type" }
>>> +static_assert(__has_unique_object_representations(X[]), "");  // { dg-error "invalid use of incomplete type" }
>>> +static_assert(__has_unique_object_representations(X[1]), "");  // { dg-error "invalid use of incomplete type" }
>>> +static_assert(__has_unique_object_representations(X[][1]), "");  // { dg-error "invalid use of incomplete type" }
>>> +
>>> +struct X {
>>> +  int x;
>>> +};
>>> +static_assert(__has_unique_object_representations(X), "");
>>> +static_assert(__has_unique_object_representations(X[]), "");
>>> +static_assert(__has_unique_object_representations(X[1]), "");
>>> +static_assert(__has_unique_object_representations(X[][1]), "");
>>>
>>> base-commit: 7f9be55a4630134a237219af9cc8143e02080380
>>
>
  
Jonathan Wakely June 25, 2024, 5:22 p.m. UTC | #4
On Tue, 25 Jun 2024 at 16:17, Jason Merrill <jason@redhat.com> wrote:
>
> On 6/25/24 07:15, Jonathan Wakely wrote:
> > On Tue, 25 Jun 2024 at 03:12, Jason Merrill <jason@redhat.com> wrote:
> >>
> >> On 6/18/24 10:31, Marek Polacek wrote:
> >>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14/13?
> >>
> >> Makes sense to me, though probably the [meta.unary.prop] table should be
> >> adjusted in the same way.  Jonathan, what do you think?
> >
> > Just to make sure I understand correctly, the suggestion is to change
> > the precondition for the trait to something like:
> >
> > "remove_all_extents_t<T> shall be a complete type or cv void."
> >
> > i.e. if T is incomplete then T[] cannot be used with the trait, right?
>
> Yes.

Thanks. This is now https://cplusplus.github.io/LWG/issue4113
  
Marek Polacek June 25, 2024, 7:07 p.m. UTC | #5
On Tue, Jun 25, 2024 at 06:22:56PM +0100, Jonathan Wakely wrote:
> On Tue, 25 Jun 2024 at 16:17, Jason Merrill <jason@redhat.com> wrote:
> >
> > On 6/25/24 07:15, Jonathan Wakely wrote:
> > > On Tue, 25 Jun 2024 at 03:12, Jason Merrill <jason@redhat.com> wrote:
> > >>
> > >> On 6/18/24 10:31, Marek Polacek wrote:
> > >>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14/13?
> > >>
> > >> Makes sense to me, though probably the [meta.unary.prop] table should be
> > >> adjusted in the same way.  Jonathan, what do you think?
> > >
> > > Just to make sure I understand correctly, the suggestion is to change
> > > the precondition for the trait to something like:
> > >
> > > "remove_all_extents_t<T> shall be a complete type or cv void."
> > >
> > > i.e. if T is incomplete then T[] cannot be used with the trait, right?
> >
> > Yes.
> 
> Thanks. This is now https://cplusplus.github.io/LWG/issue4113

Looks good.  Should I push my patch now? 

Marek
  
Jason Merrill June 25, 2024, 9:23 p.m. UTC | #6
On 6/25/24 15:07, Marek Polacek wrote:
> On Tue, Jun 25, 2024 at 06:22:56PM +0100, Jonathan Wakely wrote:
>> On Tue, 25 Jun 2024 at 16:17, Jason Merrill <jason@redhat.com> wrote:
>>>
>>> On 6/25/24 07:15, Jonathan Wakely wrote:
>>>> On Tue, 25 Jun 2024 at 03:12, Jason Merrill <jason@redhat.com> wrote:
>>>>>
>>>>> On 6/18/24 10:31, Marek Polacek wrote:
>>>>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14/13?
>>>>>
>>>>> Makes sense to me, though probably the [meta.unary.prop] table should be
>>>>> adjusted in the same way.  Jonathan, what do you think?
>>>>
>>>> Just to make sure I understand correctly, the suggestion is to change
>>>> the precondition for the trait to something like:
>>>>
>>>> "remove_all_extents_t<T> shall be a complete type or cv void."
>>>>
>>>> i.e. if T is incomplete then T[] cannot be used with the trait, right?
>>>
>>> Yes.
>>
>> Thanks. This is now https://cplusplus.github.io/LWG/issue4113
> 
> Looks good.  Should I push my patch now?

Yes, please.

Jason
  

Patch

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 08f5f245e7d..42251b6764b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12966,7 +12966,6 @@  finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_HAS_NOTHROW_COPY:
     case CPTK_HAS_TRIVIAL_COPY:
     case CPTK_HAS_TRIVIAL_DESTRUCTOR:
-    case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
       if (!check_trait_type (type1))
 	return error_mark_node;
       break;
@@ -12976,6 +12975,7 @@  finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_STD_LAYOUT:
     case CPTK_IS_TRIVIAL:
     case CPTK_IS_TRIVIALLY_COPYABLE:
+    case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
       if (!check_trait_type (type1, /* kind = */ 2))
 	return error_mark_node;
       break;
diff --git a/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
new file mode 100644
index 00000000000..d6949dc7005
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations4.C
@@ -0,0 +1,16 @@ 
+// PR c++/115476
+// { dg-do compile { target c++11 } }
+
+struct X;
+static_assert(__has_unique_object_representations(X), "");	  // { dg-error "invalid use of incomplete type" }
+static_assert(__has_unique_object_representations(X[]), "");  // { dg-error "invalid use of incomplete type" }
+static_assert(__has_unique_object_representations(X[1]), "");  // { dg-error "invalid use of incomplete type" }
+static_assert(__has_unique_object_representations(X[][1]), "");  // { dg-error "invalid use of incomplete type" }
+
+struct X {
+  int x;
+};
+static_assert(__has_unique_object_representations(X), "");
+static_assert(__has_unique_object_representations(X[]), "");
+static_assert(__has_unique_object_representations(X[1]), "");
+static_assert(__has_unique_object_representations(X[][1]), "");