2018-04-23 Eric Botcazou PR middle-end/85496 * expr.c (store_field): In the bitfield case, if the value comes from a function call and is returned in registers by means of a PARALLEL, do not change the mode of the temporary unless BLKmode and VOIDmode. * g++.dg/torture/pr85496.C: New test. --- gcc/testsuite/g++.dg/torture/pr85496.C (nonexistent) +++ gcc/testsuite/g++.dg/torture/pr85496.C (revision 259576) @@ -0,0 +1,18 @@ +// PR middle-end/85496 +// Reported by Marek Polacek + +template class complex; +template complex<_Tp> operator*(complex<_Tp>, complex<_Tp>); +template <> struct complex { _Complex float _M_value; }; +class A { + complex _f0, _f1; + +public: + complex &m_fn1() { return _f1; } +}; +complex a; +void cos() { + A b; + complex c; + b.m_fn1() = c * a; +} --- gcc/expr.c (revision 259575) +++ gcc/expr.c (revision 259576) @@ -6893,8 +6893,9 @@ if (GET_CODE (temp) == PARALLEL) { HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp)); - machine_mode temp_mode - = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT); + machine_mode temp_mode = GET_MODE (temp); + if (temp_mode == BLKmode || temp_mode == VOIDmode) + temp_mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT); rtx temp_target = gen_reg_rtx (temp_mode); emit_group_store (temp_target, temp, TREE_TYPE (exp), size); temp = temp_target;