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(...@@ -4092,15 +4092,17 @@ fn structDeclInner(
4092 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());4092 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
4093 wip_members.appendToField(doc_comment_index);4093 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
4100 const have_align = member.ast.align_expr != 0;4095 const have_align = member.ast.align_expr != 0;
4101 const have_value = member.ast.value_expr != 0;4096 const have_value = member.ast.value_expr != 0;
4102 const is_comptime = member.comptime_token != null;4097 const is_comptime = member.comptime_token != null;
4103 const unused = false;4098 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 }
4104 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, unused });4106 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, unused });
41054107
4106 if (have_align) {4108 if (have_align) {
src/Sema.zig+8-5
...@@ -3203,11 +3203,6 @@ fn zirValidateArrayInit(...@@ -3203,11 +3203,6 @@ fn zirValidateArrayInit(
32033203
3204 // Determine whether the value stored to this pointer is comptime-known.3204 // 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
3211 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;3206 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
3212 const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?;3207 const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?;
3213 // Find the block index of the elem_ptr so that we can look at the next3208 // Find the block index of the elem_ptr so that we can look at the next
...@@ -3223,6 +3218,12 @@ fn zirValidateArrayInit(...@@ -3223,6 +3218,12 @@ fn zirValidateArrayInit(
3223 break :inst block.instructions.items[block_index + 1];3218 break :inst block.instructions.items[block_index + 1];
3224 };3219 };
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
3226 // If the next instructon is a store with a comptime operand, this element3227 // If the next instructon is a store with a comptime operand, this element
3227 // is comptime.3228 // is comptime.
3228 switch (air_tags[next_air_inst]) {3229 switch (air_tags[next_air_inst]) {
...@@ -20860,6 +20861,7 @@ pub fn typeHasOnePossibleValue(...@@ -20860,6 +20861,7 @@ pub fn typeHasOnePossibleValue(
20860 const resolved_ty = try sema.resolveTypeFields(block, src, ty);20861 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
20861 const s = resolved_ty.castTag(.@"struct").?.data;20862 const s = resolved_ty.castTag(.@"struct").?.data;
20862 for (s.fields.values()) |value| {20863 for (s.fields.values()) |value| {
20864 if (value.is_comptime) continue;
20863 if ((try sema.typeHasOnePossibleValue(block, src, value.ty)) == null) {20865 if ((try sema.typeHasOnePossibleValue(block, src, value.ty)) == null) {
20864 return null;20866 return null;
20865 }20867 }
...@@ -21532,6 +21534,7 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C...@@ -21532,6 +21534,7 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C
2153221534
21533 struct_obj.requires_comptime = .wip;21535 struct_obj.requires_comptime = .wip;
21534 for (struct_obj.fields.values()) |field| {21536 for (struct_obj.fields.values()) |field| {
21537 if (field.is_comptime) continue;
21535 if (try sema.typeRequiresComptime(block, src, field.ty)) {21538 if (try sema.typeRequiresComptime(block, src, field.ty)) {
21536 struct_obj.requires_comptime = .yes;21539 struct_obj.requires_comptime = .yes;
21537 return true;21540 return true;
src/codegen/llvm.zig+4-3
...@@ -5422,21 +5422,22 @@ pub const FuncGen = struct {...@@ -5422,21 +5422,22 @@ pub const FuncGen = struct {
5422 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5422 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5423 const dest_ptr = try self.resolveInst(bin_op.lhs);5423 const dest_ptr = try self.resolveInst(bin_op.lhs);
5424 const ptr_ty = self.air.typeOf(bin_op.lhs);5424 const ptr_ty = self.air.typeOf(bin_op.lhs);
5425 const operand_ty = ptr_ty.childType();
5426 if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return null;
54255427
5426 // TODO Sema should emit a different instruction when the store should5428 // TODO Sema should emit a different instruction when the store should
5427 // possibly do the safety 0xaa bytes for undefined.5429 // possibly do the safety 0xaa bytes for undefined.
5428 const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;5430 const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
5429 if (val_is_undef) {5431 if (val_is_undef) {
5430 const elem_ty = ptr_ty.childType();
5431 const target = self.dg.module.getTarget();5432 const target = self.dg.module.getTarget();
5432 const elem_size = elem_ty.abiSize(target);5433 const operand_size = operand_ty.abiSize(target);
5433 const u8_llvm_ty = self.context.intType(8);5434 const u8_llvm_ty = self.context.intType(8);
5434 const ptr_u8_llvm_ty = u8_llvm_ty.pointerType(0);5435 const ptr_u8_llvm_ty = u8_llvm_ty.pointerType(0);
5435 const dest_ptr_u8 = self.builder.buildBitCast(dest_ptr, ptr_u8_llvm_ty, "");5436 const dest_ptr_u8 = self.builder.buildBitCast(dest_ptr, ptr_u8_llvm_ty, "");
5436 const fill_char = u8_llvm_ty.constInt(0xaa, .False);5437 const fill_char = u8_llvm_ty.constInt(0xaa, .False);
5437 const dest_ptr_align = ptr_ty.ptrAlignment(target);5438 const dest_ptr_align = ptr_ty.ptrAlignment(target);
5438 const usize_llvm_ty = try self.dg.llvmType(Type.usize);5439 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);
5440 _ = self.builder.buildMemSet(dest_ptr_u8, fill_char, len, dest_ptr_align, ptr_ty.isVolatilePtr());5441 _ = self.builder.buildMemSet(dest_ptr_u8, fill_char, len, dest_ptr_align, ptr_ty.isVolatilePtr());
5441 if (self.dg.module.comp.bin_file.options.valgrind) {5442 if (self.dg.module.comp.bin_file.options.valgrind) {
5442 // TODO generate valgrind client request to mark byte range as undefined5443 // TODO generate valgrind client request to mark byte range as undefined
src/type.zig+1
...@@ -2098,6 +2098,7 @@ pub const Type = extern union {...@@ -2098,6 +2098,7 @@ pub const Type = extern union {
2098 }2098 }
2099 assert(struct_obj.haveFieldTypes());2099 assert(struct_obj.haveFieldTypes());
2100 for (struct_obj.fields.values()) |value| {2100 for (struct_obj.fields.values()) |value| {
2101 if (value.is_comptime) continue;
2101 if (value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only))2102 if (value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only))
2102 return true;2103 return true;
2103 } else {2104 } else {
test/behavior.zig+3
...@@ -65,8 +65,11 @@ test {...@@ -65,8 +65,11 @@ test {
65 _ = @import("behavior/bugs/10970.zig");65 _ = @import("behavior/bugs/10970.zig");
66 _ = @import("behavior/bugs/11046.zig");66 _ = @import("behavior/bugs/11046.zig");
67 _ = @import("behavior/bugs/11139.zig");67 _ = @import("behavior/bugs/11139.zig");
68 _ = @import("behavior/bugs/11159.zig");
69 _ = @import("behavior/bugs/11162.zig");
68 _ = @import("behavior/bugs/11165.zig");70 _ = @import("behavior/bugs/11165.zig");
69 _ = @import("behavior/bugs/11181.zig");71 _ = @import("behavior/bugs/11181.zig");
72 _ = @import("behavior/bugs/11182.zig");
70 _ = @import("behavior/call.zig");73 _ = @import("behavior/call.zig");
71 _ = @import("behavior/cast.zig");74 _ = @import("behavior/cast.zig");
72 _ = @import("behavior/comptime_memory.zig");75 _ = @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}