mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
Sema: fix compiler crash @ptrCasting optional slice
This commit is contained in:
parent
7d41a5cbcf
commit
1e67f50211
32
src/Sema.zig
32
src/Sema.zig
@ -22779,7 +22779,11 @@ fn ptrCastFull(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ptr = if (src_info.flags.size == .Slice and dest_info.flags.size != .Slice) ptr: {
|
const ptr = if (src_info.flags.size == .Slice and dest_info.flags.size != .Slice) ptr: {
|
||||||
break :ptr try sema.analyzeSlicePtr(block, operand_src, operand, operand_ty);
|
if (operand_ty.zigTypeTag(mod) == .Optional) {
|
||||||
|
break :ptr try sema.analyzeOptionalSlicePtr(block, operand_src, operand, operand_ty);
|
||||||
|
} else {
|
||||||
|
break :ptr try sema.analyzeSlicePtr(block, operand_src, operand, operand_ty);
|
||||||
|
}
|
||||||
} else operand;
|
} else operand;
|
||||||
|
|
||||||
const dest_ptr_ty = if (dest_info.flags.size == .Slice and src_info.flags.size != .Slice) blk: {
|
const dest_ptr_ty = if (dest_info.flags.size == .Slice and src_info.flags.size != .Slice) blk: {
|
||||||
@ -32564,6 +32568,32 @@ fn analyzeSlicePtr(
|
|||||||
return block.addTyOp(.slice_ptr, result_ty, slice);
|
return block.addTyOp(.slice_ptr, result_ty, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn analyzeOptionalSlicePtr(
|
||||||
|
sema: *Sema,
|
||||||
|
block: *Block,
|
||||||
|
opt_slice_src: LazySrcLoc,
|
||||||
|
opt_slice: Air.Inst.Ref,
|
||||||
|
opt_slice_ty: Type,
|
||||||
|
) CompileError!Air.Inst.Ref {
|
||||||
|
const mod = sema.mod;
|
||||||
|
const result_ty = opt_slice_ty.optionalChild(mod).slicePtrFieldType(mod);
|
||||||
|
|
||||||
|
if (try sema.resolveValue(opt_slice)) |opt_val| {
|
||||||
|
if (opt_val.isUndef(mod)) return mod.undefRef(result_ty);
|
||||||
|
const slice_ptr: InternPool.Index = if (opt_val.optionalValue(mod)) |val|
|
||||||
|
val.slicePtr(mod).toIntern()
|
||||||
|
else
|
||||||
|
.null_value;
|
||||||
|
|
||||||
|
return Air.internedToRef(slice_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
try sema.requireRuntimeBlock(block, opt_slice_src, null);
|
||||||
|
|
||||||
|
const slice = try block.addTyOp(.optional_payload, opt_slice_ty, opt_slice);
|
||||||
|
return block.addTyOp(.slice_ptr, result_ty, slice);
|
||||||
|
}
|
||||||
|
|
||||||
fn analyzeSliceLen(
|
fn analyzeSliceLen(
|
||||||
sema: *Sema,
|
sema: *Sema,
|
||||||
block: *Block,
|
block: *Block,
|
||||||
|
|||||||
@ -1550,6 +1550,32 @@ test "optional pointer coerced to optional allowzero pointer" {
|
|||||||
try expect(@intFromPtr(q.?) == 4);
|
try expect(@intFromPtr(q.?) == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "optional slice coerced to allowzero many pointer" {
|
||||||
|
const a: ?[]const u32 = null;
|
||||||
|
const b: [*]allowzero const u8 = @ptrCast(a);
|
||||||
|
const c = @intFromPtr(b);
|
||||||
|
try std.testing.expect(c == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "optional slice passed as parameter coerced to allowzero many pointer" {
|
||||||
|
const ns = struct {
|
||||||
|
const Color = struct {
|
||||||
|
r: u8,
|
||||||
|
g: u8,
|
||||||
|
b: u8,
|
||||||
|
a: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn foo(pixels: ?[]const Color) !void {
|
||||||
|
const data: [*]allowzero const u8 = @ptrCast(pixels);
|
||||||
|
const int = @intFromPtr(data);
|
||||||
|
try std.testing.expect(int == 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try ns.foo(null);
|
||||||
|
}
|
||||||
|
|
||||||
test "single item pointer to pointer to array to slice" {
|
test "single item pointer to pointer to array to slice" {
|
||||||
var x: i32 = 1234;
|
var x: i32 = 1234;
|
||||||
try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);
|
try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user