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...@@ -1899,6 +1899,17 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
1899 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,1899 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1900 .namespace => break,1900 .namespace => break,
1901 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,1901 .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 },
1902 .top => unreachable,1913 .top => unreachable,
1903 }1914 }
1904 }1915 }
...@@ -1958,6 +1969,17 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -1958,6 +1969,17 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
1958 try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node);1969 try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node);
1959 },1970 },
1960 .defer_error => scope = scope.cast(Scope.Defer).?.parent,1971 .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 },
1961 .namespace => break,1983 .namespace => break,
1962 .top => unreachable,1984 .top => unreachable,
1963 }1985 }
...@@ -2022,6 +2044,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke...@@ -2022,6 +2044,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke
2022 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,2044 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2023 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,2045 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2024 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,2046 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2047 .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent,
2025 .namespace => break,2048 .namespace => break,
2026 .top => unreachable,2049 .top => unreachable,
2027 }2050 }
...@@ -2206,7 +2229,13 @@ fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Sc...@@ -2206,7 +2229,13 @@ fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Sc
2206 astgen.source_offset = defer_scope.source_offset;2229 astgen.source_offset = defer_scope.source_offset;
2207 astgen.source_line = defer_scope.source_line;2230 astgen.source_line = defer_scope.source_line;
2208 astgen.source_column = defer_scope.source_column;2231 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);
2210}2239}
22112240
2212/// Returns AST source node of the thing that is noreturn if the statement is2241/// 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...@@ -2553,6 +2582,7 @@ fn countDefers(astgen: *AstGen, outer_scope: *Scope, inner_scope: *Scope) struct
2553 .gen_zir => scope = scope.cast(GenZir).?.parent,2582 .gen_zir => scope = scope.cast(GenZir).?.parent,
2554 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,2583 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2555 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,2584 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2585 .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent,
2556 .defer_normal => {2586 .defer_normal => {
2557 const defer_scope = scope.cast(Scope.Defer).?;2587 const defer_scope = scope.cast(Scope.Defer).?;
2558 scope = defer_scope.parent;2588 scope = defer_scope.parent;
...@@ -2602,6 +2632,7 @@ fn genDefers(...@@ -2602,6 +2632,7 @@ fn genDefers(
2602 .gen_zir => scope = scope.cast(GenZir).?.parent,2632 .gen_zir => scope = scope.cast(GenZir).?.parent,
2603 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,2633 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2604 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,2634 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2635 .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent,
2605 .defer_normal => {2636 .defer_normal => {
2606 const defer_scope = scope.cast(Scope.Defer).?;2637 const defer_scope = scope.cast(Scope.Defer).?;
2607 scope = defer_scope.parent;2638 scope = defer_scope.parent;
...@@ -2681,6 +2712,7 @@ fn checkUsed(...@@ -2681,6 +2712,7 @@ fn checkUsed(
2681 scope = s.parent;2712 scope = s.parent;
2682 },2713 },
2683 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,2714 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2715 .defer_gen => scope = scope.cast(Scope.DeferGen).?.parent,
2684 .namespace => unreachable,2716 .namespace => unreachable,
2685 .top => unreachable,2717 .top => unreachable,
2686 }2718 }
...@@ -4040,6 +4072,7 @@ fn testDecl(...@@ -4040,6 +4072,7 @@ fn testDecl(
4040 .local_val, .local_ptr => unreachable, // a test cannot be in a local scope4072 .local_val, .local_ptr => unreachable, // a test cannot be in a local scope
4041 .gen_zir => s = s.cast(GenZir).?.parent,4073 .gen_zir => s = s.cast(GenZir).?.parent,
4042 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,4074 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
4075 .defer_gen => s = s.cast(Scope.DeferGen).?.parent,
4043 .namespace => {4076 .namespace => {
4044 const ns = s.cast(Scope.Namespace).?;4077 const ns = s.cast(Scope.Namespace).?;
4045 if (ns.decls.get(name_str_index)) |i| {4078 if (ns.decls.get(name_str_index)) |i| {
...@@ -6730,6 +6763,7 @@ fn localVarRef(...@@ -6730,6 +6763,7 @@ fn localVarRef(
6730 },6763 },
6731 .gen_zir => s = s.cast(GenZir).?.parent,6764 .gen_zir => s = s.cast(GenZir).?.parent,
6732 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,6765 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
6766 .defer_gen => s = s.cast(Scope.DeferGen).?.parent,
6733 .namespace => {6767 .namespace => {
6734 const ns = s.cast(Scope.Namespace).?;6768 const ns = s.cast(Scope.Namespace).?;
6735 if (ns.decls.get(name_str_index)) |i| {6769 if (ns.decls.get(name_str_index)) |i| {
...@@ -7351,6 +7385,7 @@ fn builtinCall(...@@ -7351,6 +7385,7 @@ fn builtinCall(
7351 },7385 },
7352 .gen_zir => s = s.cast(GenZir).?.parent,7386 .gen_zir => s = s.cast(GenZir).?.parent,
7353 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,7387 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
7388 .defer_gen => s = s.cast(Scope.DeferGen).?.parent,
7354 .namespace => {7389 .namespace => {
7355 const ns = s.cast(Scope.Namespace).?;7390 const ns = s.cast(Scope.Namespace).?;
7356 if (ns.decls.get(decl_name)) |i| {7391 if (ns.decls.get(decl_name)) |i| {
...@@ -9808,6 +9843,7 @@ const Scope = struct {...@@ -9808,6 +9843,7 @@ const Scope = struct {
9808 local_ptr,9843 local_ptr,
9809 defer_normal,9844 defer_normal,
9810 defer_error,9845 defer_error,
9846 defer_gen,
9811 namespace,9847 namespace,
9812 top,9848 top,
9813 };9849 };
...@@ -9905,6 +9941,13 @@ const Scope = struct {...@@ -9905,6 +9941,13 @@ const Scope = struct {
9905 const base_tag: Scope.Tag = .top;9941 const base_tag: Scope.Tag = .top;
9906 base: Scope = Scope{ .tag = base_tag },9942 base: Scope = Scope{ .tag = base_tag },
9907 };9943 };
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 };
9908};9951};
99099952
9910/// This is a temporary structure; references to it are valid only9953/// This is a temporary structure; references to it are valid only
...@@ -11415,6 +11458,7 @@ fn detectLocalShadowing(...@@ -11415,6 +11458,7 @@ fn detectLocalShadowing(
11415 },11458 },
11416 .gen_zir => s = s.cast(GenZir).?.parent,11459 .gen_zir => s = s.cast(GenZir).?.parent,
11417 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,11460 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
11461 .defer_gen => s = s.cast(Scope.DeferGen).?.parent,
11418 .top => break,11462 .top => break,
11419 };11463 };
11420}11464}
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