Commit 7c236f6dd8

Andrew Kelley <superjoe30@gmail.com>
2017-05-02 18:59:09
fix compiler crash when referencing a variable...
...in an if after an if in the 2nd switch prong closes #355
1 parent 9f92042
src/all_types.hpp
@@ -1516,6 +1516,7 @@ struct VariableTableEntry {
     size_t mem_slot_index;
     size_t ref_count;
     VarLinkage linkage;
+    IrInstruction *decl_instruction;
 };
 
 struct ErrorTableEntry {
src/ir.cpp
@@ -2311,7 +2311,10 @@ static IrInstruction *ir_instruction_elemptr_get_dep(IrInstructionElemPtr *instr
 }
 
 static IrInstruction *ir_instruction_varptr_get_dep(IrInstructionVarPtr *instruction, size_t index) {
-    return nullptr;
+    switch (index) {
+        case 0: return instruction->var->decl_instruction; // can be null
+        default: return nullptr;
+    }
 }
 
 static IrInstruction *ir_instruction_call_get_dep(IrInstructionCall *instruction, size_t index) {
@@ -4646,7 +4649,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
     if (init_value == irb->codegen->invalid_instruction)
         return init_value;
 
-    return ir_build_var_decl(irb, scope, node, var, type_instruction, init_value);
+
+    IrInstruction *result = ir_build_var_decl(irb, scope, node, var, type_instruction, init_value);
+    var->decl_instruction = result;
+    return result;
 }
 
 static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig
@@ -0,0 +1,37 @@
+const assert = @import("std").debug.assert;
+const mem = @import("std").mem;
+
+var ok: bool = false;
+test "reference a variable in an if after an if in the 2nd switch prong" {
+    foo(true, Num.Two, false, "aoeu");
+    assert(!ok);
+    foo(false, Num.One, false, "aoeu");
+    assert(!ok);
+    foo(true, Num.One, false, "aoeu");
+    assert(ok);
+}
+
+const Num = enum {
+    One,
+    Two,
+};
+
+fn foo(c: bool, k: Num, c2: bool, b: []const u8) {
+    switch (k) {
+        Num.Two => {},
+        Num.One => {
+            if (c) {
+                const output_path = b;
+
+                if (c2) { }
+
+                a(output_path);
+            }
+        },
+    }
+}
+
+fn a(x: []const u8) {
+    assert(mem.eql(u8, x, "aoeu"));
+    ok = true;
+}
test/behavior.zig
@@ -24,6 +24,7 @@ comptime {
     _ = @import("cases/namespace_depends_on_compile_var/index.zig");
     _ = @import("cases/null.zig");
     _ = @import("cases/pub_enum/index.zig");
+    _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
     _ = @import("cases/sizeof_and_typeof.zig");
     _ = @import("cases/struct.zig");
     _ = @import("cases/struct_contains_slice_of_itself.zig");