Commit 3f98756f85
Changed files (3)
src-self-hosted
src-self-hosted/translate_c.zig
@@ -2577,8 +2577,27 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArrayS
const container_node = try transExpr(rp, scope, base_stmt, .used, .r_value);
const node = try transCreateNodeArrayAccess(rp.c, container_node);
- node.op.ArrayAccess = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getIdx(stmt), .used, .r_value);
- node.rtoken = try appendToken(rp.c, .RBrace, "]");
+
+ // cast if the index is long long or signed
+ const subscr_expr = ZigClangArraySubscriptExpr_getIdx(stmt);
+ const qt = getExprQualType(rp.c, subscr_expr);
+ const is_longlong = cIsLongLongInteger(qt);
+ const is_signed = cIsSignedInteger(qt);
+
+ if (is_longlong or is_signed) {
+ const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");
+ // check if long long first so that signed long long doesn't just become unsigned long long
+ var typeid_node = if (is_longlong) try transCreateNodeIdentifier(rp.c, "usize") else try transQualTypeIntWidthOf(rp.c, qt, false);
+ try cast_node.params.push(typeid_node);
+ _ = try appendToken(rp.c, .Comma, ",");
+ try cast_node.params.push(try transExpr(rp, scope, subscr_expr, .used, .r_value));
+ cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ node.rtoken = try appendToken(rp.c, .RBrace, "]");
+ node.op.ArrayAccess = &cast_node.base;
+ } else {
+ node.op.ArrayAccess = try transExpr(rp, scope, subscr_expr, .used, .r_value);
+ node.rtoken = try appendToken(rp.c, .RBrace, "]");
+ }
return maybeSuppressResult(rp, scope, result_used, &node.base);
}
@@ -3528,6 +3547,15 @@ fn cIsFloating(qt: ZigClangQualType) bool {
};
}
+fn cIsLongLongInteger(qt: ZigClangQualType) bool {
+ const c_type = qualTypeCanon(qt);
+ if (ZigClangType_getTypeClass(c_type) != .Builtin) return false;
+ const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type);
+ return switch (ZigClangBuiltinType_getKind(builtin_ty)) {
+ .LongLong, .ULongLong, .Int128, .UInt128 => true,
+ else => false,
+ };
+}
fn transCreateNodeAssign(
rp: RestorePoint,
scope: *Scope,
test/run_translated_c.zig
@@ -149,4 +149,24 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ cases.add("cast signed array index to unsigned",
+ \\#include <stdlib.h>
+ \\int main(int argc, char **argv) {
+ \\ int a[10], i = 0;
+ \\ a[i] = 0;
+ \\ if (a[i] != 0) abort();
+ \\ return 0;
+ \\}
+ , "");
+
+ cases.add("cast long long array index to unsigned",
+ \\#include <stdlib.h>
+ \\int main(int argc, char **argv) {
+ \\ long long a[10], i = 0;
+ \\ a[i] = 0;
+ \\ if (a[i] != 0) abort();
+ \\ return 0;
+ \\}
+ , "");
}
test/translate_c.zig
@@ -1843,12 +1843,51 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub export var array: [100]c_int = .{0} ** 100;
\\pub export fn foo(arg_index: c_int) c_int {
\\ var index = arg_index;
- \\ return array[index];
+ \\ return array[@intCast(c_uint, index)];
\\}
,
\\pub const ACCESS = array[2];
});
+ cases.add("cast signed array index to unsigned",
+ \\void foo() {
+ \\ int a[10], i = 0;
+ \\ a[i] = 0;
+ \\}
+ , &[_][]const u8{
+ \\pub export fn foo() void {
+ \\ var a: [10]c_int = undefined;
+ \\ var i: c_int = 0;
+ \\ a[@intCast(c_uint, i)] = 0;
+ \\}
+ });
+
+ cases.add("long long array index cast to usize",
+ \\void foo() {
+ \\ long long a[10], i = 0;
+ \\ a[i] = 0;
+ \\}
+ , &[_][]const u8{
+ \\pub export fn foo() void {
+ \\ var a: [10]c_longlong = undefined;
+ \\ var i: c_longlong = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0)));
+ \\ a[@intCast(usize, i)] = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0)));
+ \\}
+ });
+
+ cases.add("unsigned array index skips cast",
+ \\void foo() {
+ \\ unsigned int a[10], i = 0;
+ \\ a[i] = 0;
+ \\}
+ , &[_][]const u8{
+ \\pub export fn foo() void {
+ \\ var a: [10]c_uint = undefined;
+ \\ var i: c_uint = @bitCast(c_uint, @as(c_int, 0));
+ \\ a[i] = @bitCast(c_uint, @as(c_int, 0));
+ \\}
+ });
+
cases.add("macro call",
\\#define CALL(arg) bar(arg)
, &[_][]const u8{