https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78687
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |missed-optimization Status|UNCONFIRMED |NEW Last reconfirmed| |2016-12-06 CC| |jamborm at gcc dot gnu.org, | |rguenth at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- Trunk rejects it with (might be worth another bug?) t.C: In function ‘ref_proxy<qual_option, inplace_ref<qual_option> > make_object_4(ref_proxy<option_2, variant_ref<option_1, option_2> >&&)’: t.C:469:39: error: conversion from ‘inplace_ref<qual_option>’ to ‘ref_proxy<qual_option, inplace_ref<qual_option> >’ is ambiguous return make_object_3(std::move(a0)); ^ t.C:394:8: note: candidate: constexpr inplace_ref<qual_option>::inplace_ref(const inplace_ref<qual_option>&) struct inplace_ref ^~~~~~~~~~~ t.C:380:17: note: inherited here using Base::Base; ^~~~ t.C:394:8: note: candidate: constexpr inplace_ref<qual_option>::inplace_ref(inplace_ref<qual_option>&&) struct inplace_ref ^~~~~~~~~~~ t.C:380:17: note: inherited here using Base::Base; ^~~~ t.C:387:5: note: candidate: ref_proxy<T, Base>::ref_proxy(Base) [with T = qual_option; Base = inplace_ref<qual_option>] ref_proxy(Base ptr) ^~~~~~~~~ Confirmed with GCC 6.2 - we have quite many aggregate temporaries not optimized away: __attribute__((noinline)) ref_proxy<qual_option, inplace_ref<qual_option> > f() () { struct qual_optionD.34988 D.41115; struct ref_proxyD.34990 D.41114; struct qual_optionD.34988 innerD.41113; struct ref_proxyD.34990 typeD.41111; struct ref_proxyD.34990 typeD.41112; struct ref_proxyD.36874 D.41109; struct ref_proxyD.36874 ptrD.41110; struct inplace_refD.37561 D.41107; struct inplace_refD.37561 ptrD.41106; <bb 2>: MEM[(struct ref_proxyD.36874 *)&D.41109 + 40B] = 2; ptrD.41110 = D.41109; MEM[(struct &)&D.41114] ={v} {CLOBBER}; MEM[(struct variantD.35001 *)&ptrD.41110 + 40B] = 2; MEM[(struct variant_refD.34986 *)&D.41114].inner_storage_D.35021 = ptrD.41110.D.36914.inner_storage_D.35021; MEM[(struct ref_proxyD.34990 *)&D.41114 + 40B] = 2; typeD.41111 = D.41114; MEM[(struct ref_proxyD.34990 *)&typeD.41111 + 40B] = 2; typeD.41112 = typeD.41111; MEM[(struct &)&D.41115] ={v} {CLOBBER}; MEM[(struct ref_proxyD.34990 *)&typeD.41112 + 40B] = 2; D.41115.type_D.36509 = typeD.41112; MEM[(struct qual_optionD.34988 *)&D.41115 + 40B] = 2; MEM[(struct qual_optionD.34988 *)&D.41115 + 48B] = 0; innerD.41113 = D.41115; MEM[(struct &)&D.41107] ={v} {CLOBBER}; MEM[(struct qual_optionD.34988 *)&innerD.41113 + 48B] = 0; D.41107.inner_D.37568 = innerD.41113; D.41115 ={v} {CLOBBER}; D.41114 ={v} {CLOBBER}; MEM[(struct inplace_refD.37561 *)&D.41107 + 48B] = 0; ptrD.41106 = D.41107; MEM[(struct &)&<retval>] ={v} {CLOBBER}; MEM[(struct inplace_refD.37561 *)&ptrD.41106 + 48B] = 0; <retval>.D.37651 = ptrD.41106; return <retval>; } it usually is SRAs job to do this but it seems to fail in this case: <bb 2>: MEM[(struct &)&D.37695] ={v} {CLOBBER}; SR.31_24 = 2; MEM[(struct ref_proxyD.36874 *)&D.41109 + 40B] = SR.31_24; SR.34_26 = SR.31_24; MEM[(struct ref_proxyD.36874 *)&D.41109 + 40B] = SR.34_26; ptrD.41110 = D.41109; ^^^ aggregate copy not scalarized ptr$D36914$inner_storage_$_storage$_which_28 = SR.34_26; MEM[(struct &)&D.41114] ={v} {CLOBBER}; MEM[(struct variantD.35001 *)&ptrD.41110 + 40B] = ptr$D36914$inner_storage_$_storage$_which_28; in fact ptrD.41110 is not scalarized at all. Looks like the init from D.41109 makes us fail here. Martin?