fix compiler crash when referencing a variable...

...in an if after an if in the 2nd switch prong

closes #355
This commit is contained in:
Andrew Kelley 2017-05-02 12:59:09 -04:00
parent 9f92042da9
commit 7c236f6dd8
4 changed files with 47 additions and 2 deletions

View File

@ -1516,6 +1516,7 @@ struct VariableTableEntry {
size_t mem_slot_index;
size_t ref_count;
VarLinkage linkage;
IrInstruction *decl_instruction;
};
struct ErrorTableEntry {

View File

@ -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) {

View File

@ -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");

View File

@ -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;
}