| author | |
| committer | |
| log | 3b40aaa01fb15799cf27d662229597ac98e2ab77 |
| tree | db9403afed5078fe795b07ce3d522b3f2a9d4343 |
| parent | 4b99f5978f35e54d4b4f1bfae022f48f193e40fd |
closes #2663 files changed, 29 insertions(+), 0 deletions(-)
src/all_types.hpp+4| ... | ... | @@ -1589,6 +1589,10 @@ struct IrBasicBlock { |
| 1589 | 1589 | // analyze the basic block. If the same instruction wants us to emit |
| 1590 | 1590 | // the same basic block, then we re-generate it instead of saving it. |
| 1591 | 1591 | 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; | |
| 1592 | 1596 | }; |
| 1593 | 1597 | |
| 1594 | 1598 | enum IrInstructionId { |
src/ir.cpp+12| ... | ... | @@ -8601,6 +8601,15 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr |
| 8601 | 8601 | return ir_inline_bb(ira, &br_instruction->base, old_dest_block); |
| 8602 | 8602 | |
| 8603 | 8603 | 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 | ||
| 8604 | 8613 | ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb); |
| 8605 | 8614 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); |
| 8606 | 8615 | } |
| ... | ... | @@ -9392,6 +9401,9 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 9392 | 9401 | ConstExprValue *dest_val = const_ptr_pointee(&ptr->value); |
| 9393 | 9402 | if (dest_val->special != ConstValSpecialRuntime) { |
| 9394 | 9403 | *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 | } | |
| 9395 | 9407 | return ir_analyze_void(ira, &store_ptr_instruction->base); |
| 9396 | 9408 | } |
| 9397 | 9409 | } |
test/run_tests.cpp+13| ... | ... | @@ -1678,6 +1678,19 @@ fn assert(ok: bool) { |
| 1678 | 1678 | ".tmp_source.zig:11:14: error: unable to evaluate constant expression", |
| 1679 | 1679 | ".tmp_source.zig:7:20: note: called from here"); |
| 1680 | 1680 | |
| 1681 | add_compile_fail_case("control flow uses comptime var at runtime", R"SOURCE( | |
| 1682 | fn foo() { | |
| 1683 | comptime var i = 0; | |
| 1684 | while (i < 5; i += 1) { | |
| 1685 | bar(); | |
| 1686 | } | |
| 1687 | } | |
| 1688 | ||
| 1689 | fn 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 | ||
| 1681 | 1694 | } |
| 1682 | 1695 | |
| 1683 | 1696 | ////////////////////////////////////////////////////////////////////////////// |