Commit d8499f7abe

LemonBoy <thatlemon@gmail.com>
2019-12-17 00:31:32
Make sure the fields array is always non-null
Fixes #3497
1 parent f389e5e
Changed files (3)
src
test
stage1
behavior
src/analyze.cpp
@@ -5584,6 +5584,18 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
     ZigValue *result = create_const_vals(1);
     result->type = type_entry;
     result->special = ConstValSpecialStatic;
+    if (result->type->id == ZigTypeIdStruct) {
+        // The fields array cannot be left unpopulated
+        const ZigType *struct_type = result->type;
+        const size_t field_count = struct_type->data.structure.src_field_count;
+        result->data.x_struct.fields = alloc_const_vals_ptrs(field_count);
+        for (size_t i = 0; i < field_count; i += 1) {
+            TypeStructField *field = struct_type->data.structure.fields[i];
+            ZigType *field_type = resolve_struct_field_type(g, field);
+            assert(field_type != nullptr);
+            result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
+        }
+    }
     g->one_possible_values.put(type_entry, result);
     return result;
 }
src/ir.cpp
@@ -14018,7 +14018,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
         case OnePossibleValueInvalid:
             return ira->codegen->invalid_instruction;
         case OnePossibleValueYes:
-            return ir_const(ira, source_instruction, child_type);
+            return ir_const_move(ira, source_instruction,
+                     get_the_one_possible_value(ira->codegen, child_type));
         case OnePossibleValueNo:
             break;
     }
@@ -19226,7 +19227,8 @@ skip_resolve_peer_types:
     case OnePossibleValueInvalid:
         return ira->codegen->invalid_instruction;
     case OnePossibleValueYes:
-        return ir_const(ira, &phi_instruction->base, resolved_type);
+        return ir_const_move(ira, &phi_instruction->base,
+                 get_the_one_possible_value(ira->codegen, resolved_type));
     case OnePossibleValueNo:
         break;
     }
@@ -19862,7 +19864,8 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
         case OnePossibleValueInvalid:
             return ira->codegen->invalid_instruction;
         case OnePossibleValueYes: {
-            IrInstruction *elem = ir_const(ira, source_instr, field_type);
+            IrInstruction *elem = ir_const_move(ira, source_instr,
+                 get_the_one_possible_value(ira->codegen, field_type));
             return ir_get_ref(ira, source_instr, elem, false, false);
         }
         case OnePossibleValueNo:
@@ -21933,7 +21936,8 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
         case OnePossibleValueInvalid:
             return ira->codegen->invalid_instruction;
         case OnePossibleValueYes:
-            return ir_const(ira, &instruction->base, container_type);
+            return ir_const_move(ira, &instruction->base,
+                     get_the_one_possible_value(ira->codegen, container_type));
         case OnePossibleValueNo:
             break;
     }
test/stage1/behavior/pointers.zig
@@ -14,6 +14,22 @@ fn testDerefPtr() void {
     expect(x == 1235);
 }
 
+const Foo1 = struct {
+    x: void,
+};
+
+test "dereference pointer again" {
+    testDerefPtrOneVal();
+    comptime testDerefPtrOneVal();
+}
+
+fn testDerefPtrOneVal() void {
+    // Foo1 satisfies the OnePossibleValueYes criteria
+    const x = &Foo1{ .x = {} };
+    const y = x.*;
+    expect(@TypeOf(y.x) == void);
+}
+
 test "pointer arithmetic" {
     var ptr: [*]const u8 = "abcd";