On 4/28/21 10:12 AM, Richard Biener wrote:
> On Wed, Apr 28, 2021 at 8:54 AM Andreas Krebbel via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
>>
>> The problem appears to be triggered by two locations in the front-end
>> where non-POINTER_SIZE pointers aren't handled right now.
>>
>> 1. An assertion in strip_typedefs is triggered because the alignment
>> of the types don't match. This in turn is caused by creating the new
>> type with build_pointer_type instead of taking the type of the
>> original pointer into account.
>>
>> 2. An assertion in cp_convert_to_pointer is triggered which expects
>> the target type to always have POINTER_SIZE.
>>
>> Ok for mainline?
>>
>> gcc/cp/ChangeLog:
>>
>>         PR c++/100281
>>         * cvt.c (cp_convert_to_pointer): Use the size of the target
>>         pointer type.
>>         * tree.c (strip_typedefs): Use build_pointer_type_for_mode for
>>         non-POINTER_SIZE pointers.
>>
>> gcc/testsuite/ChangeLog:
>>
>>         PR c++/100281
>>         * g++.target/s390/pr100281.C: New test.
>> ---
>>  gcc/cp/cvt.c                             |  2 +-
>>  gcc/cp/tree.c                            |  5 ++++-
>>  gcc/testsuite/g++.target/s390/pr100281.C | 10 ++++++++++
>>  3 files changed, 15 insertions(+), 2 deletions(-)
>>  create mode 100644 gcc/testsuite/g++.target/s390/pr100281.C
>>
>> diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
>> index f1687e804d1..7fa6e8df52b 100644
>> --- a/gcc/cp/cvt.c
>> +++ b/gcc/cp/cvt.c
>> @@ -232,7 +232,7 @@ cp_convert_to_pointer (tree type, tree expr, bool dofold,
>>      {
>>        if (TYPE_PRECISION (intype) == POINTER_SIZE)
>>         return build1 (CONVERT_EXPR, type, expr);
>> -      expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr,
>> +      expr = cp_convert (c_common_type_for_size (TYPE_PRECISION (type), 0), 
>> expr,
>>                          complain);
>>        /* Modes may be different but sizes should be the same.  There
>>          is supposed to be some integral type that is the same width
>> diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
>> index a8bfd5fc053..6f6b732c9c9 100644
>> --- a/gcc/cp/tree.c
>> +++ b/gcc/cp/tree.c
>> @@ -1556,7 +1556,10 @@ strip_typedefs (tree t, bool *remove_attributes, 
>> unsigned int flags)
>>      {
>>      case POINTER_TYPE:
>>        type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
>> -      result = build_pointer_type (type);
>> +      if (TYPE_PRECISION (t) == POINTER_SIZE)
>> +       result = build_pointer_type (type);
>> +      else
>> +       result = build_pointer_type_for_mode (type, TYPE_MODE (t), false);
> 
> I wonder under which circumstances re-using the original mode will fail?  In
> particular I do not like the TYPE_PRECISION check.  Supposedly you
> were thinking of playing safe?

Yes. build_pointer_type_for_mode carries some additional logic compared to just 
build_pointer_type
and I wanted to avoid impacting other targets that way.

> 
>>        break;
>>      case REFERENCE_TYPE:
>>        type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
> 
> There's code below with exactly the same issue for reference types which
> would need adjustments to cp_build_reference_type.

Ok. I'll have a look.

Andreas

> 
>> diff --git a/gcc/testsuite/g++.target/s390/pr100281.C 
>> b/gcc/testsuite/g++.target/s390/pr100281.C
>> new file mode 100644
>> index 00000000000..f45798c3879
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.target/s390/pr100281.C
>> @@ -0,0 +1,10 @@
>> +// PR C++/100281
>> +// { dg-do compile }
>> +
>> +typedef void * __attribute__((mode (SI))) __ptr32_t;
>> +
>> +void foo(){
>> +  unsigned int b = 100;
>> +  __ptr32_t a;
>> +  a = b; /* { dg-error "invalid conversion from 'unsigned int' to 
>> '__ptr32_t'.*" } */
>> +}
>> --
>> 2.30.2
>>

Reply via email to