authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-02 19:15:41+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-03 16:45:33+03:00
log02112f88364d0564346a71d4f9fcd1936547d725
tree1210e428cfa92b675719714bec0308f31d715fd9
parent6547c3887eb604cf4d494d307927a50a12117708

AstGen: add error for break/continue out of defer expression


5 files changed, 73 insertions(+), 27 deletions(-)

src/AstGen.zig+45-1
......@@ -1899,6 +1899,17 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
18991899 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
19001900 .namespace => break,
19011901 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1902 .defer_gen => {
1903 const defer_gen = scope.cast(Scope.DeferGen).?;
1904
1905 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{
1906 try astgen.errNoteNode(
1907 defer_gen.defer_node,
1908 "defer expression here",
1909 .{},
1910 ),
1911 });
1912 },
19021913 .top => unreachable,
19031914 }
19041915 }
......@@ -1958,6 +1969,17 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
19581969 try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node);
19591970 },
19601971 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1972 .defer_gen => {
1973 const defer_gen = scope.cast(Scope.DeferGen).?;
1974
1975 return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{
1976 try astgen.errNoteNode(
1977 defer_gen.defer_node,
1978 "defer expression here",
1979 .{},
1980 ),
1981 });
1982 },
19611983 .namespace => break,
19621984 .top => unreachable,
19631985 }
......@@ -2022,6 +2044,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke
20222044 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
20232045 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
20242046 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2047 .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent,
20252048 .namespace => break,
20262049 .top => unreachable,
20272050 }
......@@ -2206,7 +2229,13 @@ fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Sc
22062229 astgen.source_offset = defer_scope.source_offset;
22072230 astgen.source_line = defer_scope.source_line;
22082231 astgen.source_column = defer_scope.source_column;
2209 _ = try unusedResultExpr(gz, expr_scope, expr_node);
2232
2233 var defer_gen: Scope.DeferGen = .{
2234 .parent = expr_scope,
2235 .defer_node = defer_scope.defer_node,
2236 };
2237
2238 _ = try unusedResultExpr(gz, &defer_gen.base, expr_node);
22102239}
22112240
22122241/// Returns AST source node of the thing that is noreturn if the statement is
......@@ -2553,6 +2582,7 @@ fn countDefers(astgen: *AstGen, outer_scope: *Scope, inner_scope: *Scope) struct
25532582 .gen_zir => scope = scope.cast(GenZir).?.parent,
25542583 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
25552584 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2585 .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent,
25562586 .defer_normal => {
25572587 const defer_scope = scope.cast(Scope.Defer).?;
25582588 scope = defer_scope.parent;
......@@ -2602,6 +2632,7 @@ fn genDefers(
26022632 .gen_zir => scope = scope.cast(GenZir).?.parent,
26032633 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
26042634 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2635 .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent,
26052636 .defer_normal => {
26062637 const defer_scope = scope.cast(Scope.Defer).?;
26072638 scope = defer_scope.parent;
......@@ -2681,6 +2712,7 @@ fn checkUsed(
26812712 scope = s.parent;
26822713 },
26832714 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2715 .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent,
26842716 .namespace => unreachable,
26852717 .top => unreachable,
26862718 }
......@@ -4040,6 +4072,7 @@ fn testDecl(
40404072 .local_val, .local_ptr => unreachable, // a test cannot be in a local scope
40414073 .gen_zir => s = s.cast(GenZir).?.parent,
40424074 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
4075 .defer_gen => s = s.cast(Scope.DeferGen).?.parent,
40434076 .namespace => {
40444077 const ns = s.cast(Scope.Namespace).?;
40454078 if (ns.decls.get(name_str_index)) |i| {
......@@ -6730,6 +6763,7 @@ fn localVarRef(
67306763 },
67316764 .gen_zir => s = s.cast(GenZir).?.parent,
67326765 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
6766 .defer_gen => s = s.cast(Scope.DeferGen).?.parent,
67336767 .namespace => {
67346768 const ns = s.cast(Scope.Namespace).?;
67356769 if (ns.decls.get(name_str_index)) |i| {
......@@ -7351,6 +7385,7 @@ fn builtinCall(
73517385 },
73527386 .gen_zir => s = s.cast(GenZir).?.parent,
73537387 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
7388 .defer_gen => s = s.cast(Scope.DeferGen).?.parent,
73547389 .namespace => {
73557390 const ns = s.cast(Scope.Namespace).?;
73567391 if (ns.decls.get(decl_name)) |i| {
......@@ -9808,6 +9843,7 @@ const Scope = struct {
98089843 local_ptr,
98099844 defer_normal,
98109845 defer_error,
9846 defer_gen,
98119847 namespace,
98129848 top,
98139849 };
......@@ -9905,6 +9941,13 @@ const Scope = struct {
99059941 const base_tag: Scope.Tag = .top;
99069942 base: Scope = Scope{ .tag = base_tag },
99079943 };
9944
9945 const DeferGen = struct {
9946 const base_tag: Scope.Tag = .defer_gen;
9947 base: Scope = Scope{ .tag = base_tag },
9948 parent: *Scope,
9949 defer_node: Ast.Node.Index,
9950 };
99089951};
99099952
99109953/// This is a temporary structure; references to it are valid only
......@@ -11415,6 +11458,7 @@ fn detectLocalShadowing(
1141511458 },
1141611459 .gen_zir => s = s.cast(GenZir).?.parent,
1141711460 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
11461 .defer_gen => s = s.cast(Scope.DeferGen).?.parent,
1141811462 .top => break,
1141911463 };
1142011464}
test/cases/compile_errors/cannot_break_out_of_defer_expression.zig created+14
......@@ -0,0 +1,14 @@
1export fn foo() void {
2 while (true) {
3 defer {
4 break;
5 }
6 }
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :4:13: error: cannot break out of defer expression
14// :3:9: note: defer expression here
test/cases/compile_errors/cannot_continue_out_of_defer_expression.zig created+14
......@@ -0,0 +1,14 @@
1export fn foo() void {
2 while (true) {
3 defer {
4 continue;
5 }
6 }
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :4:13: error: cannot continue out of defer expression
14// :3:9: note: defer expression here
test/cases/compile_errors/stage1/obj/cannot_break_out_of_defer_expression.zig deleted-13
......@@ -1,13 +0,0 @@
1export fn foo() void {
2 while (true) {
3 defer {
4 break;
5 }
6 }
7}
8
9// error
10// backend=stage1
11// target=native
12//
13// tmp.zig:4:13: error: cannot break out of defer expression
test/cases/compile_errors/stage1/obj/cannot_continue_out_of_defer_expression.zig deleted-13
......@@ -1,13 +0,0 @@
1export fn foo() void {
2 while (true) {
3 defer {
4 continue;
5 }
6 }
7}
8
9// error
10// backend=stage1
11// target=native
12//
13// tmp.zig:4:13: error: cannot continue out of defer expression