| author | |
| committer | |
| log | 3f98756f8542e5ca6b45322f17eb59b74706fb62 |
| tree | 609251a690623f262f5657b7cd649bd7cccb0e9d |
| parent | ae324985a67b1258c226a799f2680906686670f2 |
* cast only if the index is long long or signed
* cast long long to usize rather than c_uint
closes #40753 files changed, 90 insertions(+), 3 deletions(-)
src-self-hosted/translate_c.zig+30-2| ... | ... | @@ -2577,8 +2577,27 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArrayS |
| 2577 | 2577 | |
| 2578 | 2578 | const container_node = try transExpr(rp, scope, base_stmt, .used, .r_value); |
| 2579 | 2579 | const node = try transCreateNodeArrayAccess(rp.c, container_node); |
| 2580 | node.op.ArrayAccess = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getIdx(stmt), .used, .r_value); | |
| 2581 | node.rtoken = try appendToken(rp.c, .RBrace, "]"); | |
| 2580 | ||
| 2581 | // cast if the index is long long or signed | |
| 2582 | const subscr_expr = ZigClangArraySubscriptExpr_getIdx(stmt); | |
| 2583 | const qt = getExprQualType(rp.c, subscr_expr); | |
| 2584 | const is_longlong = cIsLongLongInteger(qt); | |
| 2585 | const is_signed = cIsSignedInteger(qt); | |
| 2586 | ||
| 2587 | if (is_longlong or is_signed) { | |
| 2588 | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast"); | |
| 2589 | // check if long long first so that signed long long doesn't just become unsigned long long | |
| 2590 | var typeid_node = if (is_longlong) try transCreateNodeIdentifier(rp.c, "usize") else try transQualTypeIntWidthOf(rp.c, qt, false); | |
| 2591 | try cast_node.params.push(typeid_node); | |
| 2592 | _ = try appendToken(rp.c, .Comma, ","); | |
| 2593 | try cast_node.params.push(try transExpr(rp, scope, subscr_expr, .used, .r_value)); | |
| 2594 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | |
| 2595 | node.rtoken = try appendToken(rp.c, .RBrace, "]"); | |
| 2596 | node.op.ArrayAccess = &cast_node.base; | |
| 2597 | } else { | |
| 2598 | node.op.ArrayAccess = try transExpr(rp, scope, subscr_expr, .used, .r_value); | |
| 2599 | node.rtoken = try appendToken(rp.c, .RBrace, "]"); | |
| 2600 | } | |
| 2582 | 2601 | return maybeSuppressResult(rp, scope, result_used, &node.base); |
| 2583 | 2602 | } |
| 2584 | 2603 | |
| ... | ... | @@ -3528,6 +3547,15 @@ fn cIsFloating(qt: ZigClangQualType) bool { |
| 3528 | 3547 | }; |
| 3529 | 3548 | } |
| 3530 | 3549 | |
| 3550 | fn cIsLongLongInteger(qt: ZigClangQualType) bool { | |
| 3551 | const c_type = qualTypeCanon(qt); | |
| 3552 | if (ZigClangType_getTypeClass(c_type) != .Builtin) return false; | |
| 3553 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type); | |
| 3554 | return switch (ZigClangBuiltinType_getKind(builtin_ty)) { | |
| 3555 | .LongLong, .ULongLong, .Int128, .UInt128 => true, | |
| 3556 | else => false, | |
| 3557 | }; | |
| 3558 | } | |
| 3531 | 3559 | fn transCreateNodeAssign( |
| 3532 | 3560 | rp: RestorePoint, |
| 3533 | 3561 | scope: *Scope, |
test/run_translated_c.zig+20| ... | ... | @@ -149,4 +149,24 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 149 | 149 | \\ return 0; |
| 150 | 150 | \\} |
| 151 | 151 | , ""); |
| 152 | ||
| 153 | cases.add("cast signed array index to unsigned", | |
| 154 | \\#include <stdlib.h> | |
| 155 | \\int main(int argc, char **argv) { | |
| 156 | \\ int a[10], i = 0; | |
| 157 | \\ a[i] = 0; | |
| 158 | \\ if (a[i] != 0) abort(); | |
| 159 | \\ return 0; | |
| 160 | \\} | |
| 161 | , ""); | |
| 162 | ||
| 163 | cases.add("cast long long array index to unsigned", | |
| 164 | \\#include <stdlib.h> | |
| 165 | \\int main(int argc, char **argv) { | |
| 166 | \\ long long a[10], i = 0; | |
| 167 | \\ a[i] = 0; | |
| 168 | \\ if (a[i] != 0) abort(); | |
| 169 | \\ return 0; | |
| 170 | \\} | |
| 171 | , ""); | |
| 152 | 172 | } |
test/translate_c.zig+40-1| ... | ... | @@ -1843,12 +1843,51 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1843 | 1843 | \\pub export var array: [100]c_int = .{0} ** 100; |
| 1844 | 1844 | \\pub export fn foo(arg_index: c_int) c_int { |
| 1845 | 1845 | \\ var index = arg_index; |
| 1846 | \\ return array[index]; | |
| 1846 | \\ return array[@intCast(c_uint, index)]; | |
| 1847 | 1847 | \\} |
| 1848 | 1848 | , |
| 1849 | 1849 | \\pub const ACCESS = array[2]; |
| 1850 | 1850 | }); |
| 1851 | 1851 | |
| 1852 | cases.add("cast signed array index to unsigned", | |
| 1853 | \\void foo() { | |
| 1854 | \\ int a[10], i = 0; | |
| 1855 | \\ a[i] = 0; | |
| 1856 | \\} | |
| 1857 | , &[_][]const u8{ | |
| 1858 | \\pub export fn foo() void { | |
| 1859 | \\ var a: [10]c_int = undefined; | |
| 1860 | \\ var i: c_int = 0; | |
| 1861 | \\ a[@intCast(c_uint, i)] = 0; | |
| 1862 | \\} | |
| 1863 | }); | |
| 1864 | ||
| 1865 | cases.add("long long array index cast to usize", | |
| 1866 | \\void foo() { | |
| 1867 | \\ long long a[10], i = 0; | |
| 1868 | \\ a[i] = 0; | |
| 1869 | \\} | |
| 1870 | , &[_][]const u8{ | |
| 1871 | \\pub export fn foo() void { | |
| 1872 | \\ var a: [10]c_longlong = undefined; | |
| 1873 | \\ var i: c_longlong = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0))); | |
| 1874 | \\ a[@intCast(usize, i)] = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0))); | |
| 1875 | \\} | |
| 1876 | }); | |
| 1877 | ||
| 1878 | cases.add("unsigned array index skips cast", | |
| 1879 | \\void foo() { | |
| 1880 | \\ unsigned int a[10], i = 0; | |
| 1881 | \\ a[i] = 0; | |
| 1882 | \\} | |
| 1883 | , &[_][]const u8{ | |
| 1884 | \\pub export fn foo() void { | |
| 1885 | \\ var a: [10]c_uint = undefined; | |
| 1886 | \\ var i: c_uint = @bitCast(c_uint, @as(c_int, 0)); | |
| 1887 | \\ a[i] = @bitCast(c_uint, @as(c_int, 0)); | |
| 1888 | \\} | |
| 1889 | }); | |
| 1890 | ||
| 1852 | 1891 | cases.add("macro call", |
| 1853 | 1892 | \\#define CALL(arg) bar(arg) |
| 1854 | 1893 | , &[_][]const u8{ |