mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
stage2: add error for comptime control flow in runtime block
This commit is contained in:
parent
b5861193e0
commit
9e0a930ce3
@ -1940,6 +1940,9 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
|
||||
.break_inline
|
||||
else
|
||||
.@"break";
|
||||
if (break_tag == .break_inline) {
|
||||
_ = try parent_gz.addNode(.check_comptime_control_flow, node);
|
||||
}
|
||||
_ = try parent_gz.addBreak(break_tag, continue_block, .void_value);
|
||||
return Zir.Inst.Ref.unreachable_value;
|
||||
},
|
||||
@ -2473,6 +2476,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
|
||||
.repeat_inline,
|
||||
.panic,
|
||||
.panic_comptime,
|
||||
.check_comptime_control_flow,
|
||||
=> {
|
||||
noreturn_src_node = statement;
|
||||
break :b true;
|
||||
|
||||
@ -2283,6 +2283,8 @@ pub const SrcLoc = struct {
|
||||
.@"while" => tree.whileFull(node).ast.cond_expr,
|
||||
.for_simple => tree.forSimple(node).ast.cond_expr,
|
||||
.@"for" => tree.forFull(node).ast.cond_expr,
|
||||
.@"orelse" => node,
|
||||
.@"catch" => node,
|
||||
else => unreachable,
|
||||
};
|
||||
return nodeToSpan(tree, src_node);
|
||||
|
||||
18
src/Sema.zig
18
src/Sema.zig
@ -1146,6 +1146,24 @@ fn analyzeBodyInner(
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
.check_comptime_control_flow => {
|
||||
if (!block.is_comptime) {
|
||||
if (block.runtime_cond orelse block.runtime_loop) |runtime_src| {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].node;
|
||||
const src = LazySrcLoc.nodeOffset(inst_data);
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, src, "comptime control flow inside runtime block", .{});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
try sema.errNote(block, runtime_src, msg, "runtime control flow here", .{});
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
|
||||
// Special case instructions to handle comptime control flow.
|
||||
.@"break" => {
|
||||
|
||||
@ -280,6 +280,9 @@ pub const Inst = struct {
|
||||
/// break instruction in a block, and the target block is the parent.
|
||||
/// Uses the `break` union field.
|
||||
break_inline,
|
||||
/// Checks that comptime control flow does not happen inside a runtime block.
|
||||
/// Uses the `node` union field.
|
||||
check_comptime_control_flow,
|
||||
/// Function call.
|
||||
/// Uses the `pl_node` union field with payload `Call`.
|
||||
/// AST node is the function call.
|
||||
@ -1266,6 +1269,7 @@ pub const Inst = struct {
|
||||
.repeat_inline,
|
||||
.panic,
|
||||
.panic_comptime,
|
||||
.check_comptime_control_flow,
|
||||
=> true,
|
||||
};
|
||||
}
|
||||
@ -1315,6 +1319,7 @@ pub const Inst = struct {
|
||||
.set_runtime_safety,
|
||||
.memcpy,
|
||||
.memset,
|
||||
.check_comptime_control_flow,
|
||||
=> true,
|
||||
|
||||
.param,
|
||||
@ -1595,6 +1600,7 @@ pub const Inst = struct {
|
||||
.bool_br_or = .bool_br,
|
||||
.@"break" = .@"break",
|
||||
.break_inline = .@"break",
|
||||
.check_comptime_control_flow = .node,
|
||||
.call = .pl_node,
|
||||
.cmp_lt = .pl_node,
|
||||
.cmp_lte = .pl_node,
|
||||
|
||||
@ -409,6 +409,7 @@ const Writer = struct {
|
||||
.alloc_inferred_comptime_mut,
|
||||
.ret_ptr,
|
||||
.ret_type,
|
||||
.check_comptime_control_flow,
|
||||
=> try self.writeNode(stream, inst),
|
||||
|
||||
.error_value,
|
||||
|
||||
@ -9,8 +9,8 @@ fn bad() !void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:4:21: error: comptime control flow inside runtime block
|
||||
// tmp.zig:4:15: note: runtime block created here
|
||||
// :4:21: error: comptime control flow inside runtime block
|
||||
// :4:15: note: runtime control flow here
|
||||
@ -8,8 +8,8 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:22: error: comptime control flow inside runtime block
|
||||
// tmp.zig:5:9: note: runtime block created here
|
||||
// :5:22: error: comptime control flow inside runtime block
|
||||
// :5:15: note: runtime control flow here
|
||||
@ -8,8 +8,8 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:20: error: comptime control flow inside runtime block
|
||||
// tmp.zig:5:9: note: runtime block created here
|
||||
// :5:20: error: comptime control flow inside runtime block
|
||||
// :5:13: note: runtime control flow here
|
||||
@ -8,8 +8,8 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:20: error: comptime control flow inside runtime block
|
||||
// tmp.zig:5:9: note: runtime block created here
|
||||
// :5:20: error: comptime control flow inside runtime block
|
||||
// :5:13: note: runtime control flow here
|
||||
@ -0,0 +1,16 @@
|
||||
export fn entry() void {
|
||||
const ints = [_]u8{ 1, 2 };
|
||||
inline for (ints) |_| {
|
||||
bad() orelse continue;
|
||||
}
|
||||
}
|
||||
fn bad() ?void {
|
||||
return null;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:22: error: comptime control flow inside runtime block
|
||||
// :4:15: note: runtime control flow here
|
||||
@ -11,8 +11,8 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:6:19: error: comptime control flow inside runtime block
|
||||
// tmp.zig:5:9: note: runtime block created here
|
||||
// :6:19: error: comptime control flow inside runtime block
|
||||
// :5:17: note: runtime control flow here
|
||||
@ -8,8 +8,8 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:25: error: comptime control flow inside runtime block
|
||||
// tmp.zig:5:9: note: runtime block created here
|
||||
// :5:25: error: comptime control flow inside runtime block
|
||||
// :5:18: note: runtime control flow here
|
||||
@ -10,8 +10,8 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:6:13: error: comptime control flow inside runtime block
|
||||
// tmp.zig:5:9: note: runtime block created here
|
||||
// :6:13: error: comptime control flow inside runtime block
|
||||
// :5:16: note: runtime control flow here
|
||||
@ -8,8 +8,8 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:23: error: comptime control flow inside runtime block
|
||||
// tmp.zig:5:9: note: runtime block created here
|
||||
// :5:23: error: comptime control flow inside runtime block
|
||||
// :5:16: note: runtime control flow here
|
||||
Loading…
x
Reference in New Issue
Block a user