From c75e8f3616d895d213faad5ad2678d3997f17d8a Mon Sep 17 00:00:00 2001 From: InKryption Date: Tue, 20 Sep 2022 21:40:16 +0200 Subject: [PATCH] Sema: check that reified enum field values fits tag type. --- src/Sema.zig | 13 ++++++++++-- .../reified_enum_field_value_overflow.zig | 20 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 test/cases/compile_errors/stage2/reified_enum_field_value_overflow.zig diff --git a/src/Sema.zig b/src/Sema.zig index 11cb409634..0aecf59d8e 100644 --- a/src/Sema.zig +++ b/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 diff --git a/test/cases/compile_errors/stage2/reified_enum_field_value_overflow.zig b/test/cases/compile_errors/stage2/reified_enum_field_value_overflow.zig new file mode 100644 index 0000000000..ad8596ebcc --- /dev/null +++ b/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'