Commit 70a4794c57

Andrew Kelley <andrew@ziglang.org>
2020-02-10 16:57:40
fix compiler assertion when duplicating fields...
...in nested anonymous struct literals closes #4391
1 parent 014f66e
Changed files (2)
src/ir.cpp
@@ -771,23 +771,9 @@ static void ira_deref(IrAnalyze *ira) {
     destroy(ira, "IrAnalyze");
 }
 
-static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
+static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_val) {
     assert(get_src_ptr_type(const_val->type) != nullptr);
     assert(const_val->special == ConstValSpecialStatic);
-    ZigValue *result;
-
-    InferredStructField *isf = const_val->type->data.pointer.inferred_struct_field;
-    if (isf != nullptr) {
-        TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
-        assert(field != nullptr);
-        if (field->is_comptime) {
-            assert(field->init_val != nullptr);
-            return field->init_val;
-        }
-        assert(const_val->data.x_ptr.special == ConstPtrSpecialRef);
-        ZigValue *struct_val = const_val->data.x_ptr.data.ref.pointee;
-        return struct_val->data.x_struct.fields[field->src_index];
-    }
 
     switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
         case OnePossibleValueInvalid:
@@ -798,6 +784,7 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
             break;
     }
 
+    ZigValue *result;
     switch (const_val->data.x_ptr.special) {
         case ConstPtrSpecialInvalid:
             zig_unreachable();
@@ -843,6 +830,26 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
     return result;
 }
 
+static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
+    assert(get_src_ptr_type(const_val->type) != nullptr);
+    assert(const_val->special == ConstValSpecialStatic);
+
+    InferredStructField *isf = const_val->type->data.pointer.inferred_struct_field;
+    if (isf != nullptr) {
+        TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
+        assert(field != nullptr);
+        if (field->is_comptime) {
+            assert(field->init_val != nullptr);
+            return field->init_val;
+        }
+        ZigValue *struct_val = const_ptr_pointee_unchecked_no_isf(g, const_val);
+        assert(struct_val->type->id == ZigTypeIdStruct);
+        return struct_val->data.x_struct.fields[field->src_index];
+    }
+
+    return const_ptr_pointee_unchecked_no_isf(g, const_val);
+}
+
 static bool is_tuple(ZigType *type) {
     return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialInferredTuple;
 }
test/compile_errors.zig
@@ -3,6 +3,22 @@ const builtin = @import("builtin");
 const Target = @import("std").Target;
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.addTest("duplicate field in anonymous struct literal",
+        \\export fn entry() void {
+        \\    const anon = .{
+        \\        .inner = .{
+        \\            .a = .{
+        \\                .something = "text",
+        \\            },
+        \\            .a = .{},
+        \\        },
+        \\    };
+        \\}
+    , &[_][]const u8{
+        "tmp.zig:7:13: error: duplicate field",
+        "tmp.zig:4:13: note: other field here",
+    });
+
     cases.addTest("type mismatch in C prototype with varargs",
         \\const fn_ty = ?fn ([*c]u8, ...) callconv(.C) void;
         \\extern fn fn_decl(fmt: [*:0]u8, ...) void;