From 94f0bd6af7120ff27968052ad5645a554db12bed Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 9 Mar 2018 01:13:46 -0800 Subject: [PATCH] fix Issue 18576 - Compiler not doing RVO with auto returns --- src/dmd/s2ir.d | 29 +++++++++++++++++++++++--- test/runnable/test28.d | 46 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/dmd/s2ir.d b/src/dmd/s2ir.d index 3258ba057e..2329059cb9 100644 --- a/src/dmd/s2ir.d +++ b/src/dmd/s2ir.d @@ -734,14 +734,26 @@ private extern (C++) class S2irVisitor : Visitor sle.sym = irs.shidden; writetohp = true; } - /* Detect: - * structliteral.ctor(args) + /* Detect function call that returns the same struct * and construct directly into *shidden */ else if (s.exp.op == TOK.call) { auto ce = cast(CallExp)s.exp; - if (ce.e1.op == TOK.dotVariable) + if (ce.e1.op == TOK.variable || ce.e1.op == TOK.star) + { + Type t = ce.e1.type.toBasetype(); + if (t.ty == Tdelegate) + t = t.nextOf(); + if (t.ty == Tfunction && retStyle(cast(TypeFunction)t) == RET.stack) + { + irs.ehidden = el_var(irs.shidden); + e = toElemDtor(s.exp, irs); + e = el_una(OPaddr, TYnptr, e); + goto L1; + } + } + else if (ce.e1.op == TOK.dotVariable) { auto dve = cast(DotVarExp)ce.e1; auto fd = dve.var.isFuncDeclaration(); @@ -754,6 +766,16 @@ private extern (C++) class S2irVisitor : Visitor writetohp = true; } } + Type t = ce.e1.type.toBasetype(); + if (t.ty == Tdelegate) + t = t.nextOf(); + if (t.ty == Tfunction && retStyle(cast(TypeFunction)t) == RET.stack) + { + irs.ehidden = el_var(irs.shidden); + e = toElemDtor(s.exp, irs); + e = el_una(OPaddr, TYnptr, e); + goto L1; + } } } e = toElemDtor(s.exp, irs); @@ -787,6 +809,7 @@ private extern (C++) class S2irVisitor : Visitor e = toElemDtor(s.exp, irs); assert(e); } + L1: elem_setLoc(e, s.loc); block_appendexp(blx.curblock, e); bc = BCretexp; diff --git a/test/runnable/test28.d b/test/runnable/test28.d index c7ec6ad322..b94b0b58ee 100644 --- a/test/runnable/test28.d +++ b/test/runnable/test28.d @@ -1,10 +1,10 @@ module test; +import core.stdc.stdio; import core.vararg; import std.stdio; import std.string; -extern(C) int printf(const char*, ...); /*******************************************/ @@ -1247,6 +1247,49 @@ void test65() } +/*******************************************/ +// https://issues.dlang.org/show_bug.cgi?id=18576 + +void delegate() callback; + +struct S66 { + int x; + @disable this(this); + + this(int x) { + this.x = x; + callback = &inc; + } + void inc() { + x++; + } +} + +auto f66() +{ + return g66(); // RVO should be done +} + +auto g66() +{ + return h66(); // RVO should be done +} + +auto h66() +{ + return S66(100); +} + +void test18576() +{ + auto s = f66(); + printf("%p vs %p\n", &s, callback.ptr); + callback(); + printf("s.x = %d\n", s.x); + assert(s.x == 101); + assert(&s == callback.ptr); +} + /*******************************************/ void main() @@ -1314,6 +1357,7 @@ void main() test63(); test64(); test65(); + test18576(); printf("Success\n"); }