aboutsummaryrefslogtreecommitdiff
path: root/src/AstGen.zig
diff options
context:
space:
mode:
authorjacob gw <jacoblevgw@gmail.com>2021-05-20 16:03:50 -0400
committerAndrew Kelley <andrew@ziglang.org>2021-05-22 20:54:14 -0400
commit9baf8917725ede02d9fc1aeebe253842174ee57b (patch)
tree5d9d84872f1686e5b6986804f4cd7fad32713e93 /src/AstGen.zig
parentceacb7d247950010bf42eb1390229c6fb808f949 (diff)
downloadzig-9baf8917725ede02d9fc1aeebe253842174ee57b.tar.gz
zig-9baf8917725ede02d9fc1aeebe253842174ee57b.zip
stage2: astgen error for return or try in defer block
Diffstat (limited to 'src/AstGen.zig')
-rw-r--r--src/AstGen.zig23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 8798c98021..fd2016aa11 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -86,6 +86,7 @@ pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
var gen_scope: GenZir = .{
.force_comptime = true,
+ .in_defer = false,
.parent = &top_scope.base,
.anon_name_strategy = .parent,
.decl_node_index = 0,
@@ -2118,14 +2119,20 @@ fn genDefers(
const defer_scope = scope.cast(Scope.Defer).?;
scope = defer_scope.parent;
const expr_node = node_datas[defer_scope.defer_node].rhs;
+ const prev_in_defer = gz.in_defer;
+ gz.in_defer = true;
try unusedResultExpr(gz, defer_scope.parent, expr_node);
+ gz.in_defer = prev_in_defer;
},
.defer_error => {
const defer_scope = scope.cast(Scope.Defer).?;
scope = defer_scope.parent;
if (err_code == .none) continue;
const expr_node = node_datas[defer_scope.defer_node].rhs;
+ const prev_in_defer = gz.in_defer;
+ gz.in_defer = true;
try unusedResultExpr(gz, defer_scope.parent, expr_node);
+ gz.in_defer = prev_in_defer;
},
.namespace => unreachable,
.top => unreachable,
@@ -2728,6 +2735,7 @@ fn fnDecl(
var decl_gz: GenZir = .{
.force_comptime = true,
+ .in_defer = false,
.decl_node_index = fn_proto.ast.proto_node,
.decl_line = gz.calcLine(decl_node),
.parent = scope,
@@ -2851,6 +2859,7 @@ fn fnDecl(
var fn_gz: GenZir = .{
.force_comptime = false,
+ .in_defer = false,
.decl_node_index = fn_proto.ast.proto_node,
.decl_line = decl_gz.decl_line,
.parent = &decl_gz.base,
@@ -2981,6 +2990,7 @@ fn globalVarDecl(
.decl_line = gz.calcLine(node),
.astgen = astgen,
.force_comptime = true,
+ .in_defer = false,
.anon_name_strategy = .parent,
};
defer block_scope.instructions.deinit(gpa);
@@ -3117,6 +3127,7 @@ fn comptimeDecl(
var decl_block: GenZir = .{
.force_comptime = true,
+ .in_defer = false,
.decl_node_index = node,
.decl_line = gz.calcLine(node),
.parent = scope,
@@ -3169,6 +3180,7 @@ fn usingnamespaceDecl(
var decl_block: GenZir = .{
.force_comptime = true,
+ .in_defer = false,
.decl_node_index = node,
.decl_line = gz.calcLine(node),
.parent = scope,
@@ -3214,6 +3226,7 @@ fn testDecl(
var decl_block: GenZir = .{
.force_comptime = true,
+ .in_defer = false,
.decl_node_index = node,
.decl_line = gz.calcLine(node),
.parent = scope,
@@ -3235,6 +3248,7 @@ fn testDecl(
var fn_block: GenZir = .{
.force_comptime = false,
+ .in_defer = false,
.decl_node_index = node,
.decl_line = decl_block.decl_line,
.parent = &decl_block.base,
@@ -3319,6 +3333,7 @@ fn structDeclInner(
.decl_line = gz.calcLine(node),
.astgen = astgen,
.force_comptime = true,
+ .in_defer = false,
.ref_start_index = gz.ref_start_index,
};
defer block_scope.instructions.deinit(gpa);
@@ -3580,6 +3595,7 @@ fn unionDeclInner(
.decl_line = gz.calcLine(node),
.astgen = astgen,
.force_comptime = true,
+ .in_defer = false,
.ref_start_index = gz.ref_start_index,
};
defer block_scope.instructions.deinit(gpa);
@@ -3976,6 +3992,7 @@ fn containerDecl(
.decl_line = gz.calcLine(node),
.astgen = astgen,
.force_comptime = true,
+ .in_defer = false,
.ref_start_index = gz.ref_start_index,
};
defer block_scope.instructions.deinit(gpa);
@@ -4432,6 +4449,8 @@ fn tryExpr(
return astgen.failNode(node, "invalid 'try' outside function scope", .{});
};
+ if (parent_gz.in_defer) return astgen.failNode(node, "try is not allowed inside defer expression", .{});
+
var block_scope = parent_gz.makeSubBlock(scope);
block_scope.setBreakResultLoc(rl);
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
const node_datas = tree.nodes.items(.data);
const main_tokens = tree.nodes.items(.main_token);
+ if (gz.in_defer) return astgen.failNode(node, "cannot return from defer expression", .{});
+
const operand_node = node_datas[node].lhs;
if (operand_node != 0) {
const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{
@@ -8040,6 +8061,7 @@ const GenZir = struct {
const base_tag: Scope.Tag = .gen_zir;
base: Scope = Scope{ .tag = base_tag },
force_comptime: bool,
+ in_defer: bool,
/// How decls created in this scope should be named.
anon_name_strategy: Zir.Inst.NameStrategy = .anon,
/// The end of special indexes. `Zir.Inst.Ref` subtracts against this number to convert
@@ -8087,6 +8109,7 @@ const GenZir = struct {
fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
return .{
.force_comptime = gz.force_comptime,
+ .in_defer = gz.in_defer,
.ref_start_index = gz.ref_start_index,
.decl_node_index = gz.decl_node_index,
.decl_line = gz.decl_line,