mirror of
https://github.com/ziglang/zig.git
synced 2026-01-12 10:25:13 +00:00
Merge pull request #22239 from mlugg/runtime-store-comptime-only
Sema: disallow runtime stores to pointers with comptime-only element types Resolves: #22175
This commit is contained in:
commit
12f0c38347
38
src/Sema.zig
38
src/Sema.zig
@ -3628,6 +3628,10 @@ fn zirAllocExtended(
|
||||
}
|
||||
}
|
||||
|
||||
if (small.has_type and try var_ty.comptimeOnlySema(pt)) {
|
||||
return sema.analyzeComptimeAlloc(block, var_ty, alignment);
|
||||
}
|
||||
|
||||
if (small.has_type) {
|
||||
if (!small.is_const) {
|
||||
try sema.validateVarType(block, ty_src, var_ty, false);
|
||||
@ -4075,7 +4079,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
|
||||
const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node });
|
||||
|
||||
const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
|
||||
if (block.is_comptime) {
|
||||
if (block.is_comptime or try var_ty.comptimeOnlySema(pt)) {
|
||||
return sema.analyzeComptimeAlloc(block, var_ty, .none);
|
||||
}
|
||||
if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) {
|
||||
@ -30675,6 +30679,18 @@ fn coerceExtra(
|
||||
else => {},
|
||||
}
|
||||
|
||||
const can_coerce_to = switch (dest_ty.zigTypeTag(zcu)) {
|
||||
.noreturn, .@"opaque" => false,
|
||||
else => true,
|
||||
};
|
||||
|
||||
if (can_coerce_to) {
|
||||
// undefined to anything. We do this after the big switch above so that
|
||||
// special logic has a chance to run first, such as `*[N]T` to `[]T` which
|
||||
// should initialize the length field of the slice.
|
||||
if (maybe_inst_val) |val| if (val.toIntern() == .undef) return pt.undefRef(dest_ty);
|
||||
}
|
||||
|
||||
if (!opts.report_err) return error.NotCoercible;
|
||||
|
||||
if (opts.is_ret and dest_ty.zigTypeTag(zcu) == .noreturn) {
|
||||
@ -30692,15 +30708,14 @@ fn coerceExtra(
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
}
|
||||
|
||||
// undefined to anything. We do this after the big switch above so that
|
||||
// special logic has a chance to run first, such as `*[N]T` to `[]T` which
|
||||
// should initialize the length field of the slice.
|
||||
if (maybe_inst_val) |val| if (val.toIntern() == .undef) return pt.undefRef(dest_ty);
|
||||
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(pt), inst_ty.fmt(pt) });
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
if (!can_coerce_to) {
|
||||
try sema.errNote(inst_src, msg, "cannot coerce to '{}'", .{dest_ty.fmt(pt)});
|
||||
}
|
||||
|
||||
// E!T to T
|
||||
if (inst_ty.zigTypeTag(zcu) == .error_union and
|
||||
(try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok)
|
||||
@ -31927,6 +31942,17 @@ fn storePtr2(
|
||||
} else break :rs ptr_src;
|
||||
} else ptr_src;
|
||||
|
||||
// We're performing the store at runtime; as such, we need to make sure the pointee type
|
||||
// is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.
|
||||
if (try elem_ty.comptimeOnlySema(pt)) {
|
||||
return sema.failWithOwnedErrorMsg(block, msg: {
|
||||
const msg = try sema.errMsg(src, "cannot store comptime-only type '{}' at runtime", .{elem_ty.fmt(pt)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});
|
||||
break :msg msg;
|
||||
});
|
||||
}
|
||||
|
||||
// We do this after the possible comptime store above, for the case of field_ptr stores
|
||||
// to unions because we want the comptime tag to be set, even if the field type is void.
|
||||
if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) {
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
export fn a() void {
|
||||
const p: *fn () void = @ptrFromInt(4);
|
||||
p.* = undefined;
|
||||
}
|
||||
|
||||
export fn b(p: *anyopaque) void {
|
||||
p.* = undefined;
|
||||
}
|
||||
|
||||
export fn c(p: *anyopaque, q: *anyopaque) void {
|
||||
p.* = q.*;
|
||||
}
|
||||
|
||||
const Opaque = opaque {};
|
||||
export fn d(p: *Opaque) void {
|
||||
p.* = undefined;
|
||||
}
|
||||
|
||||
export fn e() void {
|
||||
const p: *comptime_int = @ptrFromInt(16);
|
||||
p.* = undefined;
|
||||
}
|
||||
|
||||
export fn f() void {
|
||||
const p: **comptime_int = @ptrFromInt(16); // double pointer ('*comptime_int' is comptime-only)
|
||||
p.* = undefined;
|
||||
}
|
||||
|
||||
// error
|
||||
//
|
||||
// :3:9: error: cannot store comptime-only type 'fn () void' at runtime
|
||||
// :3:6: note: operation is runtime due to this pointer
|
||||
// :7:11: error: expected type 'anyopaque', found '@TypeOf(undefined)'
|
||||
// :7:11: note: cannot coerce to 'anyopaque'
|
||||
// :11:12: error: cannot load opaque type 'anyopaque'
|
||||
// :16:11: error: expected type 'tmp.Opaque', found '@TypeOf(undefined)'
|
||||
// :16:11: note: cannot coerce to 'tmp.Opaque'
|
||||
// :14:16: note: opaque declared here
|
||||
// :21:9: error: cannot store comptime-only type 'comptime_int' at runtime
|
||||
// :21:6: note: operation is runtime due to this pointer
|
||||
// :26:9: error: cannot store comptime-only type '*comptime_int' at runtime
|
||||
// :26:6: note: operation is runtime due to this pointer
|
||||
Loading…
x
Reference in New Issue
Block a user