authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-21 10:41:57-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-21 10:44:55-04:00
log9f3cca861557dab5c56d4ee5a35acd93180ef862
tree09187b849588dccd412f4c5f43276be35288cba9
parent1c6f415a6416f8b29897393b8adfef45e1a2b51f

add error for break/continue exiting defer expression

See #284

6 files changed, 145 insertions(+), 74 deletions(-)

src/all_types.hpp+6-1
...@@ -1636,9 +1636,14 @@ struct ScopeCImport {...@@ -1636,9 +1636,14 @@ struct ScopeCImport {
1636// This scope is created for a loop such as for or while in order to1636// This scope is created for a loop such as for or while in order to
1637// make break and continue statements work.1637// make break and continue statements work.
1638// NodeTypeForExpr or NodeTypeWhileExpr1638// NodeTypeForExpr or NodeTypeWhileExpr
1639// TODO I think we can get rid of this
1640struct ScopeLoop {1639struct ScopeLoop {
1641 Scope base;1640 Scope base;
1641
1642 IrBasicBlock *break_block;
1643 IrBasicBlock *continue_block;
1644 IrInstruction *is_comptime;
1645 ZigList<IrInstruction *> *incoming_values;
1646 ZigList<IrBasicBlock *> *incoming_blocks;
1642};1647};
16431648
1644// This scope is created for a comptime expression.1649// This scope is created for a comptime expression.
src/analyze.cpp+2-2
...@@ -122,11 +122,11 @@ ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent) {...@@ -122,11 +122,11 @@ ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent) {
122 return scope;122 return scope;
123}123}
124124
125Scope *create_loop_scope(AstNode *node, Scope *parent) {125ScopeLoop *create_loop_scope(AstNode *node, Scope *parent) {
126 assert(node->type == NodeTypeWhileExpr || node->type == NodeTypeForExpr);126 assert(node->type == NodeTypeWhileExpr || node->type == NodeTypeForExpr);
127 ScopeLoop *scope = allocate<ScopeLoop>(1);127 ScopeLoop *scope = allocate<ScopeLoop>(1);
128 init_scope(&scope->base, ScopeIdLoop, node, parent);128 init_scope(&scope->base, ScopeIdLoop, node, parent);
129 return &scope->base;129 return scope;
130}130}
131131
132ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry) {132ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry) {
src/analyze.hpp+1-1
...@@ -97,7 +97,7 @@ ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);...@@ -97,7 +97,7 @@ ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
97ScopeDeferExpr *create_defer_expr_scope(AstNode *node, Scope *parent);97ScopeDeferExpr *create_defer_expr_scope(AstNode *node, Scope *parent);
98Scope *create_var_scope(AstNode *node, Scope *parent, VariableTableEntry *var);98Scope *create_var_scope(AstNode *node, Scope *parent, VariableTableEntry *var);
99ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);99ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);
100Scope *create_loop_scope(AstNode *node, Scope *parent);100ScopeLoop *create_loop_scope(AstNode *node, Scope *parent);
101ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);101ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);
102ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);102ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);
103Scope *create_comptime_scope(AstNode *node, Scope *parent);103Scope *create_comptime_scope(AstNode *node, Scope *parent);
src/ir.cpp+95-67
...@@ -19,19 +19,10 @@ struct IrExecContext {...@@ -19,19 +19,10 @@ struct IrExecContext {
19 size_t mem_slot_count;19 size_t mem_slot_count;
20};20};
2121
22struct LoopStackItem {
23 IrBasicBlock *break_block;
24 IrBasicBlock *continue_block;
25 IrInstruction *is_comptime;
26 ZigList<IrInstruction *> *incoming_values;
27 ZigList<IrBasicBlock *> *incoming_blocks;
28};
29
30struct IrBuilder {22struct IrBuilder {
31 CodeGen *codegen;23 CodeGen *codegen;
32 IrExecutable *exec;24 IrExecutable *exec;
33 IrBasicBlock *current_basic_block;25 IrBasicBlock *current_basic_block;
34 ZigList<LoopStackItem> loop_stack;
35};26};
3627
37struct IrAnalyze {28struct IrAnalyze {
...@@ -59,18 +50,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc...@@ -59,18 +50,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc
59static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);50static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
60static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);51static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);
6152
62static LoopStackItem *add_loop_stack_item(IrBuilder *irb, IrBasicBlock *break_block, IrBasicBlock *continue_block,
63 IrInstruction *is_comptime, ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
64{
65 LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
66 loop_stack_item->break_block = break_block;
67 loop_stack_item->continue_block = continue_block;
68 loop_stack_item->is_comptime = is_comptime;
69 loop_stack_item->incoming_blocks = incoming_blocks;
70 loop_stack_item->incoming_values = incoming_values;
71 return loop_stack_item;
72}
73
74ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {53ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
75 assert(const_val->type->id == TypeTableEntryIdPointer);54 assert(const_val->type->id == TypeTableEntryIdPointer);
76 assert(const_val->special == ConstValSpecialStatic);55 assert(const_val->special == ConstValSpecialStatic);
...@@ -4748,13 +4727,20 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -4748,13 +4727,20 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4748 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);4727 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
4749 ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, var_value);4728 ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, var_value);
4750 }4729 }
4730
4751 ZigList<IrInstruction *> incoming_values = {0};4731 ZigList<IrInstruction *> incoming_values = {0};
4752 ZigList<IrBasicBlock *> incoming_blocks = {0};4732 ZigList<IrBasicBlock *> incoming_blocks = {0};
4753 add_loop_stack_item(irb, end_block, continue_block, is_comptime, &incoming_blocks, &incoming_values);4733
4754 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, payload_scope);4734 ScopeLoop *loop_scope = create_loop_scope(node, payload_scope);
4735 loop_scope->break_block = end_block;
4736 loop_scope->continue_block = continue_block;
4737 loop_scope->is_comptime = is_comptime;
4738 loop_scope->incoming_blocks = &incoming_blocks;
4739 loop_scope->incoming_values = &incoming_values;
4740
4741 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
4755 if (body_result == irb->codegen->invalid_instruction)4742 if (body_result == irb->codegen->invalid_instruction)
4756 return body_result;4743 return body_result;
4757 irb->loop_stack.pop();
47584744
4759 if (!instr_is_unreachable(body_result))4745 if (!instr_is_unreachable(body_result))
4760 ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime));4746 ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime));
...@@ -4821,13 +4807,20 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -4821,13 +4807,20 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4821 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?4807 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
4822 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);4808 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
4823 ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, var_value);4809 ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, var_value);
4810
4824 ZigList<IrInstruction *> incoming_values = {0};4811 ZigList<IrInstruction *> incoming_values = {0};
4825 ZigList<IrBasicBlock *> incoming_blocks = {0};4812 ZigList<IrBasicBlock *> incoming_blocks = {0};
4826 add_loop_stack_item(irb, end_block, continue_block, is_comptime, &incoming_blocks, &incoming_values);4813
4827 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, child_scope);4814 ScopeLoop *loop_scope = create_loop_scope(node, child_scope);
4815 loop_scope->break_block = end_block;
4816 loop_scope->continue_block = continue_block;
4817 loop_scope->is_comptime = is_comptime;
4818 loop_scope->incoming_blocks = &incoming_blocks;
4819 loop_scope->incoming_values = &incoming_values;
4820
4821 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
4828 if (body_result == irb->codegen->invalid_instruction)4822 if (body_result == irb->codegen->invalid_instruction)
4829 return body_result;4823 return body_result;
4830 irb->loop_stack.pop();
48314824
4832 if (!instr_is_unreachable(body_result))4825 if (!instr_is_unreachable(body_result))
4833 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));4826 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));
...@@ -4887,11 +4880,17 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -4887,11 +4880,17 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
48874880
4888 ZigList<IrInstruction *> incoming_values = {0};4881 ZigList<IrInstruction *> incoming_values = {0};
4889 ZigList<IrBasicBlock *> incoming_blocks = {0};4882 ZigList<IrBasicBlock *> incoming_blocks = {0};
4890 add_loop_stack_item(irb, end_block, continue_block, is_comptime, &incoming_blocks, &incoming_values);4883
4891 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, scope);4884 ScopeLoop *loop_scope = create_loop_scope(node, scope);
4885 loop_scope->break_block = end_block;
4886 loop_scope->continue_block = continue_block;
4887 loop_scope->is_comptime = is_comptime;
4888 loop_scope->incoming_blocks = &incoming_blocks;
4889 loop_scope->incoming_values = &incoming_values;
4890
4891 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
4892 if (body_result == irb->codegen->invalid_instruction)4892 if (body_result == irb->codegen->invalid_instruction)
4893 return body_result;4893 return body_result;
4894 irb->loop_stack.pop();
48954894
4896 if (!instr_is_unreachable(body_result))4895 if (!instr_is_unreachable(body_result))
4897 ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime));4896 ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime));
...@@ -4952,12 +4951,10 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -4952,12 +4951,10 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
4952 IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,4951 IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,
4953 ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);4952 ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);
49544953
4955 Scope *child_scope = create_loop_scope(node, parent_scope);
4956
4957 // TODO make it an error to write to element variable or i variable.4954 // TODO make it an error to write to element variable or i variable.
4958 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;4955 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
4959 VariableTableEntry *elem_var = ir_create_var(irb, elem_node, child_scope, elem_var_name, true, false, false, is_comptime);4956 VariableTableEntry *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
4960 child_scope = elem_var->child_scope;4957 Scope *child_scope = elem_var->child_scope;
49614958
4962 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);4959 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
4963 ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, undefined_value);4960 ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, undefined_value);
...@@ -5010,9 +5007,14 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5010,9 +5007,14 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
50105007
5011 ZigList<IrInstruction *> incoming_values = {0};5008 ZigList<IrInstruction *> incoming_values = {0};
5012 ZigList<IrBasicBlock *> incoming_blocks = {0};5009 ZigList<IrBasicBlock *> incoming_blocks = {0};
5013 add_loop_stack_item(irb, end_block, continue_block, is_comptime, &incoming_blocks, &incoming_values);5010 ScopeLoop *loop_scope = create_loop_scope(node, child_scope);
5014 IrInstruction *body_result = ir_gen_node(irb, body_node, child_scope);5011 loop_scope->break_block = end_block;
5015 irb->loop_stack.pop();5012 loop_scope->continue_block = continue_block;
5013 loop_scope->is_comptime = is_comptime;
5014 loop_scope->incoming_blocks = &incoming_blocks;
5015 loop_scope->incoming_values = &incoming_values;
5016
5017 IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base);
50165018
5017 if (!instr_is_unreachable(body_result))5019 if (!instr_is_unreachable(body_result))
5018 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));5020 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));
...@@ -5584,62 +5586,88 @@ static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5584,62 +5586,88 @@ static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNo
5584 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval);5586 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval);
5585}5587}
55865588
5587static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node) {5589static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *node) {
5588 assert(node->type == NodeTypeBreak);5590 assert(node->type == NodeTypeBreak);
55895591
5590 if (irb->loop_stack.length == 0) {5592 // Search up the scope. We'll find one of these things first:
5591 add_node_error(irb->codegen, node,5593 // * function definition scope or global scope => error, break outside loop
5592 buf_sprintf("'break' expression outside loop"));5594 // * defer expression scope => error, cannot break out of defer expression
5593 return irb->codegen->invalid_instruction;5595 // * loop scope => OK
5594 }
55955596
5596 LoopStackItem *loop_stack_item = &irb->loop_stack.last();5597 Scope *search_scope = break_scope;
5598 ScopeLoop *loop_scope;
5599 for (;;) {
5600 if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) {
5601 add_node_error(irb->codegen, node, buf_sprintf("break expression outside loop"));
5602 return irb->codegen->invalid_instruction;
5603 } else if (search_scope->id == ScopeIdDeferExpr) {
5604 add_node_error(irb->codegen, node, buf_sprintf("cannot break out of defer expression"));
5605 return irb->codegen->invalid_instruction;
5606 } else if (search_scope->id == ScopeIdLoop) {
5607 loop_scope = (ScopeLoop *)search_scope;
5608 break;
5609 }
5610 search_scope = search_scope->parent;
5611 }
55975612
5598 IrInstruction *is_comptime;5613 IrInstruction *is_comptime;
5599 if (ir_should_inline(irb->exec, scope)) {5614 if (ir_should_inline(irb->exec, break_scope)) {
5600 is_comptime = ir_build_const_bool(irb, scope, node, true);5615 is_comptime = ir_build_const_bool(irb, break_scope, node, true);
5601 } else {5616 } else {
5602 is_comptime = loop_stack_item->is_comptime;5617 is_comptime = loop_scope->is_comptime;
5603 }5618 }
56045619
5605 IrInstruction *result_value;5620 IrInstruction *result_value;
5606 if (node->data.break_expr.expr) {5621 if (node->data.break_expr.expr) {
5607 result_value = ir_gen_node(irb, node->data.break_expr.expr, scope);5622 result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope);
5608 if (result_value == irb->codegen->invalid_instruction)5623 if (result_value == irb->codegen->invalid_instruction)
5609 return irb->codegen->invalid_instruction;5624 return irb->codegen->invalid_instruction;
5610 } else {5625 } else {
5611 result_value = ir_build_const_void(irb, scope, node);5626 result_value = ir_build_const_void(irb, break_scope, node);
5612 }5627 }
56135628
5614 IrBasicBlock *dest_block = loop_stack_item->break_block;5629 IrBasicBlock *dest_block = loop_scope->break_block;
5615 ir_gen_defers_for_block(irb, scope, dest_block->scope, false);5630 ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false);
56165631
5617 loop_stack_item->incoming_blocks->append(irb->current_basic_block);5632 loop_scope->incoming_blocks->append(irb->current_basic_block);
5618 loop_stack_item->incoming_values->append(result_value);5633 loop_scope->incoming_values->append(result_value);
5619 return ir_build_br(irb, scope, node, dest_block, is_comptime);5634 return ir_build_br(irb, break_scope, node, dest_block, is_comptime);
5620}5635}
56215636
5622static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *node) {5637static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, AstNode *node) {
5623 assert(node->type == NodeTypeContinue);5638 assert(node->type == NodeTypeContinue);
56245639
5625 if (irb->loop_stack.length == 0) {5640 // Search up the scope. We'll find one of these things first:
5626 add_node_error(irb->codegen, node,5641 // * function definition scope or global scope => error, break outside loop
5627 buf_sprintf("'continue' expression outside loop"));5642 // * defer expression scope => error, cannot break out of defer expression
5628 return irb->codegen->invalid_instruction;5643 // * loop scope => OK
5629 }
56305644
5631 LoopStackItem *loop_stack_item = &irb->loop_stack.last();5645 Scope *search_scope = continue_scope;
5646 ScopeLoop *loop_scope;
5647 for (;;) {
5648 if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) {
5649 add_node_error(irb->codegen, node, buf_sprintf("continue expression outside loop"));
5650 return irb->codegen->invalid_instruction;
5651 } else if (search_scope->id == ScopeIdDeferExpr) {
5652 add_node_error(irb->codegen, node, buf_sprintf("cannot continue out of defer expression"));
5653 return irb->codegen->invalid_instruction;
5654 } else if (search_scope->id == ScopeIdLoop) {
5655 loop_scope = (ScopeLoop *)search_scope;
5656 break;
5657 }
5658 search_scope = search_scope->parent;
5659 }
56325660
5633 IrInstruction *is_comptime;5661 IrInstruction *is_comptime;
5634 if (ir_should_inline(irb->exec, scope)) {5662 if (ir_should_inline(irb->exec, continue_scope)) {
5635 is_comptime = ir_build_const_bool(irb, scope, node, true);5663 is_comptime = ir_build_const_bool(irb, continue_scope, node, true);
5636 } else {5664 } else {
5637 is_comptime = loop_stack_item->is_comptime;5665 is_comptime = loop_scope->is_comptime;
5638 }5666 }
56395667
5640 IrBasicBlock *dest_block = loop_stack_item->continue_block;5668 IrBasicBlock *dest_block = loop_scope->continue_block;
5641 ir_gen_defers_for_block(irb, scope, dest_block->scope, false);5669 ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false);
5642 return ir_build_br(irb, scope, node, dest_block, is_comptime);5670 return ir_build_br(irb, continue_scope, node, dest_block, is_comptime);
5643}5671}
56445672
5645static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) {5673static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) {
test/cases/defer.zig+17-1
...@@ -13,7 +13,7 @@ fn runSomeErrorDefers(x: bool) -> %bool {...@@ -13,7 +13,7 @@ fn runSomeErrorDefers(x: bool) -> %bool {
13 return if (x) x else error.FalseNotAllowed;13 return if (x) x else error.FalseNotAllowed;
14}14}
1515
16test "mixingNormalAndErrorDefers" {16test "mixing normal and error defers" {
17 assert(%%runSomeErrorDefers(true));17 assert(%%runSomeErrorDefers(true));
18 assert(result[0] == 'c');18 assert(result[0] == 'c');
19 assert(result[1] == 'a');19 assert(result[1] == 'a');
...@@ -27,3 +27,19 @@ test "mixingNormalAndErrorDefers" {...@@ -27,3 +27,19 @@ test "mixingNormalAndErrorDefers" {
27 assert(result[1] == 'b');27 assert(result[1] == 'b');
28 assert(result[2] == 'a');28 assert(result[2] == 'a');
29}29}
30
31test "break and continue inside loop inside defer expression" {
32 testBreakContInDefer(10);
33 comptime testBreakContInDefer(10);
34}
35
36fn testBreakContInDefer(x: usize) {
37 defer {
38 var i: usize = 0;
39 while (i < x) : (i += 1) {
40 if (i < 5) continue;
41 if (i == 5) break;
42 }
43 assert(i == 5);
44 };
45}
test/compile_errors.zig+24-2
...@@ -472,13 +472,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -472,13 +472,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
472 \\export fn f() {472 \\export fn f() {
473 \\ break;473 \\ break;
474 \\}474 \\}
475 , ".tmp_source.zig:2:5: error: 'break' expression outside loop");475 , ".tmp_source.zig:2:5: error: break expression outside loop");
476476
477 cases.add("invalid continue expression",477 cases.add("invalid continue expression",
478 \\export fn f() {478 \\export fn f() {
479 \\ continue;479 \\ continue;
480 \\}480 \\}
481 , ".tmp_source.zig:2:5: error: 'continue' expression outside loop");481 , ".tmp_source.zig:2:5: error: continue expression outside loop");
482482
483 cases.add("invalid maybe type",483 cases.add("invalid maybe type",
484 \\export fn f() {484 \\export fn f() {
...@@ -1860,4 +1860,26 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -1860,4 +1860,26 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
1860 \\}1860 \\}
1861 ,1861 ,
1862 ".tmp_source.zig:2:14: error: array access of non-array type 'type'");1862 ".tmp_source.zig:2:14: error: array access of non-array type 'type'");
1863
1864 cases.add("cannot break out of defer expression",
1865 \\export fn foo() {
1866 \\ while (true) {
1867 \\ defer {
1868 \\ break;
1869 \\ }
1870 \\ }
1871 \\}
1872 ,
1873 ".tmp_source.zig:4:13: error: cannot break out of defer expression");
1874
1875 cases.add("cannot continue out of defer expression",
1876 \\export fn foo() {
1877 \\ while (true) {
1878 \\ defer {
1879 \\ continue;
1880 \\ }
1881 \\ }
1882 \\}
1883 ,
1884 ".tmp_source.zig:4:13: error: cannot continue out of defer expression");
1863}1885}