On 4/28/21 10:22 AM, Andreas Krebbel via Gcc-patches wrote: > 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.
build_pointer_type just calls build_pointer_type_for_mode. I'll drop the check then and re-test. > >> >>> 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 >>> >