mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
Sema: validate bitcast operand type
This commit is contained in:
parent
e7b6a18331
commit
57f9405a8f
86
src/Sema.zig
86
src/Sema.zig
@ -8288,6 +8288,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
|
||||
const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
switch (dest_ty.zigTypeTag()) {
|
||||
.AnyFrame,
|
||||
.ComptimeFloat,
|
||||
@ -8310,8 +8311,8 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
switch (sema.typeOf(operand).zigTypeTag()) {
|
||||
.Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum for type coercion", .{}),
|
||||
switch (operand_ty.zigTypeTag()) {
|
||||
.Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(sema.mod)}),
|
||||
else => {},
|
||||
}
|
||||
|
||||
@ -8320,9 +8321,20 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
},
|
||||
|
||||
.Pointer => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}', use @ptrCast to cast to a pointer", .{
|
||||
dest_ty.fmt(sema.mod),
|
||||
}),
|
||||
.Pointer => {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
switch (operand_ty.zigTypeTag()) {
|
||||
.Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(sema.mod)}),
|
||||
.Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(sema.mod)}),
|
||||
else => {},
|
||||
}
|
||||
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
},
|
||||
.Struct, .Union => if (dest_ty.containerLayout() == .Auto) {
|
||||
const container = switch (dest_ty.zigTypeTag()) {
|
||||
.Struct => "struct",
|
||||
@ -8342,6 +8354,70 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
.Vector,
|
||||
=> {},
|
||||
}
|
||||
switch (operand_ty.zigTypeTag()) {
|
||||
.AnyFrame,
|
||||
.ComptimeFloat,
|
||||
.ComptimeInt,
|
||||
.EnumLiteral,
|
||||
.ErrorSet,
|
||||
.ErrorUnion,
|
||||
.Fn,
|
||||
.Frame,
|
||||
.NoReturn,
|
||||
.Null,
|
||||
.Opaque,
|
||||
.Optional,
|
||||
.Type,
|
||||
.Undefined,
|
||||
.Void,
|
||||
=> return sema.fail(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}),
|
||||
|
||||
.Enum => {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
switch (dest_ty.zigTypeTag()) {
|
||||
.Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}),
|
||||
else => {},
|
||||
}
|
||||
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
},
|
||||
.Pointer => {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
switch (dest_ty.zigTypeTag()) {
|
||||
.Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}),
|
||||
.Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(sema.mod)}),
|
||||
else => {},
|
||||
}
|
||||
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
},
|
||||
.Struct, .Union => if (operand_ty.containerLayout() == .Auto) {
|
||||
const container = switch (operand_ty.zigTypeTag()) {
|
||||
.Struct => "struct",
|
||||
.Union => "union",
|
||||
else => unreachable,
|
||||
};
|
||||
return sema.fail(block, operand_src, "cannot @bitCast from '{}', {s} does not have a guaranteed in-memory layout", .{
|
||||
operand_ty.fmt(sema.mod), container,
|
||||
});
|
||||
},
|
||||
.BoundFn => @panic("TODO remove this type from the language and compiler"),
|
||||
|
||||
.Array,
|
||||
.Bool,
|
||||
.Float,
|
||||
.Int,
|
||||
.Vector,
|
||||
=> {},
|
||||
}
|
||||
return sema.bitCast(block, dest_ty, operand, operand_src);
|
||||
}
|
||||
|
||||
|
||||
@ -90,22 +90,6 @@ test "nested bitcast" {
|
||||
comptime try S.foo(42);
|
||||
}
|
||||
|
||||
test "@bitCast enum to its integer type" {
|
||||
const SOCK = enum(c_int) {
|
||||
A,
|
||||
B,
|
||||
|
||||
fn testBitCastExternEnum() !void {
|
||||
var SOCK_DGRAM = @This().B;
|
||||
var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
|
||||
try expect(sock_dgram == 1);
|
||||
}
|
||||
};
|
||||
|
||||
try SOCK.testBitCastExternEnum();
|
||||
comptime try SOCK.testBitCastExternEnum();
|
||||
}
|
||||
|
||||
// issue #3010: compiler segfault
|
||||
test "bitcast literal [4]u8 param to u32" {
|
||||
const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
|
||||
|
||||
@ -9,4 +9,4 @@ export fn entry() void {
|
||||
// target=native
|
||||
//
|
||||
// :3:24: error: cannot @bitCast to 'tmp.entry.E'
|
||||
// :3:24: note: use @intToEnum for type coercion
|
||||
// :3:24: note: use @intToEnum to cast from 'u32'
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
pub export fn entry() void {
|
||||
var y = @intToPtr([*]align(4) u8, 5);
|
||||
_ = y;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:39: error: pointer type '[*]align(4) u8' requires aligned address
|
||||
@ -10,8 +10,10 @@ export fn foo2() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:42: error: unable to @bitCast from pointer type '*[2]u8'
|
||||
// tmp.zig:8:32: error: destination type 'u16' has size 2 but source type '[]const u8' has size 16
|
||||
// :3:42: error: cannot @bitCast from '*[2]u8'
|
||||
// :3:42: note: use @ptrToInt to cast to 'u16'
|
||||
// :8:37: error: cannot @bitCast from '[]const u8'
|
||||
// :8:37: note: use @ptrToInt to cast to 'u16'
|
||||
@ -1,10 +0,0 @@
|
||||
pub fn main() void {
|
||||
var y = @intToPtr([*]align(4) u8, 5);
|
||||
_ = y;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address
|
||||
Loading…
x
Reference in New Issue
Block a user