From 023753b4693317055e8094059f6195d041311b5d Mon Sep 17 00:00:00 2001 From: mlugg Date: Fri, 10 Mar 2023 00:42:56 +0000 Subject: [PATCH] Sema: correctly detect use of undefined within slices in @Type Resolves: #14712 --- src/Sema.zig | 2 +- src/value.zig | 31 +++++++++++++++---- .../reify_type_with_undefined.zig | 13 ++++++++ 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 840e8a4c6c..41685890f7 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18373,7 +18373,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in const union_val = val.cast(Value.Payload.Union).?.data; const target = mod.getTarget(); const tag_index = type_info_ty.unionTagFieldIndex(union_val.tag, mod).?; - if (union_val.val.anyUndef()) return sema.failWithUseOfUndef(block, src); + if (union_val.val.anyUndef(mod)) return sema.failWithUseOfUndef(block, src); switch (@intToEnum(std.builtin.TypeId, tag_index)) { .Type => return Air.Inst.Ref.type_type, .Void => return Air.Inst.Ref.void_type, diff --git a/src/value.zig b/src/value.zig index 00bf59ca38..b6d27d620d 100644 --- a/src/value.zig +++ b/src/value.zig @@ -3144,13 +3144,32 @@ pub const Value = extern union { /// TODO: check for cases such as array that is not marked undef but all the element /// values are marked undef, or struct that is not marked undef but all fields are marked /// undef, etc. - pub fn anyUndef(self: Value) bool { - if (self.castTag(.aggregate)) |aggregate| { - for (aggregate.data) |val| { - if (val.anyUndef()) return true; - } + pub fn anyUndef(self: Value, mod: *Module) bool { + switch (self.tag()) { + .slice => { + const payload = self.castTag(.slice).?; + const len = payload.data.len.toUnsignedInt(mod.getTarget()); + + var elem_value_buf: ElemValueBuffer = undefined; + var i: usize = 0; + while (i < len) : (i += 1) { + const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf); + if (elem_val.anyUndef(mod)) return true; + } + }, + + .aggregate => { + const payload = self.castTag(.aggregate).?; + for (payload.data) |val| { + if (val.anyUndef(mod)) return true; + } + }, + + .undef => return true, + else => {}, } - return self.isUndef(); + + return false; } /// Asserts the value is not undefined and not unreachable. diff --git a/test/cases/compile_errors/reify_type_with_undefined.zig b/test/cases/compile_errors/reify_type_with_undefined.zig index e5753fa420..59c0314773 100644 --- a/test/cases/compile_errors/reify_type_with_undefined.zig +++ b/test/cases/compile_errors/reify_type_with_undefined.zig @@ -11,6 +11,18 @@ comptime { }, }); } +comptime { + const std = @import("std"); + const fields: [1]std.builtin.Type.StructField = undefined; + _ = @Type(.{ + .Struct = .{ + .layout = .Auto, + .fields = &fields, + .decls = &.{}, + .is_tuple = false, + }, + }); +} // error // backend=stage2 @@ -18,3 +30,4 @@ comptime { // // :2:9: error: use of undefined value here causes undefined behavior // :5:9: error: use of undefined value here causes undefined behavior +// :17:9: error: use of undefined value here causes undefined behavior