aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-07-28 15:00:40 +0300
committerVeikka Tuominen <git@vexu.eu>2022-08-01 23:37:01 +0300
commit57f9405a8fcaec6043d680fa47ae0e98709160c2 (patch)
tree40614ac1850186954c45c91f169d60a4df2bdb2b /src/Sema.zig
parente7b6a1833106a5d808e4e82a2d61abf417aff407 (diff)
downloadzig-57f9405a8fcaec6043d680fa47ae0e98709160c2.tar.gz
zig-57f9405a8fcaec6043d680fa47ae0e98709160c2.zip
Sema: validate bitcast operand type
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig86
1 files changed, 81 insertions, 5 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index a0829d6eb7..efdc0f8262 100644
--- a/src/Sema.zig
+++ b/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);
}