diff --git a/src/dmd/escape.d b/src/dmd/escape.d index 21da2b2c32d9..c44ea4a4000c 100644 --- a/src/dmd/escape.d +++ b/src/dmd/escape.d @@ -597,10 +597,10 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) (va.storage_class & (STC.ref_ | STC.out_) || va.type.toBasetype().ty == Tclass); if (log && vaIsRef) printf("va is ref `%s`\n", va.toChars()); - /* Determine if va is the first parameter, through which other 'return' parameters + /* Determine if va is the first non-return parameter, through which other 'return' parameters * can be assigned. */ - bool isFirstRef() + bool isReturnDest() { if (!vaIsRef) return false; @@ -613,13 +613,20 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) return false; if (va == fd.vthis) return true; - if (fd.parameters && fd.parameters.dim && (*fd.parameters)[0] == va) - return true; + if (fd.parameters) + { + foreach (i, v; *fd.parameters) { + if (v == va) + return true; + if (!(v.storage_class & STC.return_)) + return false; + } + } } return false; } - const bool vaIsFirstRef = isFirstRef(); - if (log && vaIsFirstRef) printf("va is first ref `%s`\n", va.toChars()); + const bool vaIsReturnDest = isReturnDest(); + if (log && vaIsReturnDest) printf("va is first ref `%s`\n", va.toChars()); bool result = false; foreach (VarDeclaration v; er.byvalue) @@ -643,7 +650,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) continue; } - if (vaIsFirstRef && + if (vaIsReturnDest && (v.isScope() || (v.storage_class & STC.maybescope)) && !(v.storage_class & STC.return_) && v.isParameter() && @@ -659,7 +666,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) if (v.isScope()) { - if (vaIsFirstRef && v.isParameter() && v.storage_class & STC.return_) + if (vaIsReturnDest && v.isParameter() && v.storage_class & STC.return_) { if (va.isScope()) continue; diff --git a/test/fail_compilation/test19097.d b/test/fail_compilation/test19097.d index 8a41037f348a..441c9b4de161 100644 --- a/test/fail_compilation/test19097.d +++ b/test/fail_compilation/test19097.d @@ -1,7 +1,8 @@ /* REQUIRED_ARGS: -dip1000 * TEST_OUTPUT: --- -fail_compilation/test19097.d(35): Error: scope variable `s` may not be returned +fail_compilation/test19097.d(25): Error: scope variable `p` assigned to `r` with longer lifetime +fail_compilation/test19097.d(46): Error: scope variable `s` may not be returned --- */ @@ -14,6 +15,16 @@ void betty(ref scope int* r, return scope int* p) r = p; } +void tabby(return scope int* p, ref scope int* r) +{ + r = p; +} + +void kitty(return scope int* p, int intermediate, ref scope int* r) +{ + r = p; +} + void freddy(out scope int* r, return scope int* p) { r = p;