| ... | ... | @@ -5982,12 +5982,34 @@ static bool ir_goto_pass2(IrBuilder *irb) { |
| 5982 | 5982 | irb->current_basic_block->instruction_list.resize(goto_item->instruction_index); |
| 5983 | 5983 | |
| 5984 | 5984 | Buf *label_name = source_node->data.goto_expr.name; |
| 5985 | | LabelTableEntry *label = find_label(irb->exec, goto_item->scope, label_name); |
| 5986 | | if (!label) { |
| 5987 | | add_node_error(irb->codegen, source_node, |
| 5988 | | buf_sprintf("no label in scope named '%s'", buf_ptr(label_name))); |
| 5989 | | return false; |
| 5985 | |
| 5986 | // Search up the scope until we find one of these things: |
| 5987 | // * A block scope with the label in it => OK |
| 5988 | // * A defer expression scope => error, error, cannot leave defer expression |
| 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 | 6013 | label->used = true; |
| 5992 | 6014 | |
| 5993 | 6015 | IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node, |