Hi! At expansion time, we in various cases choose to assign_temp and ICE in that case on any expressions with TREE_ADDRESSABLE types. We don't want to create any temporaries for such types, the var needs to live in memory and if the constraint doesn't allow mem, we should just reject it as invalid.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/8.2? 2018-05-06 Jakub Jelinek <ja...@redhat.com> PR c++/85659 * cfgexpand.c (expand_asm_stmt): Don't create a temporary if the type is addressable. Don't force op into register if it has BLKmode. * g++.dg/ext/asm14.C: New test. * g++.dg/ext/asm15.C: New test. * g++.dg/ext/asm16.C: New test. --- gcc/cfgexpand.c.jj 2018-03-27 12:54:43.000000000 +0200 +++ gcc/cfgexpand.c 2018-05-05 13:28:44.037551377 +0200 @@ -3044,14 +3044,14 @@ expand_asm_stmt (gasm *stmt) generating_concat_p = 0; - if ((TREE_CODE (val) == INDIRECT_REF - && allows_mem) + if ((TREE_CODE (val) == INDIRECT_REF && allows_mem) || (DECL_P (val) && (allows_mem || REG_P (DECL_RTL (val))) && ! (REG_P (DECL_RTL (val)) && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))) || ! allows_reg - || is_inout) + || is_inout + || TREE_ADDRESSABLE (type)) { op = expand_expr (val, NULL_RTX, VOIDmode, !allows_reg ? EXPAND_MEMORY : EXPAND_WRITE); @@ -3060,7 +3060,7 @@ expand_asm_stmt (gasm *stmt) if (! allows_reg && !MEM_P (op)) error ("output number %d not directly addressable", i); - if ((! allows_mem && MEM_P (op)) + if ((! allows_mem && MEM_P (op) && GET_MODE (op) != BLKmode) || GET_CODE (op) == CONCAT) { rtx old_op = op; --- gcc/testsuite/g++.dg/ext/asm14.C.jj 2018-05-05 13:15:50.099258834 +0200 +++ gcc/testsuite/g++.dg/ext/asm14.C 2018-05-05 13:19:09.717327528 +0200 @@ -0,0 +1,10 @@ +// PR c++/85659 +// { dg-do compile } + +struct S { S (); ~S (); int s; }; + +void +foo (S &s) +{ + __asm volatile ("" : "+m,r" (s) : : "memory"); +} --- gcc/testsuite/g++.dg/ext/asm15.C.jj 2018-05-05 13:15:56.656261090 +0200 +++ gcc/testsuite/g++.dg/ext/asm15.C 2018-05-05 13:19:15.125329389 +0200 @@ -0,0 +1,10 @@ +// PR c++/85659 +// { dg-do compile } + +struct S { S (); ~S (); int s; }; + +void +foo (S &s) +{ + __asm volatile ("" : "+r" (s) : : "memory"); // { dg-error "" } +} --- gcc/testsuite/g++.dg/ext/asm16.C.jj 2018-05-05 13:28:03.448530441 +0200 +++ gcc/testsuite/g++.dg/ext/asm16.C 2018-05-05 13:28:21.068539532 +0200 @@ -0,0 +1,10 @@ +// PR c++/85659 +// { dg-do compile } + +struct S { S (); ~S (); int s[64]; } s; + +void +foo () +{ + __asm volatile ("" : "=r" (s) : : "memory"); // { dg-error "" } +} Jakub