Commit c75e8f3616

InKryption <inkryption07@gmail.com>
2022-09-20 21:40:16
Sema: check that reified enum field values fits tag type.
1 parent c673e6a
Changed files (2)
src
test
cases
src/Sema.zig
@@ -17092,7 +17092,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
                 try sema.reifyStruct(block, inst, src, layout, backing_int_val, fields_val, name_strategy);
         },
         .Enum => {
-            const struct_val = union_val.val.castTag(.aggregate).?.data;
+            const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data;
             // TODO use reflection instead of magic numbers here
             // layout: ContainerLayout,
             const layout_val = struct_val[0];
@@ -17176,7 +17176,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
             var i: usize = 0;
             while (i < fields_len) : (i += 1) {
                 const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i);
-                const field_struct_val = elem_val.castTag(.aggregate).?.data;
+                const field_struct_val: []const Value = elem_val.castTag(.aggregate).?.data;
                 // TODO use reflection instead of magic numbers here
                 // name: []const u8
                 const name_val = field_struct_val[0];
@@ -17189,6 +17189,15 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
                     sema.mod,
                 );
 
+                if (!try sema.intFitsInType(block, src, value_val, enum_obj.tag_ty, null)) {
+                    // TODO: better source location
+                    return sema.fail(block, src, "field '{s}' with enumeration value '{}' is too large for backing int type '{}'", .{
+                        field_name,
+                        value_val.fmtValue(Type.@"comptime_int", mod),
+                        enum_obj.tag_ty.fmt(mod),
+                    });
+                }
+
                 const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name);
                 if (gop.found_existing) {
                     // TODO: better source location
test/cases/compile_errors/stage2/reified_enum_field_value_overflow.zig
@@ -0,0 +1,20 @@
+comptime {
+    const E = @Type(.{ .Enum = .{
+        .layout = .Auto,
+        .tag_type = u1,
+        .fields = &.{
+            .{ .name = "f0", .value = 0 },
+            .{ .name = "f1", .value = 1 },
+            .{ .name = "f2", .value = 2 },
+        },
+        .decls = &.{},
+        .is_exhaustive = true,
+    } });
+    _ = E;
+}
+
+// error
+// target=native
+// backend=stage2
+//
+// :2:15: error: field 'f2' with enumeration value '2' is too large for backing int type 'u1'