Commit 3b40aaa01f

Andrew Kelley <superjoe30@gmail.com>
2017-02-24 19:57:00
add compile error for control flow using comptime var at runtime
closes #266
1 parent 4b99f59
Changed files (3)
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 {
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);
                 }
             }
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");
+
 }
 
 //////////////////////////////////////////////////////////////////////////////