Hi, When c-typeck.cc:c_build_qualified_type builds an array type from its element type, it does not copy the address space of the element type to the array type itself. This is unlike tree.cc:build_array_type_1, which explicitly does
TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type); This causes the ICE described in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86869. struct S { char y[2]; }; extern const __memx struct S *s; extern void bar(const __memx void*); void foo(void) { bar(&s->y); } build_component_ref calls c_build_qualified_type, passing in the array type and quals including the address space (ADDR_SPACE_MEMX in this case). Because of this missing address space copy, the returned array type remains in the generic address space. Later down the line, expand_expr_addr_expr detects the mismatch in address space/mode and tries to convert, and that leads to the ICE described in the bug. This patch sets the address space of the array type to that of the element type. Regression tests for avr look ok. Ok for trunk? Regards Senthil PR 86869 gcc/c/ChangeLog: * c-typeck.cc (c_build_qualified_type): Set TYPE_ADDR_SPACE for ARRAY_TYPE. gcc/testsuite/ChangeLog: * gcc.target/avr/pr86869.c: New test. diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 22e240a3c2a..d4ab1d1bd46 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -16284,6 +16284,7 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, t = build_variant_type_copy (type); TREE_TYPE (t) = element_type; + TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (element_type); if (TYPE_STRUCTURAL_EQUALITY_P (element_type) || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain))) diff --git a/gcc/testsuite/gcc.target/avr/pr86869.c b/gcc/testsuite/gcc.target/avr/pr86869.c new file mode 100644 index 00000000000..54cd984276e --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr86869.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-std=gnu99" } */ + +extern void bar(const __memx void* p); + +struct S { + char y[2]; +}; +extern const __memx struct S *s; + +void foo(void) { + bar(&s->y); +}