| author | |
| committer | |
| log | b77679039fd40aa1693781f99ac89f2dc705e5c2 |
| tree | e3a4d2e77f3e4e31b3c854a6ffe010f1cb35e8b5 |
| parent | 0f2339f55b2fa45a8af94c26a7ceb8377e3acfef |
| parent | c205521aea01e332209a28e7518a787d1c1e8f26 |
| signature |
Set `c_char` signedness based on the target6 files changed, 44 insertions(+), 5 deletions(-)
lib/std/target.zig+26| ... | @@ -1910,6 +1910,32 @@ pub const Target = struct { | ... | @@ -1910,6 +1910,32 @@ pub const Target = struct { |
| 1910 | } | 1910 | } |
| 1911 | } | 1911 | } |
| 1912 | 1912 | ||
| 1913 | /// Default signedness of `char` for the native C compiler for this target | ||
| 1914 | /// Note that char signedness is implementation-defined and many compilers provide | ||
| 1915 | /// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char | ||
| 1916 | pub fn charSignedness(target: Target) std.builtin.Signedness { | ||
| 1917 | switch (target.cpu.arch) { | ||
| 1918 | .aarch64, | ||
| 1919 | .aarch64_32, | ||
| 1920 | .aarch64_be, | ||
| 1921 | .arm, | ||
| 1922 | .armeb, | ||
| 1923 | .thumb, | ||
| 1924 | .thumbeb, | ||
| 1925 | => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned, | ||
| 1926 | .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned, | ||
| 1927 | .powerpc64le, | ||
| 1928 | .s390x, | ||
| 1929 | .xcore, | ||
| 1930 | .arc, | ||
| 1931 | .msp430, | ||
| 1932 | .riscv32, | ||
| 1933 | .riscv64, | ||
| 1934 | => return .unsigned, | ||
| 1935 | else => return .signed, | ||
| 1936 | } | ||
| 1937 | } | ||
| 1938 | |||
| 1913 | pub const CType = enum { | 1939 | pub const CType = enum { |
| 1914 | char, | 1940 | char, |
| 1915 | short, | 1941 | short, |
src/codegen/c.zig+1-1| ... | @@ -1880,7 +1880,7 @@ pub const DeclGen = struct { | ... | @@ -1880,7 +1880,7 @@ pub const DeclGen = struct { |
| 1880 | if (cty.isBool()) | 1880 | if (cty.isBool()) |
| 1881 | signAbbrev(.unsigned) | 1881 | signAbbrev(.unsigned) |
| 1882 | else if (cty.isInteger()) | 1882 | else if (cty.isInteger()) |
| 1883 | signAbbrev(cty.signedness() orelse .unsigned) | 1883 | signAbbrev(cty.signedness(dg.module.getTarget())) |
| 1884 | else if (cty.isFloat()) | 1884 | else if (cty.isFloat()) |
| 1885 | @as(u8, 'f') | 1885 | @as(u8, 'f') |
| 1886 | else if (cty.isPointer()) | 1886 | else if (cty.isPointer()) |
src/codegen/c/type.zig+2-2| ... | @@ -537,9 +537,9 @@ pub const CType = extern union { | ... | @@ -537,9 +537,9 @@ pub const CType = extern union { |
| 537 | }; | 537 | }; |
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | pub fn signedness(self: CType) ?std.builtin.Signedness { | 540 | pub fn signedness(self: CType, target: std.Target) std.builtin.Signedness { |
| 541 | return switch (self.tag()) { | 541 | return switch (self.tag()) { |
| 542 | .char => null, // unknown signedness | 542 | .char => target.charSignedness(), |
| 543 | .@"signed char", | 543 | .@"signed char", |
| 544 | .short, | 544 | .short, |
| 545 | .int, | 545 | .int, |
src/type.zig+4-2| ... | @@ -2216,7 +2216,8 @@ pub const Type = struct { | ... | @@ -2216,7 +2216,8 @@ pub const Type = struct { |
| 2216 | /// Returns true if and only if the type is a fixed-width, signed integer. | 2216 | /// Returns true if and only if the type is a fixed-width, signed integer. |
| 2217 | pub fn isSignedInt(ty: Type, mod: *const Module) bool { | 2217 | pub fn isSignedInt(ty: Type, mod: *const Module) bool { |
| 2218 | return switch (ty.toIntern()) { | 2218 | return switch (ty.toIntern()) { |
| 2219 | .c_char_type, .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true, | 2219 | .c_char_type => mod.getTarget().charSignedness() == .signed, |
| 2220 | .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true, | ||
| 2220 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2221 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { |
| 2221 | .int_type => |int_type| int_type.signedness == .signed, | 2222 | .int_type => |int_type| int_type.signedness == .signed, |
| 2222 | else => false, | 2223 | else => false, |
| ... | @@ -2227,6 +2228,7 @@ pub const Type = struct { | ... | @@ -2227,6 +2228,7 @@ pub const Type = struct { |
| 2227 | /// Returns true if and only if the type is a fixed-width, unsigned integer. | 2228 | /// Returns true if and only if the type is a fixed-width, unsigned integer. |
| 2228 | pub fn isUnsignedInt(ty: Type, mod: *const Module) bool { | 2229 | pub fn isUnsignedInt(ty: Type, mod: *const Module) bool { |
| 2229 | return switch (ty.toIntern()) { | 2230 | return switch (ty.toIntern()) { |
| 2231 | .c_char_type => mod.getTarget().charSignedness() == .unsigned, | ||
| 2230 | .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true, | 2232 | .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true, |
| 2231 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2233 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { |
| 2232 | .int_type => |int_type| int_type.signedness == .unsigned, | 2234 | .int_type => |int_type| int_type.signedness == .unsigned, |
| ... | @@ -2257,7 +2259,7 @@ pub const Type = struct { | ... | @@ -2257,7 +2259,7 @@ pub const Type = struct { |
| 2257 | }, | 2259 | }, |
| 2258 | .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() }, | 2260 | .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() }, |
| 2259 | .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() }, | 2261 | .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() }, |
| 2260 | .c_char_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.char) }, | 2262 | .c_char_type => return .{ .signedness = mod.getTarget().charSignedness(), .bits = target.c_type_bit_size(.char) }, |
| 2261 | .c_short_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) }, | 2263 | .c_short_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) }, |
| 2262 | .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) }, | 2264 | .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) }, |
| 2263 | .c_int_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) }, | 2265 | .c_int_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) }, |
test/behavior.zig+1| ... | @@ -145,6 +145,7 @@ test { | ... | @@ -145,6 +145,7 @@ test { |
| 145 | _ = @import("behavior/bugs/15778.zig"); | 145 | _ = @import("behavior/bugs/15778.zig"); |
| 146 | _ = @import("behavior/byteswap.zig"); | 146 | _ = @import("behavior/byteswap.zig"); |
| 147 | _ = @import("behavior/byval_arg_var.zig"); | 147 | _ = @import("behavior/byval_arg_var.zig"); |
| 148 | _ = @import("behavior/c_char_signedness.zig"); | ||
| 148 | _ = @import("behavior/call.zig"); | 149 | _ = @import("behavior/call.zig"); |
| 149 | _ = @import("behavior/cast.zig"); | 150 | _ = @import("behavior/cast.zig"); |
| 150 | _ = @import("behavior/cast_int.zig"); | 151 | _ = @import("behavior/cast_int.zig"); |
test/behavior/c_char_signedness.zig created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expectEqual = std.testing.expectEqual; | ||
| 3 | const c = @cImport({ | ||
| 4 | @cInclude("limits.h"); | ||
| 5 | }); | ||
| 6 | |||
| 7 | test "c_char signedness" { | ||
| 8 | try expectEqual(@as(c_char, c.CHAR_MIN), std.math.minInt(c_char)); | ||
| 9 | try expectEqual(@as(c_char, c.CHAR_MAX), std.math.maxInt(c_char)); | ||
| 10 | } | ||