zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 3b40aaa01fb15799cf27d662229597ac98e2ab77 (tree)
parent 4b99f5978f35e54d4b4f1bfae022f48f193e40fd
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Fri, 24 Feb 2017 13:57:00 -0500

add compile error for control flow using comptime var at runtime

closes #266

Diffstat:
Msrc/all_types.hpp | 4++++
Msrc/ir.cpp | 12++++++++++++
Mtest/run_tests.cpp | 13+++++++++++++
3 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/src/all_types.hpp b/src/all_types.hpp @@ -1589,6 +1589,10 @@ struct IrBasicBlock { // analyze the basic block. If the same instruction wants us to emit // the same basic block, then we re-generate it instead of saving it. IrInstruction *ref_instruction; + // When this is non-null, a branch to this basic block is only allowed + // if the branch is comptime. The instruction points to the reason + // the basic block must be comptime. + IrInstruction *must_be_comptime_source_instr; }; enum IrInstructionId { diff --git a/src/ir.cpp b/src/ir.cpp @@ -8601,6 +8601,15 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr return ir_inline_bb(ira, &br_instruction->base, old_dest_block); IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block, &br_instruction->base); + + if (new_bb->must_be_comptime_source_instr) { + ErrorMsg *msg = ir_add_error(ira, &br_instruction->base, + buf_sprintf("control flow attempts to use compile-time variable at runtime")); + add_error_note(ira->codegen, msg, new_bb->must_be_comptime_source_instr->source_node, + buf_sprintf("compile-time variable assigned here")); + return ir_unreach_error(ira); + } + ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb); return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); } @@ -9392,6 +9401,9 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru ConstExprValue *dest_val = const_ptr_pointee(&ptr->value); if (dest_val->special != ConstValSpecialRuntime) { *dest_val = casted_value->value; + if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) { + ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base; + } return ir_analyze_void(ira, &store_ptr_instruction->base); } } diff --git a/test/run_tests.cpp b/test/run_tests.cpp @@ -1678,6 +1678,19 @@ fn assert(ok: bool) { ".tmp_source.zig:11:14: error: unable to evaluate constant expression", ".tmp_source.zig:7:20: note: called from here"); + add_compile_fail_case("control flow uses comptime var at runtime", R"SOURCE( +fn foo() { + comptime var i = 0; + while (i < 5; i += 1) { + bar(); + } +} + +fn bar() { } + )SOURCE", 2, + ".tmp_source.zig:4:5: error: control flow attempts to use compile-time variable at runtime", + ".tmp_source.zig:4:21: note: compile-time variable assigned here"); + } //////////////////////////////////////////////////////////////////////////////