https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66666
James Greenhalgh <jgreenhalgh at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |hubicka at gcc dot gnu.org --- Comment #17 from James Greenhalgh <jgreenhalgh at gcc dot gnu.org> --- This feels very similar to pr65236. For your second testbench, we can look at the output assembly for the fixup thunk for MyObject->getTestReference() for arm: --- _ZTv0_n16_N8MyObject16getTestReferenceEv: .fnstart .LFB1058: @ args = 0, pretend = 0, frame = 16 @ frame_needed = 1, uses_anonymous_args = 0 stmfd sp!, {r4, fp, lr} @, .save {r4, fp, lr} .setfp fp, sp, #8 add fp, sp, #8 @,, .pad #20 sub sp, sp, #20 @,, str r0, [fp, #-16] @ .result_ptr, .result_ptr str r1, [fp, #-20] @ this, this ldr r3, [fp, #-20] @ vptr.4, this ldr r3, [r3] @ vtableaddr.5, *vptr.4_4 sub r3, r3, #16 @ vtableaddr.5, vtableaddr.5, ldr r3, [r3] @ vcalloffset.6, *vtableaddr.5_6 mov r2, r3 @ D.25213, vcalloffset.6 ldr r3, [fp, #-20] @ tmp116, this add r3, r3, r2 @ D.25214, tmp116, D.25213 ldr r4, [fp, #-16] @ tmp117, .result_ptr sub r2, fp, #28 @ tmp118,, mov r0, r2 @, tmp118 mov r1, r3 @, D.25214 bl .LTHUNK0 @ ldr r3, [fp, #-28] @ tmp119, str r3, [r4] @ tmp119, <retval> ldr r0, [fp, #-16] @, .result_ptr sub sp, fp, #8 @,, @ sp needed @ ldmfd sp!, {r4, fp, pc} @ .fnend --- We allocate some stack space for the result (tmp118) and hand it off to the called function as the return value. The copy constructor is invoked as a copy to this temporary rather than to the stack slot reserved for TestReference_clone. When we do return to main, we just do a simple word-wise copy of the object. As to your original bug, the root cause is similar, the copy constructor for list wants to set up pointers to the final list node (I think). But we've given it an address on the stack which we will soon clobber when we start executing. You can see the mismatch in expectations if you build an empty list, and check it is empty with list->empty rather than size. (gdb) print this->_M_impl._M_node $3 = {_M_next = 0xbeffef08, _M_prev = 0xbeffef08} (gdb) print &this->_M_impl._M_node $4 = (std::__detail::_List_node_base *) 0xbeffef2c As to why this is target specific... My untested hunch is you'll see it on the following targets { vax, stormy16, pa, nds32, mmix, frv, cris, arm } - those being the targets which #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall and go through the generic, heavyweight, (and apparently broken) thunk code. Enabling return slot optimization would protect these targets against the current issue - that of the thunk code constructing a temporary object in a soon-to-die location on the stack. With all that said, I think backporting Honza's trunk patch for pr65236 looks like a reasonable thing to do. Though, I'm CCing Honza for his input.