authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-15 14:28:16-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-09-15 14:28:16-04:00
logb3cc36857ebc4bcfc259da361018d70c1a7d9e7b
treea7f68df99f4296ecd80e1d0e42d31bcebf43775d
parentc1c3212500377a8128f37a873a7845c6bf5993e6
parenta3624e94f812efaae40d2ca66da0b49ca63cb936
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6340 from Vexu/fix

Fixes

2 files changed, 67 insertions(+), 16 deletions(-)

lib/std/meta.zig+55-12
......@@ -717,7 +717,7 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
717717 },
718718 .Optional => |opt| {
719719 if (@typeInfo(opt.child) == .Pointer) {
720 return @ptrCast(DestType, @alignCast(dest_ptr, target));
720 return @ptrCast(DestType, @alignCast(dest_ptr.alignment, target));
721721 }
722722 },
723723 else => {},
......@@ -725,23 +725,24 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
725725 },
726726 .Optional => |dest_opt| {
727727 if (@typeInfo(dest_opt.child) == .Pointer) {
728 const dest_ptr = @typeInfo(dest_opt.child).Pointer;
728729 switch (@typeInfo(TargetType)) {
729730 .Int, .ComptimeInt => {
730731 return @intToPtr(DestType, target);
731732 },
732733 .Pointer => {
733 return @ptrCast(DestType, @alignCast(@alignOf(dest_opt.child.Child), target));
734 return @ptrCast(DestType, @alignCast(dest_ptr.alignment, target));
734735 },
735736 .Optional => |target_opt| {
736737 if (@typeInfo(target_opt.child) == .Pointer) {
737 return @ptrCast(DestType, @alignCast(@alignOf(dest_opt.child.Child), target));
738 return @ptrCast(DestType, @alignCast(dest_ptr.alignment, target));
738739 }
739740 },
740741 else => {},
741742 }
742743 }
743744 },
744 .Enum, .EnumLiteral => {
745 .Enum => {
745746 if (@typeInfo(TargetType) == .Int or @typeInfo(TargetType) == .ComptimeInt) {
746747 return @intToEnum(DestType, target);
747748 }
......@@ -749,15 +750,18 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
749750 .Int, .ComptimeInt => {
750751 switch (@typeInfo(TargetType)) {
751752 .Pointer => {
752 return @as(DestType, @ptrToInt(target));
753 return @intCast(DestType, @ptrToInt(target));
753754 },
754755 .Optional => |opt| {
755756 if (@typeInfo(opt.child) == .Pointer) {
756 return @as(DestType, @ptrToInt(target));
757 return @intCast(DestType, @ptrToInt(target));
757758 }
758759 },
759 .Enum, .EnumLiteral => {
760 return @as(DestType, @enumToInt(target));
760 .Enum => {
761 return @intCast(DestType, @enumToInt(target));
762 },
763 .Int, .ComptimeInt => {
764 return @intCast(DestType, target);
761765 },
762766 else => {},
763767 }
......@@ -776,10 +780,49 @@ test "std.meta.cast" {
776780
777781 var i = @as(i64, 10);
778782
779 testing.expect(cast(?*c_void, 0) == @intToPtr(?*c_void, 0));
780783 testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16));
781 testing.expect(cast(u64, @as(u32, 10)) == @as(u64, 10));
782 testing.expect(cast(E, 1) == .One);
783 testing.expect(cast(u8, E.Two) == 2);
784784 testing.expect(cast(*u64, &i).* == @as(u64, 10));
785 testing.expect(cast(*i64, @as(?*align(1) i64, &i)) == &i);
786
787 testing.expect(cast(?*u8, 2) == @intToPtr(*u8, 2));
788 testing.expect(cast(?*i64, @as(*align(1) i64, &i)) == &i);
789 testing.expect(cast(?*i64, @as(?*align(1) i64, &i)) == &i);
790
791 testing.expect(cast(E, 1) == .One);
792
793 testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(*u32, 4)));
794 testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(?*u32, 4)));
795 testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10)));
796 testing.expectEqual(@as(u8, 2), cast(u8, E.Two));
797}
798
799/// Given a value returns its size as C's sizeof operator would.
800/// This is for translate-c and is not intended for general use.
801pub fn sizeof(target: anytype) usize {
802 switch (@typeInfo(@TypeOf(target))) {
803 .Type => return @sizeOf(target),
804 .Float, .Int, .Struct, .Union, .Enum => return @sizeOf(@TypeOf(target)),
805 .ComptimeFloat => return @sizeOf(f64), // TODO c_double #3999
806 .ComptimeInt => {
807 // TODO to get the correct result we have to translate
808 // `1073741824 * 4` as `int(1073741824) *% int(4)` since
809 // sizeof(1073741824 * 4) != sizeof(4294967296).
810
811 // TODO test if target fits in int, long or long long
812 return @sizeOf(c_int);
813 },
814 else => @compileError("TODO implement std.meta.sizeof for type " ++ @typeName(@TypeOf(target))),
815 }
816}
817
818test "sizeof" {
819 const E = extern enum(c_int) { One, _ };
820 const S = extern struct { a: u32 };
821
822 testing.expect(sizeof(u32) == 4);
823 testing.expect(sizeof(@as(u32, 2)) == 4);
824 testing.expect(sizeof(2) == @sizeOf(c_int));
825 testing.expect(sizeof(E) == @sizeOf(c_int));
826 testing.expect(sizeof(E.One) == @sizeOf(c_int));
827 testing.expect(sizeof(S) == 4);
785828}
src-self-hosted/translate_c.zig+12-4
......@@ -6324,10 +6324,18 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.
63246324 break :blk inner;
63256325 } else try parseCPrefixOpExpr(c, m, scope);
63266326
6327 const builtin_call = try c.createBuiltinCall("@sizeOf", 1);
6328 builtin_call.params()[0] = inner;
6329 builtin_call.rparen_token = try appendToken(c, .RParen, ")");
6330 return &builtin_call.base;
6327 //(@import("std").meta.sizeof(dest, x))
6328 const import_fn_call = try c.createBuiltinCall("@import", 1);
6329 const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
6330 import_fn_call.params()[0] = std_node;
6331 import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
6332 const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "meta");
6333 const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "sizeof");
6334
6335 const sizeof_call = try c.createCall(outer_field_access, 1);
6336 sizeof_call.params()[0] = inner;
6337 sizeof_call.rtoken = try appendToken(c, .RParen, ")");
6338 return &sizeof_call.base;
63316339 },
63326340 .Keyword_alignof => {
63336341 // TODO this won't work if using <stdalign.h>'s