mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
Sema: fix illegal multi level pointer coercions
Moves a premature check that allowed pointers to mutable pointers to coerce to any other pointer to a mutable pointer.
This commit is contained in:
parent
c6b5945356
commit
06d08dabab
20
src/Sema.zig
20
src/Sema.zig
@ -29385,14 +29385,18 @@ const InMemoryCoercionResult = union(enum) {
|
|||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
.array_sentinel => |sentinel| {
|
.array_sentinel => |sentinel| {
|
||||||
if (sentinel.actual.toIntern() != .unreachable_value) {
|
if (sentinel.wanted.toIntern() == .unreachable_value) {
|
||||||
try sema.errNote(src, msg, "array sentinel '{f}' cannot cast into array sentinel '{f}'", .{
|
try sema.errNote(src, msg, "source array cannot be guaranteed to maintain '{f}' sentinel", .{
|
||||||
sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
|
sentinel.actual.fmtValueSema(pt, sema),
|
||||||
});
|
});
|
||||||
} else {
|
} else if (sentinel.actual.toIntern() == .unreachable_value) {
|
||||||
try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{
|
try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{
|
||||||
sentinel.wanted.fmtValueSema(pt, sema),
|
sentinel.wanted.fmtValueSema(pt, sema),
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
try sema.errNote(src, msg, "array sentinel '{f}' cannot cast into array sentinel '{f}'", .{
|
||||||
|
sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
@ -30179,10 +30183,14 @@ fn coerceInMemoryAllowedPtrs(
|
|||||||
src_src,
|
src_src,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
if (child != .ok and !dest_is_mut) allow: {
|
if (child != .ok) allow: {
|
||||||
// As a special case, we also allow coercing `*[n:s]T` to `*[n]T`, akin to dropping the sentinel from a slice.
|
// As a special case, we also allow coercing `*[n:s]T` to `*[n]T`, akin to dropping the sentinel from a slice.
|
||||||
// `*[n:s]T` cannot coerce in memory to `*[n]T` since they have different sizes.
|
// `*[n:s]T` cannot coerce in memory to `*[n]T` since they have different sizes.
|
||||||
if (src_child.zigTypeTag(zcu) == .array and dest_child.zigTypeTag(zcu) == .array and
|
//
|
||||||
|
// We must once again include `dest_is_mut` because `**[n:s]T -> **[n]T`
|
||||||
|
// is not allowed, as it would make it possible to assign an illegal value
|
||||||
|
// to the sentinel-terminated side.
|
||||||
|
if (!dest_is_mut and src_child.zigTypeTag(zcu) == .array and dest_child.zigTypeTag(zcu) == .array and
|
||||||
src_child.arrayLen(zcu) == dest_child.arrayLen(zcu) and
|
src_child.arrayLen(zcu) == dest_child.arrayLen(zcu) and
|
||||||
src_child.sentinel(zcu) != null and dest_child.sentinel(zcu) == null and
|
src_child.sentinel(zcu) != null and dest_child.sentinel(zcu) == null and
|
||||||
.ok == try sema.coerceInMemoryAllowed(block, dest_child.childType(zcu), src_child.childType(zcu), !dest_info.flags.is_const, target, dest_src, src_src, null))
|
.ok == try sema.coerceInMemoryAllowed(block, dest_child.childType(zcu), src_child.childType(zcu), !dest_info.flags.is_const, target, dest_src, src_src, null))
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
export fn entry1() void {
|
||||||
|
const p: **u32 = undefined;
|
||||||
|
const q: **i32 = p;
|
||||||
|
_ = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn entry2() void {
|
||||||
|
const p: [*]*u32 = undefined;
|
||||||
|
const q: [*]*i32 = p;
|
||||||
|
_ = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn entry3() void {
|
||||||
|
const p: []*u32 = undefined;
|
||||||
|
const q: []*i32 = p;
|
||||||
|
_ = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn entry4() void {
|
||||||
|
const p: [*c]*u32 = undefined;
|
||||||
|
const q: [*c]*i32 = p;
|
||||||
|
_ = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn entry5() void {
|
||||||
|
const p: **[1:42]u8 = undefined;
|
||||||
|
const q: **[1]u8 = p;
|
||||||
|
_ = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
//
|
||||||
|
// :3:22: error: expected type '**i32', found '**u32'
|
||||||
|
// :3:22: note: pointer type child '*u32' cannot cast into pointer type child '*i32'
|
||||||
|
// :3:22: note: pointer type child 'u32' cannot cast into pointer type child 'i32'
|
||||||
|
// :3:22: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
|
||||||
|
// :9:24: error: expected type '[*]*i32', found '[*]*u32'
|
||||||
|
// :9:24: note: pointer type child '*u32' cannot cast into pointer type child '*i32'
|
||||||
|
// :9:24: note: pointer type child 'u32' cannot cast into pointer type child 'i32'
|
||||||
|
// :9:24: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
|
||||||
|
// :15:23: error: expected type '[]*i32', found '[]*u32'
|
||||||
|
// :15:23: note: pointer type child '*u32' cannot cast into pointer type child '*i32'
|
||||||
|
// :15:23: note: pointer type child 'u32' cannot cast into pointer type child 'i32'
|
||||||
|
// :15:23: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
|
||||||
|
// :21:25: error: expected type '[*c]*i32', found '[*c]*u32'
|
||||||
|
// :21:25: note: pointer type child '*u32' cannot cast into pointer type child '*i32'
|
||||||
|
// :21:25: note: pointer type child 'u32' cannot cast into pointer type child 'i32'
|
||||||
|
// :21:25: note: signed 32-bit int cannot represent all possible unsigned 32-bit values
|
||||||
|
// :27:24: error: expected type '**[1]u8', found '**[1:42]u8'
|
||||||
|
// :27:24: note: pointer type child '*[1:42]u8' cannot cast into pointer type child '*[1]u8'
|
||||||
|
// :27:24: note: pointer type child '[1:42]u8' cannot cast into pointer type child '[1]u8'
|
||||||
|
// :27:24: note: source array cannot be guaranteed to maintain '42' sentinel
|
||||||
Loading…
x
Reference in New Issue
Block a user