mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2: add error for unused labels
This commit is contained in:
parent
40aad4f47e
commit
a50759325c
@ -804,7 +804,7 @@ pub const Scope = struct {
|
||||
pub const Label = struct {
|
||||
token: ast.TokenIndex,
|
||||
block_inst: *zir.Inst.Block,
|
||||
result_loc: astgen.ResultLoc,
|
||||
used: bool = false,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -348,8 +348,9 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr
|
||||
|
||||
const block_inst = blk: {
|
||||
if (node.getLabel()) |break_label| {
|
||||
if (gen_zir.label) |label| {
|
||||
if (gen_zir.label) |*label| {
|
||||
if (try tokenIdentEql(mod, parent_scope, label.token, break_label)) {
|
||||
label.used = true;
|
||||
break :blk label.block_inst;
|
||||
}
|
||||
}
|
||||
@ -407,8 +408,9 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowE
|
||||
continue;
|
||||
};
|
||||
if (node.getLabel()) |break_label| blk: {
|
||||
if (gen_zir.label) |label| {
|
||||
if (gen_zir.label) |*label| {
|
||||
if (try tokenIdentEql(mod, parent_scope, label.token, break_label)) {
|
||||
label.used = true;
|
||||
break :blk;
|
||||
}
|
||||
}
|
||||
@ -485,6 +487,9 @@ fn labeledBlockExpr(
|
||||
defer block_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
try blockExprStmts(mod, &block_scope.base, &block_node.base, block_node.statements());
|
||||
if (!block_scope.label.?.used) {
|
||||
return mod.fail(parent_scope, tree.token_locs[block_node.label].start, "unused block label", .{});
|
||||
}
|
||||
|
||||
block_inst.positionals.body.instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items);
|
||||
try gen_zir.instructions.append(mod.gpa, &block_inst.base);
|
||||
@ -1398,7 +1403,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
|
||||
loop_scope.break_block = while_block;
|
||||
loop_scope.continue_block = cond_block;
|
||||
if (while_node.label) |some| {
|
||||
loop_scope.label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{
|
||||
loop_scope.label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{
|
||||
.token = some,
|
||||
.block_inst = while_block,
|
||||
});
|
||||
@ -1465,6 +1470,11 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
|
||||
condbr.positionals.else_body = .{
|
||||
.instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
|
||||
};
|
||||
if (loop_scope.label) |some| {
|
||||
if (!some.used) {
|
||||
return mod.fail(scope, tree.token_locs[some.token].start, "unused while label", .{});
|
||||
}
|
||||
}
|
||||
return &while_block.base;
|
||||
}
|
||||
|
||||
@ -1555,7 +1565,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
|
||||
loop_scope.break_block = for_block;
|
||||
loop_scope.continue_block = cond_block;
|
||||
if (for_node.label) |some| {
|
||||
loop_scope.label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{
|
||||
loop_scope.label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{
|
||||
.token = some,
|
||||
.block_inst = for_block,
|
||||
});
|
||||
@ -1646,6 +1656,11 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
|
||||
condbr.positionals.else_body = .{
|
||||
.instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
|
||||
};
|
||||
if (loop_scope.label) |some| {
|
||||
if (!some.used) {
|
||||
return mod.fail(scope, tree.token_locs[some.token].start, "unused for label", .{});
|
||||
}
|
||||
}
|
||||
return &for_block.base;
|
||||
}
|
||||
|
||||
|
||||
@ -1207,7 +1207,7 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
|
||||
{
|
||||
var case = ctx.exe("break/continue", linux_x64);
|
||||
|
||||
|
||||
// Break out of loop
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
@ -1296,4 +1296,23 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
var case = ctx.exe("unused labels", linux_x64);
|
||||
case.addError(
|
||||
\\comptime {
|
||||
\\ foo: {}
|
||||
\\}
|
||||
, &[_][]const u8{":2:5: error: unused block label"});
|
||||
case.addError(
|
||||
\\comptime {
|
||||
\\ foo: while (true) {}
|
||||
\\}
|
||||
, &[_][]const u8{":2:5: error: unused while label"});
|
||||
case.addError(
|
||||
\\comptime {
|
||||
\\ foo: for ("foo") |_| {}
|
||||
\\}
|
||||
, &[_][]const u8{":2:5: error: unused for label"});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user