Commit 023753b469

mlugg <mlugg@mlugg.co.uk>
2023-03-10 01:42:56
Sema: correctly detect use of undefined within slices in @Type
Resolves: #14712
1 parent b445bbf
Changed files (3)
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,
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.
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