Commit fb9d6b8bd9

Evan Haas <evan@lagerdata.com>
2023-06-20 09:20:32
codegen: Set c_char signedness based on the target
1 parent 657fe55
Changed files (5)
src/codegen/c/type.zig
@@ -537,9 +537,9 @@ pub const CType = extern union {
         };
     }
 
-    pub fn signedness(self: CType) ?std.builtin.Signedness {
+    pub fn signedness(self: CType, target: std.Target) std.builtin.Signedness {
         return switch (self.tag()) {
-            .char => null, // unknown signedness
+            .char => target.charSignedness(),
             .@"signed char",
             .short,
             .int,
src/codegen/c.zig
@@ -1880,7 +1880,7 @@ pub const DeclGen = struct {
                 if (cty.isBool())
                     signAbbrev(.unsigned)
                 else if (cty.isInteger())
-                    signAbbrev(cty.signedness() orelse .unsigned)
+                    signAbbrev(cty.signedness(dg.module.getTarget()))
                 else if (cty.isFloat())
                     @as(u8, 'f')
                 else if (cty.isPointer())
src/type.zig
@@ -2216,7 +2216,8 @@ pub const Type = struct {
     /// Returns true if and only if the type is a fixed-width, signed integer.
     pub fn isSignedInt(ty: Type, mod: *const Module) bool {
         return switch (ty.toIntern()) {
-            .c_char_type, .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
+            .c_char_type => mod.getTarget().charSignedness() == .signed,
+            .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
             else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
                 .int_type => |int_type| int_type.signedness == .signed,
                 else => false,
@@ -2227,6 +2228,7 @@ pub const Type = struct {
     /// Returns true if and only if the type is a fixed-width, unsigned integer.
     pub fn isUnsignedInt(ty: Type, mod: *const Module) bool {
         return switch (ty.toIntern()) {
+            .c_char_type => mod.getTarget().charSignedness() == .unsigned,
             .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
             else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
                 .int_type => |int_type| int_type.signedness == .unsigned,
@@ -2257,7 +2259,7 @@ pub const Type = struct {
             },
             .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
             .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
-            .c_char_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.char) },
+            .c_char_type => return .{ .signedness = mod.getTarget().charSignedness(), .bits = target.c_type_bit_size(.char) },
             .c_short_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },
             .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },
             .c_int_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },
test/behavior/c_char_signedness.zig
@@ -0,0 +1,10 @@
+const std = @import("std");
+const expectEqual = std.testing.expectEqual;
+const c = @cImport({
+    @cInclude("limits.h");
+});
+
+test "c_char signedness" {
+    try expectEqual(@as(c_char, c.CHAR_MIN), std.math.minInt(c_char));
+    try expectEqual(@as(c_char, c.CHAR_MAX), std.math.maxInt(c_char));
+}
test/behavior.zig
@@ -145,6 +145,7 @@ test {
     _ = @import("behavior/bugs/15778.zig");
     _ = @import("behavior/byteswap.zig");
     _ = @import("behavior/byval_arg_var.zig");
+    _ = @import("behavior/c_char_signedness.zig");
     _ = @import("behavior/call.zig");
     _ = @import("behavior/cast.zig");
     _ = @import("behavior/cast_int.zig");