diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index 31b6397ecf5a..86b9d0bf8074 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -2769,7 +2769,6 @@ void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret) * fbody.dsymbolSemantic() running, vresult.type might be modified. */ fd.vresult = new VarDeclaration(loc, tret, Id.result, null); - fd.vresult._init = new VoidInitializer(loc); // hdrgen requires _init fd.vresult.storage_class |= STC.nodtor | STC.temp; if (!fd.isVirtual()) fd.vresult.storage_class |= STC.const_; diff --git a/compiler/src/dmd/glue/s2ir.d b/compiler/src/dmd/glue/s2ir.d index 50f8c4177636..c73b27424dd5 100644 --- a/compiler/src/dmd/glue/s2ir.d +++ b/compiler/src/dmd/glue/s2ir.d @@ -661,7 +661,22 @@ void Statement_toIR(Statement s, ref IRState irs, StmtState* stmtstate) { // Reference return, so convert to a pointer e = toElemDtor(s.exp, irs); + + /* already taken care of for vresult in buildResultVar() and semantic3.d + * https://issues.dlang.org/show_bug.cgi?id=19384 + */ + if (func.vresult) + if (BlitExp be = s.exp.isBlitExp()) + { + if (VarExp ve = be.e1.isVarExp()) + { + if (ve.var == func.vresult) + goto Lskip; + } + } + e = addressElem(e, s.exp.type.pointerTo()); + Lskip: } else { diff --git a/compiler/src/dmd/semantic3.d b/compiler/src/dmd/semantic3.d index 234782645487..2c1850fc688b 100644 --- a/compiler/src/dmd/semantic3.d +++ b/compiler/src/dmd/semantic3.d @@ -961,10 +961,8 @@ private extern(C++) final class Semantic3Visitor : Visitor /* https://issues.dlang.org/show_bug.cgi?id=10789 * If NRVO is not possible, all returned lvalues should call their postblits. - * For functions with a __result variable, postblits will be called later - * during initialization of __result. */ - if (!funcdecl.isNRVO && !funcdecl.vresult) + if (!funcdecl.isNRVO) exp = doCopyOrMove(sc2, exp, f.next, true, true); if (tret.hasPointers()) @@ -975,12 +973,13 @@ private extern(C++) final class Semantic3Visitor : Visitor if (funcdecl.vresult) { - Scope* scret = rs.fesFunc ? rs.fesFunc._scope : sc2; + // Create: return vresult = exp; + if (canElideCopy(exp, funcdecl.vresult.type)) + exp = new ConstructExp(rs.loc, funcdecl.vresult, exp); + else + exp = new BlitExp(rs.loc, funcdecl.vresult, exp); - // Create: return (vresult = exp, vresult); - exp = new ConstructExp(rs.loc, funcdecl.vresult, exp); - exp = exp.expressionSemantic(scret); - exp = Expression.combine(exp, new VarExp(rs.loc, funcdecl.vresult)); + exp.type = funcdecl.vresult.type; if (rs.caseDim) exp = Expression.combine(exp, new IntegerExp(rs.caseDim)); diff --git a/compiler/test/compilable/extra-files/vcg-ast.d.cg b/compiler/test/compilable/extra-files/vcg-ast.d.cg index 1af770427a9c..c910f593394e 100644 --- a/compiler/test/compilable/extra-files/vcg-ast.d.cg +++ b/compiler/test/compilable/extra-files/vcg-ast.d.cg @@ -61,7 +61,7 @@ class C : Object } __require(); this.__invariant(); - __result = 2 , __result; + __result = 2; goto __returnLabel; __returnLabel: this.__invariant();