parent
5ceaae288c
commit
44ca5e19dc
|
@ -830,6 +830,11 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
|
|||
context->parent = parent;
|
||||
context->variable_table.init(8);
|
||||
|
||||
if (parent) {
|
||||
context->break_allowed = parent->break_allowed || parent->next_child_break_allowed;
|
||||
parent->next_child_break_allowed = false;
|
||||
}
|
||||
|
||||
if (node && node->type == NodeTypeFnDef) {
|
||||
AstNode *fn_proto_node = node->data.fn_def.fn_proto;
|
||||
context->fn_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
|
||||
|
@ -1359,13 +1364,20 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
|
|||
TypeTableEntry *expected_type, AstNode *node)
|
||||
{
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.while_expr.condition);
|
||||
|
||||
context->next_child_break_allowed = true;
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_void, node->data.while_expr.body);
|
||||
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
TypeTableEntry *expected_type, AstNode *node)
|
||||
{
|
||||
if (!context->break_allowed) {
|
||||
add_node_error(g, node,
|
||||
buf_sprintf("'break' expression not in loop"));
|
||||
}
|
||||
return g->builtin_types.entry_unreachable;
|
||||
}
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ struct CodeGen {
|
|||
FnTableEntry *cur_fn;
|
||||
LLVMBasicBlockRef cur_basic_block;
|
||||
BlockContext *cur_block_context;
|
||||
LLVMBasicBlockRef cur_break_block;
|
||||
ZigList<LLVMBasicBlockRef> break_block_stack;
|
||||
bool c_stdint_used;
|
||||
AstNode *root_export_decl;
|
||||
int version_major;
|
||||
|
@ -226,6 +226,8 @@ struct BlockContext {
|
|||
HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
|
||||
ZigList<CastNode *> cast_expr_alloca_list;
|
||||
ZigList<StructValExprNode *> struct_val_expr_alloca_list;
|
||||
bool break_allowed;
|
||||
bool next_child_break_allowed;
|
||||
LLVMZigDIScope *di_scope;
|
||||
};
|
||||
|
||||
|
|
|
@ -1024,10 +1024,12 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
|
|||
LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, body_block);
|
||||
g->cur_break_block = end_block;
|
||||
g->break_block_stack.append(end_block);
|
||||
gen_expr(g, node->data.while_expr.body);
|
||||
g->cur_break_block = nullptr;
|
||||
LLVMBuildBr(g->builder, cond_block);
|
||||
g->break_block_stack.pop();
|
||||
if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
|
||||
LLVMBuildBr(g->builder, cond_block);
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, end_block);
|
||||
return nullptr;
|
||||
|
@ -1035,10 +1037,10 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
|
|||
|
||||
static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
|
||||
assert(node->type == NodeTypeBreak);
|
||||
assert(g->cur_break_block);
|
||||
LLVMBasicBlockRef dest_block = g->break_block_stack.last();
|
||||
|
||||
add_debug_source_node(g, node);
|
||||
return LLVMBuildBr(g->builder, g->cur_break_block);
|
||||
return LLVMBuildBr(g->builder, dest_block);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
||||
|
|
|
@ -664,11 +664,14 @@ use "std.zig";
|
|||
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
||||
var i : i32 = 0;
|
||||
while true {
|
||||
if i >= 4 {
|
||||
break;
|
||||
while true {
|
||||
if i >= 4 {
|
||||
break;
|
||||
}
|
||||
print_str("loop\n");
|
||||
i += 1;
|
||||
}
|
||||
print_str("loop\n");
|
||||
i += 1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -949,6 +952,12 @@ fn f() {
|
|||
};
|
||||
}
|
||||
)SOURCE", 1, ".tmp_source.zig:11:9: error: no member named 'foo' in 'A'");
|
||||
|
||||
add_compile_fail_case("invalid break expression", R"SOURCE(
|
||||
fn f() {
|
||||
break;
|
||||
}
|
||||
)SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression not in loop");
|
||||
}
|
||||
|
||||
static void print_compiler_invocation(TestCase *test_case) {
|
||||
|
|
Loading…
Reference in New Issue