authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-24 13:57:00-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-24 13:57:00-05:00
log3b40aaa01fb15799cf27d662229597ac98e2ab77
treedb9403afed5078fe795b07ce3d522b3f2a9d4343
parent4b99f5978f35e54d4b4f1bfae022f48f193e40fd

add compile error for control flow using comptime var at runtime

closes #266

3 files changed, 29 insertions(+), 0 deletions(-)

src/all_types.hpp+4
......@@ -1589,6 +1589,10 @@ struct IrBasicBlock {
15891589 // analyze the basic block. If the same instruction wants us to emit
15901590 // the same basic block, then we re-generate it instead of saving it.
15911591 IrInstruction *ref_instruction;
1592 // When this is non-null, a branch to this basic block is only allowed
1593 // if the branch is comptime. The instruction points to the reason
1594 // the basic block must be comptime.
1595 IrInstruction *must_be_comptime_source_instr;
15921596};
15931597
15941598enum IrInstructionId {
src/ir.cpp+12
......@@ -8601,6 +8601,15 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr
86018601 return ir_inline_bb(ira, &br_instruction->base, old_dest_block);
86028602
86038603 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block, &br_instruction->base);
8604
8605 if (new_bb->must_be_comptime_source_instr) {
8606 ErrorMsg *msg = ir_add_error(ira, &br_instruction->base,
8607 buf_sprintf("control flow attempts to use compile-time variable at runtime"));
8608 add_error_note(ira->codegen, msg, new_bb->must_be_comptime_source_instr->source_node,
8609 buf_sprintf("compile-time variable assigned here"));
8610 return ir_unreach_error(ira);
8611 }
8612
86048613 ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);
86058614 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
86068615}
......@@ -9392,6 +9401,9 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
93929401 ConstExprValue *dest_val = const_ptr_pointee(&ptr->value);
93939402 if (dest_val->special != ConstValSpecialRuntime) {
93949403 *dest_val = casted_value->value;
9404 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
9405 ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base;
9406 }
93959407 return ir_analyze_void(ira, &store_ptr_instruction->base);
93969408 }
93979409 }
test/run_tests.cpp+13
......@@ -1678,6 +1678,19 @@ fn assert(ok: bool) {
16781678 ".tmp_source.zig:11:14: error: unable to evaluate constant expression",
16791679 ".tmp_source.zig:7:20: note: called from here");
16801680
1681 add_compile_fail_case("control flow uses comptime var at runtime", R"SOURCE(
1682fn foo() {
1683 comptime var i = 0;
1684 while (i < 5; i += 1) {
1685 bar();
1686 }
1687}
1688
1689fn bar() { }
1690 )SOURCE", 2,
1691 ".tmp_source.zig:4:5: error: control flow attempts to use compile-time variable at runtime",
1692 ".tmp_source.zig:4:21: note: compile-time variable assigned here");
1693
16811694}
16821695
16831696//////////////////////////////////////////////////////////////////////////////