authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-15 20:03:58-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-15 20:03:58-04:00
log1149e8bb088f48e29f3abc06196b1134f5e1c42f
treeb3637be2086b25649d71e2d24d334aa634e87e03
parent7d0b6956c0935807f0e5862c45da857e8e065c6b
parent480e7eec65c02952b71ecc2f4ff2adccb6092a5f
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11185 from topolarity/bugfix-11159

stage2: resolve panic on array-like tuple initialization

8 files changed, 72 insertions(+), 13 deletions(-)

src/AstGen.zig+7-5
......@@ -4092,15 +4092,17 @@ fn structDeclInner(
40924092 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
40934093 wip_members.appendToField(doc_comment_index);
40944094
4095 known_non_opv = known_non_opv or
4096 nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr);
4097 known_comptime_only = known_comptime_only or
4098 nodeImpliesComptimeOnly(tree, member.ast.type_expr);
4099
41004095 const have_align = member.ast.align_expr != 0;
41014096 const have_value = member.ast.value_expr != 0;
41024097 const is_comptime = member.comptime_token != null;
41034098 const unused = false;
4099
4100 if (!is_comptime) {
4101 known_non_opv = known_non_opv or
4102 nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr);
4103 known_comptime_only = known_comptime_only or
4104 nodeImpliesComptimeOnly(tree, member.ast.type_expr);
4105 }
41044106 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, unused });
41054107
41064108 if (have_align) {
src/Sema.zig+8-5
......@@ -3203,11 +3203,6 @@ fn zirValidateArrayInit(
32033203
32043204 // Determine whether the value stored to this pointer is comptime-known.
32053205
3206 if (opt_opv) |opv| {
3207 element_vals[i] = opv;
3208 continue;
3209 }
3210
32113206 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
32123207 const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?;
32133208 // Find the block index of the elem_ptr so that we can look at the next
......@@ -3223,6 +3218,12 @@ fn zirValidateArrayInit(
32233218 break :inst block.instructions.items[block_index + 1];
32243219 };
32253220
3221 // Array has one possible value, so value is always comptime-known
3222 if (opt_opv) |opv| {
3223 element_vals[i] = opv;
3224 continue;
3225 }
3226
32263227 // If the next instructon is a store with a comptime operand, this element
32273228 // is comptime.
32283229 switch (air_tags[next_air_inst]) {
......@@ -20860,6 +20861,7 @@ pub fn typeHasOnePossibleValue(
2086020861 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
2086120862 const s = resolved_ty.castTag(.@"struct").?.data;
2086220863 for (s.fields.values()) |value| {
20864 if (value.is_comptime) continue;
2086320865 if ((try sema.typeHasOnePossibleValue(block, src, value.ty)) == null) {
2086420866 return null;
2086520867 }
......@@ -21532,6 +21534,7 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C
2153221534
2153321535 struct_obj.requires_comptime = .wip;
2153421536 for (struct_obj.fields.values()) |field| {
21537 if (field.is_comptime) continue;
2153521538 if (try sema.typeRequiresComptime(block, src, field.ty)) {
2153621539 struct_obj.requires_comptime = .yes;
2153721540 return true;
src/codegen/llvm.zig+4-3
......@@ -5422,21 +5422,22 @@ pub const FuncGen = struct {
54225422 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
54235423 const dest_ptr = try self.resolveInst(bin_op.lhs);
54245424 const ptr_ty = self.air.typeOf(bin_op.lhs);
5425 const operand_ty = ptr_ty.childType();
5426 if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return null;
54255427
54265428 // TODO Sema should emit a different instruction when the store should
54275429 // possibly do the safety 0xaa bytes for undefined.
54285430 const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
54295431 if (val_is_undef) {
5430 const elem_ty = ptr_ty.childType();
54315432 const target = self.dg.module.getTarget();
5432 const elem_size = elem_ty.abiSize(target);
5433 const operand_size = operand_ty.abiSize(target);
54335434 const u8_llvm_ty = self.context.intType(8);
54345435 const ptr_u8_llvm_ty = u8_llvm_ty.pointerType(0);
54355436 const dest_ptr_u8 = self.builder.buildBitCast(dest_ptr, ptr_u8_llvm_ty, "");
54365437 const fill_char = u8_llvm_ty.constInt(0xaa, .False);
54375438 const dest_ptr_align = ptr_ty.ptrAlignment(target);
54385439 const usize_llvm_ty = try self.dg.llvmType(Type.usize);
5439 const len = usize_llvm_ty.constInt(elem_size, .False);
5440 const len = usize_llvm_ty.constInt(operand_size, .False);
54405441 _ = self.builder.buildMemSet(dest_ptr_u8, fill_char, len, dest_ptr_align, ptr_ty.isVolatilePtr());
54415442 if (self.dg.module.comp.bin_file.options.valgrind) {
54425443 // TODO generate valgrind client request to mark byte range as undefined
src/type.zig+1
......@@ -2098,6 +2098,7 @@ pub const Type = extern union {
20982098 }
20992099 assert(struct_obj.haveFieldTypes());
21002100 for (struct_obj.fields.values()) |value| {
2101 if (value.is_comptime) continue;
21012102 if (value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only))
21022103 return true;
21032104 } else {
test/behavior.zig+3
......@@ -65,8 +65,11 @@ test {
6565 _ = @import("behavior/bugs/10970.zig");
6666 _ = @import("behavior/bugs/11046.zig");
6767 _ = @import("behavior/bugs/11139.zig");
68 _ = @import("behavior/bugs/11159.zig");
69 _ = @import("behavior/bugs/11162.zig");
6870 _ = @import("behavior/bugs/11165.zig");
6971 _ = @import("behavior/bugs/11181.zig");
72 _ = @import("behavior/bugs/11182.zig");
7073 _ = @import("behavior/call.zig");
7174 _ = @import("behavior/cast.zig");
7275 _ = @import("behavior/comptime_memory.zig");
test/behavior/bugs/11159.zig created+23
......@@ -0,0 +1,23 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4test {
5 const T = @TypeOf(.{ @as(i32, 0), @as(u32, 0) });
6 var a: T = .{ 0, 0 };
7 _ = a;
8}
9
10test {
11 if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
14
15 const S = struct {
16 comptime x: i32 = 0,
17 comptime y: u32 = 0,
18 };
19 var a: S = .{};
20 _ = a;
21 var b = S{};
22 _ = b;
23}
test/behavior/bugs/11162.zig created+16
......@@ -0,0 +1,16 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5test {
6 if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
8
9 var x: u32 = 15;
10 const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
11 var a: T = .{ -1234, 5678, x + 1 };
12
13 try expect(a[0] == -1234);
14 try expect(a[1] == 5678);
15 try expect(a[2] == 16);
16}
test/behavior/bugs/11182.zig created+10
......@@ -0,0 +1,10 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4test {
5 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
6
7 const T = @TypeOf(.{ @as(i32, 0), @as(u32, 0) });
8 var a = T{ 0, 0 };
9 _ = a;
10}