authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-07 18:12:56-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-07 18:13:54-05:00
log598170756cd91b6f300921d256baa72141ec3098
tree241d9000faac13be10f36a4963c70e9ea01a439c
parent632d143bff3611be8a48d8c9c9dc9d56e759eb15

`a catch unreachable` generates unwrap-error code

See #545 See #510 See #632

2 files changed, 22 insertions(+), 9 deletions(-)

src/ir.cpp+17-7
......@@ -3898,22 +3898,21 @@ static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *n
38983898 align_value, bit_offset_start, bit_offset_end);
38993899}
39003900
3901static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
3902 assert(node->type == NodeTypePrefixOpExpr);
3903 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
3904
3901static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
3902 LVal lval)
3903{
39053904 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR);
39063905 if (err_union_ptr == irb->codegen->invalid_instruction)
39073906 return irb->codegen->invalid_instruction;
39083907
3909 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, true);
3908 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, source_node, err_union_ptr, true);
39103909 if (payload_ptr == irb->codegen->invalid_instruction)
39113910 return irb->codegen->invalid_instruction;
39123911
39133912 if (lval.is_ptr)
39143913 return payload_ptr;
39153914
3916 return ir_build_load_ptr(irb, scope, node, payload_ptr);
3915 return ir_build_load_ptr(irb, scope, source_node, payload_ptr);
39173916}
39183917
39193918static IrInstruction *ir_gen_maybe_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
......@@ -3965,7 +3964,7 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
39653964 case PrefixOpError:
39663965 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpError), lval);
39673966 case PrefixOpUnwrapError:
3968 return ir_gen_err_assert_ok(irb, scope, node, lval);
3967 return ir_gen_err_assert_ok(irb, scope, node, node->data.prefix_op_expr.primary_expr, lval);
39693968 case PrefixOpUnwrapMaybe:
39703969 return ir_gen_maybe_assert_ok(irb, scope, node, lval);
39713970 }
......@@ -5181,6 +5180,17 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
51815180 AstNode *op2_node = node->data.unwrap_err_expr.op2;
51825181 AstNode *var_node = node->data.unwrap_err_expr.symbol;
51835182
5183 if (op2_node->type == NodeTypeUnreachable) {
5184 if (var_node != nullptr) {
5185 assert(var_node->type == NodeTypeSymbol);
5186 Buf *var_name = var_node->data.symbol_expr.symbol;
5187 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
5188 return irb->codegen->invalid_instruction;
5189 }
5190 return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LVAL_NONE);
5191 }
5192
5193
51845194 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LVAL_PTR);
51855195 if (err_union_ptr == irb->codegen->invalid_instruction)
51865196 return irb->codegen->invalid_instruction;
test/debug_safety.zig+5-2
......@@ -221,11 +221,14 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
221221
222222 cases.addDebugSafety("unwrap error",
223223 \\pub fn panic(message: []const u8) -> noreturn {
224 \\ @import("std").os.exit(126);
224 \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {
225 \\ @import("std").os.exit(126); // good
226 \\ }
227 \\ @import("std").os.exit(0); // test failed
225228 \\}
226229 \\error Whatever;
227230 \\pub fn main() -> %void {
228 \\ %%bar();
231 \\ bar() catch unreachable;
229232 \\}
230233 \\fn bar() -> %void {
231234 \\ return error.Whatever;