mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Fix bugzilla 23657 - [REG2.101] Incorrect error escape reference to stack allocated value (#16407)
Co-authored-by: Dennis Korpel <dennis@sarc.nl>
This commit is contained in:
parent
111ae7308b
commit
1da572ac2e
2 changed files with 26 additions and 6 deletions
|
@ -1542,7 +1542,7 @@ private bool inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
|
|||
* e = expression to be returned by value
|
||||
* er = where to place collected data
|
||||
* live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`.
|
||||
* retRefTransition = if `e` is returned through a `return ref scope` function call
|
||||
* retRefTransition = if `e` is returned through a `return (ref) scope` function call
|
||||
*/
|
||||
public
|
||||
void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false)
|
||||
|
@ -1786,7 +1786,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
|
|||
}
|
||||
}
|
||||
else
|
||||
escapeByValue(arg, er, live, retRefTransition);
|
||||
escapeByValue(arg, er, live, true);
|
||||
}
|
||||
else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
|
||||
{
|
||||
|
@ -1941,7 +1941,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
|
|||
* e = expression to be returned by 'ref'
|
||||
* er = where to place collected data
|
||||
* live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`.
|
||||
* retRefTransition = if `e` is returned through a `return ref scope` function call
|
||||
* retRefTransition = if `e` is returned through a `return (ref) scope` function call
|
||||
*/
|
||||
private
|
||||
void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false)
|
||||
|
@ -2189,7 +2189,7 @@ struct EscapeByResults
|
|||
import dmd.root.array: Array;
|
||||
|
||||
/**
|
||||
* Whether the variable / expression went through a `return ref scope` function call
|
||||
* Whether the variable / expression went through a `return (ref) scope` function call
|
||||
*
|
||||
* This is needed for the dip1000 by default transition, since the rules for
|
||||
* disambiguating `return scope ref` have changed. Therefore, functions in legacy code
|
||||
|
@ -2197,6 +2197,10 @@ struct EscapeByResults
|
|||
* are being escaped, which is an error even in `@system` code. By keeping track of this
|
||||
* information, variables escaped through `return ref` can be treated as a deprecation instead
|
||||
* of error, see test/fail_compilation/dip1000_deprecation.d
|
||||
*
|
||||
* Additionally, return scope can be inferred wrongly instead of scope, in which
|
||||
* case the code could give false positives even without @safe or dip1000:
|
||||
* https://issues.dlang.org/show_bug.cgi?id=23657
|
||||
*/
|
||||
private Array!bool refRetRefTransition;
|
||||
private Array!bool expRetRefTransition;
|
||||
|
@ -2218,7 +2222,7 @@ struct EscapeByResults
|
|||
* Escape variable `v` by reference
|
||||
* Params:
|
||||
* v = variable to escape
|
||||
* retRefTransition = `v` is escaped through a `return ref scope` function call
|
||||
* retRefTransition = `v` is escaped through a `return (ref) scope` function call
|
||||
*/
|
||||
void pushRef(VarDeclaration v, bool retRefTransition)
|
||||
{
|
||||
|
@ -2230,7 +2234,7 @@ struct EscapeByResults
|
|||
* Escape a reference to expression `e`
|
||||
* Params:
|
||||
* e = expression to escape
|
||||
* retRefTransition = `e` is escaped through a `return ref scope` function call
|
||||
* retRefTransition = `e` is escaped through a `return (ref) scope` function call
|
||||
*/
|
||||
void pushExp(Expression e, bool retRefTransition)
|
||||
{
|
||||
|
|
16
compiler/test/compilable/returnscope_without_safe.d
Normal file
16
compiler/test/compilable/returnscope_without_safe.d
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Stack pointers are being escaped here, but without
|
||||
// @safe and dip1000, it should still be allowed
|
||||
// because return scope could have been inferred incorrectly,
|
||||
// and it breaks existing code:
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23657
|
||||
|
||||
int* identity(return scope int* x);
|
||||
|
||||
auto identityAuto(int* x) => x;
|
||||
|
||||
int* f()
|
||||
{
|
||||
int x;
|
||||
return identity(&x);
|
||||
return identityAuto(&x);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue