authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-21 10:59:09-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-21 10:59:09-04:00
log1c8fee41c247ea60aebd1d8b0fdba4002701b1cf
treebe4ba483d36a2988573239a926ac77bee5bf1b03
parent9f3cca861557dab5c56d4ee5a35acd93180ef862

add compile error for goto leaving defer expression

closes #284

2 files changed, 37 insertions(+), 5 deletions(-)

src/ir.cpp+27-5
...@@ -5982,12 +5982,34 @@ static bool ir_goto_pass2(IrBuilder *irb) {...@@ -5982,12 +5982,34 @@ static bool ir_goto_pass2(IrBuilder *irb) {
5982 irb->current_basic_block->instruction_list.resize(goto_item->instruction_index);5982 irb->current_basic_block->instruction_list.resize(goto_item->instruction_index);
59835983
5984 Buf *label_name = source_node->data.goto_expr.name;5984 Buf *label_name = source_node->data.goto_expr.name;
5985 LabelTableEntry *label = find_label(irb->exec, goto_item->scope, label_name);5985
5986 if (!label) {5986 // Search up the scope until we find one of these things:
5987 add_node_error(irb->codegen, source_node,5987 // * A block scope with the label in it => OK
5988 buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));5988 // * A defer expression scope => error, error, cannot leave defer expression
5989 return false;5989 // * Top level scope => error, didn't find label
5990
5991 LabelTableEntry *label;
5992 Scope *search_scope = goto_item->scope;
5993 for (;;) {
5994 if (search_scope == nullptr) {
5995 add_node_error(irb->codegen, source_node,
5996 buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));
5997 return false;
5998 } else if (search_scope->id == ScopeIdBlock) {
5999 ScopeBlock *block_scope = (ScopeBlock *)search_scope;
6000 auto entry = block_scope->label_table.maybe_get(label_name);
6001 if (entry) {
6002 label = entry->value;
6003 break;
6004 }
6005 } else if (search_scope->id == ScopeIdDeferExpr) {
6006 add_node_error(irb->codegen, source_node,
6007 buf_sprintf("cannot goto out of defer expression"));
6008 return false;
6009 }
6010 search_scope = search_scope->parent;
5990 }6011 }
6012
5991 label->used = true;6013 label->used = true;
59926014
5993 IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node,6015 IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node,
test/compile_errors.zig+10
...@@ -1882,4 +1882,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -1882,4 +1882,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
1882 \\}1882 \\}
1883 ,1883 ,
1884 ".tmp_source.zig:4:13: error: cannot continue out of defer expression");1884 ".tmp_source.zig:4:13: error: cannot continue out of defer expression");
1885
1886 cases.add("cannot goto out of defer expression",
1887 \\export fn foo() {
1888 \\ defer {
1889 \\ goto label;
1890 \\ };
1891 \\label:
1892 \\}
1893 ,
1894 ".tmp_source.zig:3:9: error: cannot goto out of defer expression");
1885}1895}