Skip to content

Commit

Permalink
fix Issue 17450 - escaping delegate context pointer not detected for …
Browse files Browse the repository at this point in the history
…member functions
  • Loading branch information
WalterBright committed May 29, 2017
1 parent e5ebfc5 commit e3e8ce2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 8 deletions.
11 changes: 8 additions & 3 deletions src/ddmd/escape.d
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ bool checkReturnEscapeRef(Scope* sc, Expression e, bool gag)

private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
{
//printf("[%s] checkReturnEscapeImpl, e = %s\n", e.loc.toChars(), e.toChars());
//printf("[%s] checkReturnEscapeImpl, e: `%s`\n", e.loc.toChars(), e.toChars());
EscapeByResults er;

if (refs)
Expand All @@ -509,7 +509,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
bool result = false;
foreach (VarDeclaration v; er.byvalue)
{
//printf("byvalue %s\n", v.toChars());
//printf("byvalue `%s`\n", v.toChars());
if (v.isDataseg())
continue;

Expand Down Expand Up @@ -571,7 +571,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)

foreach (VarDeclaration v; er.byref)
{
//printf("byref %s\n", v.toChars());
//printf("byref `%s`\n", v.toChars());
if (v.isDataseg())
continue;

Expand Down Expand Up @@ -771,6 +771,11 @@ private void escapeByValue(Expression e, EscapeByResults* er)

override void visit(DelegateExp e)
{
Type t = e.e1.type.toBasetype();
if (t.ty == Tclass || t.ty == Tpointer)
escapeByValue(e.e1, er);
else
escapeByRef(e.e1, er);
er.byfunc.push(e.func);
}

Expand Down
5 changes: 3 additions & 2 deletions test/fail_compilation/test13536.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
PERMUTE_ARGS:
TEST_OUTPUT:
---
fail_compilation/test13536.d(23): Error: field U.sysDg cannot access pointers in @safe code that overlap other fields
fail_compilation/test13536.d(24): Error: field U.safeDg cannot access pointers in @safe code that overlap other fields
fail_compilation/test13536.d(24): Error: field U.sysDg cannot access pointers in @safe code that overlap other fields
fail_compilation/test13536.d(24): Error: address of variable s assigned to u with longer lifetime
fail_compilation/test13536.d(25): Error: field U.safeDg cannot access pointers in @safe code that overlap other fields
---
*/

Expand Down
7 changes: 4 additions & 3 deletions test/fail_compilation/test16365.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
PERMUTE_ARGS:
TEST_OUTPUT:
---
fail_compilation/test16365.d(21): Error: 'this' reference necessary to take address of member f1 in @safe function main
fail_compilation/test16365.d(23): Error: cannot implicitly convert expression `&f2` of type `void delegate() pure nothrow @nogc @safe` to `void function() @safe`
fail_compilation/test16365.d(28): Error: dg.funcptr cannot be used in @safe code
fail_compilation/test16365.d(22): Error: 'this' reference necessary to take address of member f1 in @safe function main
fail_compilation/test16365.d(24): Error: cannot implicitly convert expression `&f2` of type `void delegate() pure nothrow @nogc @safe` to `void function() @safe`
fail_compilation/test16365.d(28): Error: address of variable s assigned to dg with longer lifetime
fail_compilation/test16365.d(29): Error: dg.funcptr cannot be used in @safe code
---
*/

Expand Down
58 changes: 58 additions & 0 deletions test/fail_compilation/test17450.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
REQUIRED_ARGS: -dip1000 -dip25
TEST_OUTPUT:
---
fail_compilation/test17450.d(15): Error: escaping reference to local variable s
fail_compilation/test17450.d(18): Error: escaping reference to local variable this
---
*/
// https://issues.dlang.org/show_bug.cgi?id=17450

alias dg_t = void delegate();

struct S {
@safe dg_t foo1(ref S s) {
return &s.bar;
}
@safe dg_t foo2() {
return &bar;
}

@safe dg_t foo3(return ref S s) {
return &s.bar;
}
@safe dg_t foo4() return {
return &bar;
}

@safe void bar();
}

/*
TEST_OUTPUT:
---
fail_compilation/test17450.d(103): Error: scope variable c may not be returned
fail_compilation/test17450.d(106): Error: scope variable this may not be returned
---
*/
// https://issues.dlang.org/show_bug.cgi?id=17450

#line 100

class C {
@safe dg_t foo1(scope C c) {
return &c.bar;
}
@safe dg_t foo2() scope {
return &bar;
}

@safe dg_t foo3(return scope C c) {
return &c.bar;
}
@safe dg_t foo4() return scope {
return &bar;
}

@safe void bar();
}

0 comments on commit e3e8ce2

Please sign in to comment.