@@ -158,7 +158,7 @@ bool checkMutableArguments(ref Scope sc, FuncDeclaration fd, TypeFunction tf,
158
158
159
159
void onRef (VarDeclaration v, bool transition) { eb.byref.push(v); }
160
160
void onValue (VarDeclaration v) { eb.byvalue.push(v); }
161
- void onFunc (FuncDeclaration fd) {}
161
+ void onFunc (FuncDeclaration fd, bool called ) {}
162
162
void onExp (Expression e, bool transition) {}
163
163
164
164
scope EscapeByResults er = EscapeByResults(&onRef, &onValue, &onFunc, &onExp);
@@ -417,7 +417,7 @@ bool checkParamArgumentEscape(ref Scope sc, FuncDeclaration fdc, Identifier parI
417
417
}
418
418
}
419
419
420
- void onFunc (FuncDeclaration fd)
420
+ void onFunc (FuncDeclaration fd, bool called )
421
421
{
422
422
// printf("fd = %s, %d\n", fd.toChars(), fd.tookAddressOf);
423
423
if (parStc & STC .scope_)
@@ -862,7 +862,7 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef)
862
862
result |= sc.setUnsafeDIP1000(gag, ae.loc, " reference to local variable `%s` assigned to non-scope `%s`" , v, e1);
863
863
}
864
864
865
- void onFunc (FuncDeclaration func)
865
+ void onFunc (FuncDeclaration func, bool called )
866
866
{
867
867
if (log) printf(" byfunc: %s, %d\n " , func.toChars(), func.tookAddressOf);
868
868
VarDeclarations vars;
@@ -992,7 +992,7 @@ bool checkThrowEscape(ref Scope sc, Expression e, bool gag)
992
992
notMaybeScope(v, new ThrowExp(e.loc, e));
993
993
}
994
994
}
995
- void onFunc (FuncDeclaration fd) {}
995
+ void onFunc (FuncDeclaration fd, bool called ) {}
996
996
void onExp (Expression exp, bool retRefTransition) {}
997
997
998
998
scope EscapeByResults er = EscapeByResults(&onRef, &onValue, &onFunc, &onExp);
@@ -1124,7 +1124,7 @@ bool checkNewEscape(ref Scope sc, Expression e, bool gag)
1124
1124
}
1125
1125
}
1126
1126
1127
- void onFunc (FuncDeclaration fd) {}
1127
+ void onFunc (FuncDeclaration fd, bool called ) {}
1128
1128
1129
1129
void onExp (Expression ee, bool retRefTransition)
1130
1130
{
@@ -1236,15 +1236,20 @@ private bool checkReturnEscapeImpl(ref Scope sc, Expression e, bool refs, bool g
1236
1236
* return s; // s is inferred as 'scope' but incorrectly tested in foo()
1237
1237
* return null; }
1238
1238
*/
1239
- ! (! refs && p.parent == sc.func && pfunc.fes) &&
1239
+ ! (! refs && p.parent == sc.func && pfunc.fes)
1240
+ )
1241
+ {
1240
1242
/*
1241
1243
* auto p(scope string s) {
1242
1244
* string scfunc() { return s; }
1243
1245
* }
1244
1246
*/
1245
- ! (! refs && sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0 )
1246
- )
1247
- {
1247
+ if (sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0 &&
1248
+ inferReturn(sc.func, sc.func.vthis, /* returnScope*/ ! refs))
1249
+ {
1250
+ return ;
1251
+ }
1252
+
1248
1253
if (v.isParameter() && ! v.isReturn())
1249
1254
{
1250
1255
// https://issues.dlang.org/show_bug.cgi?id=23191
@@ -1411,7 +1416,11 @@ private bool checkReturnEscapeImpl(ref Scope sc, Expression e, bool refs, bool g
1411
1416
}
1412
1417
}
1413
1418
1414
- void onFunc (FuncDeclaration fd) {}
1419
+ void onFunc (FuncDeclaration fd, bool called)
1420
+ {
1421
+ if (called && fd.isNested())
1422
+ result |= sc.setUnsafeDIP1000(gag, e.loc, " escaping local variable through nested function `%s`" , fd);
1423
+ }
1415
1424
1416
1425
void onExp (Expression ee, bool retRefTransition)
1417
1426
{
@@ -1603,13 +1612,13 @@ void escapeByValue(Expression e, ref scope EscapeByResults er, bool retRefTransi
1603
1612
escapeByValue(e.e1, er, retRefTransition);
1604
1613
else
1605
1614
escapeByRef(e.e1, er, retRefTransition);
1606
- er.byFunc(e.func);
1615
+ er.byFunc(e.func, false );
1607
1616
}
1608
1617
1609
1618
void visitFunc (FuncExp e)
1610
1619
{
1611
1620
if (e.fd.tok == TOK .delegate_)
1612
- er.byFunc(e.fd);
1621
+ er.byFunc(e.fd, false );
1613
1622
}
1614
1623
1615
1624
void visitTuple (TupleExp e)
@@ -1860,7 +1869,12 @@ void escapeByValue(Expression e, ref scope EscapeByResults er, bool retRefTransi
1860
1869
if (fd && fd.isNested())
1861
1870
{
1862
1871
if (tf.isreturn && tf.isScopeQual)
1863
- er.byExp(e, false );
1872
+ {
1873
+ if (tf.isreturnscope)
1874
+ er.byFunc(fd, true );
1875
+ else
1876
+ er.byExp(e, false );
1877
+ }
1864
1878
}
1865
1879
}
1866
1880
@@ -1881,7 +1895,12 @@ void escapeByValue(Expression e, ref scope EscapeByResults er, bool retRefTransi
1881
1895
if (fd && fd.isNested())
1882
1896
{
1883
1897
if (tf.isreturn && tf.isScopeQual)
1884
- er.byExp(e, false );
1898
+ {
1899
+ if (tf.isreturnscope)
1900
+ er.byFunc(fd, true );
1901
+ else
1902
+ er.byExp(e, false );
1903
+ }
1885
1904
}
1886
1905
}
1887
1906
}
@@ -2195,7 +2214,10 @@ struct EscapeByResults
2195
2214
// / called on variables with values containing pointers
2196
2215
void delegate (VarDeclaration) byValue ;
2197
2216
// / called on nested functions that are turned into delegates
2198
- void delegate (FuncDeclaration) byFunc;
2217
+ // / When `called` is true, it means the delegate escapes variables
2218
+ // / from the closure through a call to it, while `false` means the
2219
+ // / delegate itself escapes.
2220
+ void delegate (FuncDeclaration, bool called) byFunc;
2199
2221
// / called when expression temporaries are being returned by ref / address
2200
2222
void delegate (Expression, bool retRefTransition) byExp;
2201
2223
0 commit comments