authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-05-20 16:03:50-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-22 20:54:14-04:00
log9baf8917725ede02d9fc1aeebe253842174ee57b
tree5d9d84872f1686e5b6986804f4cd7fad32713e93
parentceacb7d247950010bf42eb1390229c6fb808f949

stage2: astgen error for return or try in defer block


2 files changed, 41 insertions(+), 0 deletions(-)

src/AstGen.zig+23
......@@ -86,6 +86,7 @@ pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
8686
8787 var gen_scope: GenZir = .{
8888 .force_comptime = true,
89 .in_defer = false,
8990 .parent = &top_scope.base,
9091 .anon_name_strategy = .parent,
9192 .decl_node_index = 0,
......@@ -2118,14 +2119,20 @@ fn genDefers(
21182119 const defer_scope = scope.cast(Scope.Defer).?;
21192120 scope = defer_scope.parent;
21202121 const expr_node = node_datas[defer_scope.defer_node].rhs;
2122 const prev_in_defer = gz.in_defer;
2123 gz.in_defer = true;
21212124 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2125 gz.in_defer = prev_in_defer;
21222126 },
21232127 .defer_error => {
21242128 const defer_scope = scope.cast(Scope.Defer).?;
21252129 scope = defer_scope.parent;
21262130 if (err_code == .none) continue;
21272131 const expr_node = node_datas[defer_scope.defer_node].rhs;
2132 const prev_in_defer = gz.in_defer;
2133 gz.in_defer = true;
21282134 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2135 gz.in_defer = prev_in_defer;
21292136 },
21302137 .namespace => unreachable,
21312138 .top => unreachable,
......@@ -2728,6 +2735,7 @@ fn fnDecl(
27282735
27292736 var decl_gz: GenZir = .{
27302737 .force_comptime = true,
2738 .in_defer = false,
27312739 .decl_node_index = fn_proto.ast.proto_node,
27322740 .decl_line = gz.calcLine(decl_node),
27332741 .parent = scope,
......@@ -2851,6 +2859,7 @@ fn fnDecl(
28512859
28522860 var fn_gz: GenZir = .{
28532861 .force_comptime = false,
2862 .in_defer = false,
28542863 .decl_node_index = fn_proto.ast.proto_node,
28552864 .decl_line = decl_gz.decl_line,
28562865 .parent = &decl_gz.base,
......@@ -2981,6 +2990,7 @@ fn globalVarDecl(
29812990 .decl_line = gz.calcLine(node),
29822991 .astgen = astgen,
29832992 .force_comptime = true,
2993 .in_defer = false,
29842994 .anon_name_strategy = .parent,
29852995 };
29862996 defer block_scope.instructions.deinit(gpa);
......@@ -3117,6 +3127,7 @@ fn comptimeDecl(
31173127
31183128 var decl_block: GenZir = .{
31193129 .force_comptime = true,
3130 .in_defer = false,
31203131 .decl_node_index = node,
31213132 .decl_line = gz.calcLine(node),
31223133 .parent = scope,
......@@ -3169,6 +3180,7 @@ fn usingnamespaceDecl(
31693180
31703181 var decl_block: GenZir = .{
31713182 .force_comptime = true,
3183 .in_defer = false,
31723184 .decl_node_index = node,
31733185 .decl_line = gz.calcLine(node),
31743186 .parent = scope,
......@@ -3214,6 +3226,7 @@ fn testDecl(
32143226
32153227 var decl_block: GenZir = .{
32163228 .force_comptime = true,
3229 .in_defer = false,
32173230 .decl_node_index = node,
32183231 .decl_line = gz.calcLine(node),
32193232 .parent = scope,
......@@ -3235,6 +3248,7 @@ fn testDecl(
32353248
32363249 var fn_block: GenZir = .{
32373250 .force_comptime = false,
3251 .in_defer = false,
32383252 .decl_node_index = node,
32393253 .decl_line = decl_block.decl_line,
32403254 .parent = &decl_block.base,
......@@ -3319,6 +3333,7 @@ fn structDeclInner(
33193333 .decl_line = gz.calcLine(node),
33203334 .astgen = astgen,
33213335 .force_comptime = true,
3336 .in_defer = false,
33223337 .ref_start_index = gz.ref_start_index,
33233338 };
33243339 defer block_scope.instructions.deinit(gpa);
......@@ -3580,6 +3595,7 @@ fn unionDeclInner(
35803595 .decl_line = gz.calcLine(node),
35813596 .astgen = astgen,
35823597 .force_comptime = true,
3598 .in_defer = false,
35833599 .ref_start_index = gz.ref_start_index,
35843600 };
35853601 defer block_scope.instructions.deinit(gpa);
......@@ -3976,6 +3992,7 @@ fn containerDecl(
39763992 .decl_line = gz.calcLine(node),
39773993 .astgen = astgen,
39783994 .force_comptime = true,
3995 .in_defer = false,
39793996 .ref_start_index = gz.ref_start_index,
39803997 };
39813998 defer block_scope.instructions.deinit(gpa);
......@@ -4432,6 +4449,8 @@ fn tryExpr(
44324449 return astgen.failNode(node, "invalid 'try' outside function scope", .{});
44334450 };
44344451
4452 if (parent_gz.in_defer) return astgen.failNode(node, "try is not allowed inside defer expression", .{});
4453
44354454 var block_scope = parent_gz.makeSubBlock(scope);
44364455 block_scope.setBreakResultLoc(rl);
44374456 defer block_scope.instructions.deinit(astgen.gpa);
......@@ -5962,6 +5981,8 @@ fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref
59625981 const node_datas = tree.nodes.items(.data);
59635982 const main_tokens = tree.nodes.items(.main_token);
59645983
5984 if (gz.in_defer) return astgen.failNode(node, "cannot return from defer expression", .{});
5985
59655986 const operand_node = node_datas[node].lhs;
59665987 if (operand_node != 0) {
59675988 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{
......@@ -8040,6 +8061,7 @@ const GenZir = struct {
80408061 const base_tag: Scope.Tag = .gen_zir;
80418062 base: Scope = Scope{ .tag = base_tag },
80428063 force_comptime: bool,
8064 in_defer: bool,
80438065 /// How decls created in this scope should be named.
80448066 anon_name_strategy: Zir.Inst.NameStrategy = .anon,
80458067 /// The end of special indexes. `Zir.Inst.Ref` subtracts against this number to convert
......@@ -8087,6 +8109,7 @@ const GenZir = struct {
80878109 fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
80888110 return .{
80898111 .force_comptime = gz.force_comptime,
8112 .in_defer = gz.in_defer,
80908113 .ref_start_index = gz.ref_start_index,
80918114 .decl_node_index = gz.decl_node_index,
80928115 .decl_line = gz.decl_line,
test/stage2/test.zig+18
......@@ -926,6 +926,24 @@ pub fn addCases(ctx: *TestContext) !void {
926926 ":5:1: note: declared here",
927927 });
928928
929 ctx.compileError("returns in try", linux_x64,
930 \\pub fn main() !void {
931 \\ try a();
932 \\ try b();
933 \\}
934 \\
935 \\pub fn a() !void {
936 \\ defer try b();
937 \\}
938 \\pub fn b() !void {
939 \\ defer return a();
940 \\}
941
942 , &[_][]const u8{
943 ":7:8: error: try is not allowed inside defer expression",
944 ":10:8: error: cannot return from defer expression",
945 });
946
929947 ctx.compileError("global variable redeclaration", linux_x64,
930948 \\// dummy comment
931949 \\var foo = false;