mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
forbid trivial local address returned from functions (#25333)
progress towards #25312
This commit is contained in:
parent
7b92d5f405
commit
ba137783ed
@ -383,6 +383,8 @@ const ResultInfo = struct {
|
|||||||
assignment,
|
assignment,
|
||||||
/// No specific operator in particular.
|
/// No specific operator in particular.
|
||||||
none,
|
none,
|
||||||
|
/// The expression is operand to address-of which is the operand to a return expression.
|
||||||
|
return_addrof,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -955,7 +957,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
|
|||||||
_ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node));
|
_ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node));
|
||||||
break :rl .{ .ref_coerced_ty = res_ty_inst };
|
break :rl .{ .ref_coerced_ty = res_ty_inst };
|
||||||
} else .ref;
|
} else .ref;
|
||||||
const result = try expr(gz, scope, .{ .rl = operand_rl }, tree.nodeData(node).node);
|
const operand_node = tree.nodeData(node).node;
|
||||||
|
const result = try expr(gz, scope, .{
|
||||||
|
.rl = operand_rl,
|
||||||
|
.ctx = switch (ri.ctx) {
|
||||||
|
.@"return" => .return_addrof,
|
||||||
|
else => .none,
|
||||||
|
},
|
||||||
|
}, operand_node);
|
||||||
return rvalue(gz, ri, result, node);
|
return rvalue(gz, ri, result, node);
|
||||||
},
|
},
|
||||||
.optional_type => {
|
.optional_type => {
|
||||||
@ -8420,13 +8429,19 @@ fn localVarRef(
|
|||||||
local_ptr.used = .fromToken(ident_token);
|
local_ptr.used = .fromToken(ident_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can't close over a runtime variable
|
if (!local_ptr.maybe_comptime and !gz.is_typeof) {
|
||||||
if (num_namespaces_out != 0 and !local_ptr.maybe_comptime and !gz.is_typeof) {
|
if (num_namespaces_out != 0) {
|
||||||
const ident_name = try astgen.identifierTokenString(ident_token);
|
const ident_name = try astgen.identifierTokenString(ident_token);
|
||||||
return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{
|
return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{
|
||||||
try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),
|
try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),
|
||||||
try astgen.errNoteNode(capturing_namespace.node, "crosses namespace boundary here", .{}),
|
try astgen.errNoteNode(capturing_namespace.node, "crosses namespace boundary here", .{}),
|
||||||
});
|
});
|
||||||
|
} else if (ri.ctx == .return_addrof) {
|
||||||
|
const ident_name = try astgen.identifierTokenString(ident_token);
|
||||||
|
return astgen.failNodeNotes(ident, "returning address of expired local variable '{s}'", .{ident_name}, &.{
|
||||||
|
try astgen.errNoteTok(local_ptr.token_src, "declared runtime-known here", .{}),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ri.rl) {
|
switch (ri.rl) {
|
||||||
|
|||||||
@ -758,7 +758,8 @@ test "return undefined pointer from function, directly and by expired local" {
|
|||||||
/// Semantically equivalent to `returnUndefPointer`.
|
/// Semantically equivalent to `returnUndefPointer`.
|
||||||
fn returnStackPointer() *i32 {
|
fn returnStackPointer() *i32 {
|
||||||
var stack_allocation: i32 = 1234;
|
var stack_allocation: i32 = 1234;
|
||||||
return &stack_allocation;
|
const ptr = &stack_allocation; // defeats ast-check detection
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
9
test/cases/compile_errors/return_addr_of_local.zig
Normal file
9
test/cases/compile_errors/return_addr_of_local.zig
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export fn b() void {
|
||||||
|
var x: i32 = 1234;
|
||||||
|
return &x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
//
|
||||||
|
// :3:13: error: returning address of expired local variable 'x'
|
||||||
|
// :2:9: note: declared runtime-known here
|
||||||
Loading…
x
Reference in New Issue
Block a user