authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-13 16:53:01+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-13 16:53:01+03:00
log029fe6c9abca1373ef0e379fa8e24fbf3a987800
tree2b98942516624eefbe28112cb9ac470089427b54
parente5750f8c7f65455589e2d4b45847a351ab7023d6

meta.cast: handle casts from negative ints to ptrs


3 files changed, 38 insertions(+), 30 deletions(-)

lib/std/meta.zig+32-30
...@@ -890,38 +890,10 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {...@@ -890,38 +890,10 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
890 // this function should behave like transCCast in translate-c, except it's for macros and enums890 // this function should behave like transCCast in translate-c, except it's for macros and enums
891 const SourceType = @TypeOf(target);891 const SourceType = @TypeOf(target);
892 switch (@typeInfo(DestType)) {892 switch (@typeInfo(DestType)) {
893 .Pointer => {893 .Pointer => return castToPtr(DestType, SourceType, target),
894 switch (@typeInfo(SourceType)) {
895 .Int, .ComptimeInt => {
896 return @intToPtr(DestType, target);
897 },
898 .Pointer => {
899 return castPtr(DestType, target);
900 },
901 .Optional => |opt| {
902 if (@typeInfo(opt.child) == .Pointer) {
903 return castPtr(DestType, target);
904 }
905 },
906 else => {},
907 }
908 },
909 .Optional => |dest_opt| {894 .Optional => |dest_opt| {
910 if (@typeInfo(dest_opt.child) == .Pointer) {895 if (@typeInfo(dest_opt.child) == .Pointer) {
911 switch (@typeInfo(SourceType)) {896 return castToPtr(DestType, SourceType, target);
912 .Int, .ComptimeInt => {
913 return @intToPtr(DestType, target);
914 },
915 .Pointer => {
916 return castPtr(DestType, target);
917 },
918 .Optional => |target_opt| {
919 if (@typeInfo(target_opt.child) == .Pointer) {
920 return castPtr(DestType, target);
921 }
922 },
923 else => {},
924 }
925 }897 }
926 },898 },
927 .Enum => |enum_type| {899 .Enum => |enum_type| {
...@@ -977,6 +949,30 @@ fn castPtr(comptime DestType: type, target: anytype) DestType {...@@ -977,6 +949,30 @@ fn castPtr(comptime DestType: type, target: anytype) DestType {
977 return @ptrCast(DestType, @alignCast(dest.alignment, target));949 return @ptrCast(DestType, @alignCast(dest.alignment, target));
978}950}
979951
952fn castToPtr(comptime DestType: type, comptime SourceType: type, target: anytype) DestType {
953 switch (@typeInfo(SourceType)) {
954 .Int => {
955 return @intToPtr(DestType, castInt(usize, target));
956 },
957 .ComptimeInt => {
958 if (target < 0)
959 return @intToPtr(DestType, @bitCast(usize, @intCast(isize, target)))
960 else
961 return @intToPtr(DestType, @intCast(usize, target));
962 },
963 .Pointer => {
964 return castPtr(DestType, target);
965 },
966 .Optional => |target_opt| {
967 if (@typeInfo(target_opt.child) == .Pointer) {
968 return castPtr(DestType, target);
969 }
970 },
971 else => {},
972 }
973 return @as(DestType, target);
974}
975
980fn ptrInfo(comptime PtrType: type) TypeInfo.Pointer {976fn ptrInfo(comptime PtrType: type) TypeInfo.Pointer {
981 return switch (@typeInfo(PtrType)) {977 return switch (@typeInfo(PtrType)) {
982 .Optional => |opt_info| @typeInfo(opt_info.child).Pointer,978 .Optional => |opt_info| @typeInfo(opt_info.child).Pointer,
...@@ -1026,6 +1022,12 @@ test "std.meta.cast" {...@@ -1026,6 +1022,12 @@ test "std.meta.cast" {
1026 try testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B);1022 try testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B);
1027 try testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B);1023 try testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B);
1028 try testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42));1024 try testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42));
1025
1026 var foo: c_int = -1;
1027 try testing.expect(cast(*c_void, -1) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1))));
1028 try testing.expect(cast(*c_void, foo) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1))));
1029 try testing.expect(cast(?*c_void, -1) == @intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))));
1030 try testing.expect(cast(?*c_void, foo) == @intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))));
1029}1031}
10301032
1031/// Given a value returns its size as C's sizeof operator would.1033/// Given a value returns its size as C's sizeof operator would.
test/behavior/translate_c_macros.h+2
...@@ -16,3 +16,5 @@ struct Foo {...@@ -16,3 +16,5 @@ struct Foo {
16};16};
1717
18#define SIZE_OF_FOO sizeof(struct Foo)18#define SIZE_OF_FOO sizeof(struct Foo)
19
20#define MAP_FAILED ((void *) -1)
test/behavior/translate_c_macros.zig+4
...@@ -20,3 +20,7 @@ test "sizeof in macros" {...@@ -20,3 +20,7 @@ test "sizeof in macros" {
20test "reference to a struct type" {20test "reference to a struct type" {
21 try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);21 try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
22}22}
23
24test "cast negative integer to pointer" {
25 try expectEqual(@intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED);
26}