https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90501
--- Comment #11 from Iain Buclaw <ibuclaw at gdcproject dot org> --- (In reply to Jakub Jelinek from comment #8) > So the first question would be why D passes the return value as > DECL_BY_REFERENCE if it doesn't have TREE_ADDRESSABLE type. Looking at the places where DECL_BY_REFERENCE is set, this mismatch could happen when the result should be returned using NRVO. To memory, using a mixture of DECL_BY_REFERENCE and CALL_EXPR_RETURN_SLOT_OPT gives a desired behaviour of eliding a copy. Two things come to mind as alternatives: 1. Currently for NRVO, the DECL_RESULT is explicitly set as not addressable. TREE_TYPE (resdecl) = build_reference_type (TREE_TYPE (resdecl)); DECL_BY_REFERENCE (resdecl) = 1; TREE_ADDRESSABLE (resdecl) = 0; Is it allowed for the decl to be both DECL_BY_REFERENCE and TREE_ADDRESSABLE at the same time? Or will that just confuse things further. TREE_TYPE (resdecl) = build_reference_type (TREE_TYPE (resdecl)); DECL_BY_REFERENCE (resdecl) = 1; - TREE_ADDRESSABLE (resdecl) = 0; + if (TREE_ADDRESSABLE (TREE_TYPE (resdecl)) + TREE_ADDRESSABLE (resdecl) = 0; 2. Redo handling of NRVO in the D front-end, to enforce a specific semantic for trivial types that we want to elide a copy for. i.e: Given, --- S foo() { S result; result.a = 3; return result; } void test() { S s = foo(); } --- Generate this explicitly as: --- S* foo(S* hidden) { S result; result.a = 3; *hidden = result; return hidden; } void test() { S tmp; S s = *foo(&tmp); } --- Obviously, that change would be a bit more involved on my side.