authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-03-10 00:42:56+00:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-03-10 12:18:06+02:00
log023753b4693317055e8094059f6195d041311b5d
tree81acce280be2eae52b1985a91e931985da01fc83
parentb445bbfea205702770e4e9de4e456c3e8750f8ed

Sema: correctly detect use of undefined within slices in @Type

Resolves: #14712

3 files changed, 39 insertions(+), 7 deletions(-)

src/Sema.zig+1-1
...@@ -18373,7 +18373,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -18373,7 +18373,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
18373 const union_val = val.cast(Value.Payload.Union).?.data;18373 const union_val = val.cast(Value.Payload.Union).?.data;
18374 const target = mod.getTarget();18374 const target = mod.getTarget();
18375 const tag_index = type_info_ty.unionTagFieldIndex(union_val.tag, mod).?;18375 const tag_index = type_info_ty.unionTagFieldIndex(union_val.tag, mod).?;
18376 if (union_val.val.anyUndef()) return sema.failWithUseOfUndef(block, src);18376 if (union_val.val.anyUndef(mod)) return sema.failWithUseOfUndef(block, src);
18377 switch (@intToEnum(std.builtin.TypeId, tag_index)) {18377 switch (@intToEnum(std.builtin.TypeId, tag_index)) {
18378 .Type => return Air.Inst.Ref.type_type,18378 .Type => return Air.Inst.Ref.type_type,
18379 .Void => return Air.Inst.Ref.void_type,18379 .Void => return Air.Inst.Ref.void_type,
src/value.zig+25-6
...@@ -3144,13 +3144,32 @@ pub const Value = extern union {...@@ -3144,13 +3144,32 @@ pub const Value = extern union {
3144 /// TODO: check for cases such as array that is not marked undef but all the element3144 /// TODO: check for cases such as array that is not marked undef but all the element
3145 /// values are marked undef, or struct that is not marked undef but all fields are marked3145 /// values are marked undef, or struct that is not marked undef but all fields are marked
3146 /// undef, etc.3146 /// undef, etc.
3147 pub fn anyUndef(self: Value) bool {3147 pub fn anyUndef(self: Value, mod: *Module) bool {
3148 if (self.castTag(.aggregate)) |aggregate| {3148 switch (self.tag()) {
3149 for (aggregate.data) |val| {3149 .slice => {
3150 if (val.anyUndef()) return true;3150 const payload = self.castTag(.slice).?;
3151 }3151 const len = payload.data.len.toUnsignedInt(mod.getTarget());
3152
3153 var elem_value_buf: ElemValueBuffer = undefined;
3154 var i: usize = 0;
3155 while (i < len) : (i += 1) {
3156 const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf);
3157 if (elem_val.anyUndef(mod)) return true;
3158 }
3159 },
3160
3161 .aggregate => {
3162 const payload = self.castTag(.aggregate).?;
3163 for (payload.data) |val| {
3164 if (val.anyUndef(mod)) return true;
3165 }
3166 },
3167
3168 .undef => return true,
3169 else => {},
3152 }3170 }
3153 return self.isUndef();3171
3172 return false;
3154 }3173 }
31553174
3156 /// Asserts the value is not undefined and not unreachable.3175 /// Asserts the value is not undefined and not unreachable.
test/cases/compile_errors/reify_type_with_undefined.zig+13
...@@ -11,6 +11,18 @@ comptime {...@@ -11,6 +11,18 @@ comptime {
11 },11 },
12 });12 });
13}13}
14comptime {
15 const std = @import("std");
16 const fields: [1]std.builtin.Type.StructField = undefined;
17 _ = @Type(.{
18 .Struct = .{
19 .layout = .Auto,
20 .fields = &fields,
21 .decls = &.{},
22 .is_tuple = false,
23 },
24 });
25}
1426
15// error27// error
16// backend=stage228// backend=stage2
...@@ -18,3 +30,4 @@ comptime {...@@ -18,3 +30,4 @@ comptime {
18//30//
19// :2:9: error: use of undefined value here causes undefined behavior31// :2:9: error: use of undefined value here causes undefined behavior
20// :5:9: error: use of undefined value here causes undefined behavior32// :5:9: error: use of undefined value here causes undefined behavior
33// :17:9: error: use of undefined value here causes undefined behavior