Commit 70cc1751ca
Changed files (2)
src-self-hosted
src-self-hosted/translate_c.zig
@@ -3268,7 +3268,14 @@ fn transCreateCompoundAssign(
const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);
const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);
const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);
- const is_signed = cIsSignedInteger(getExprQualType(rp.c, lhs));
+ const lhs_qt = getExprQualType(rp.c, lhs);
+ const rhs_qt = getExprQualType(rp.c, rhs);
+ const is_signed = cIsSignedInteger(lhs_qt);
+ const requires_int_cast = blk: {
+ const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt);
+ const are_same_sign = cIsSignedInteger(lhs_qt) == cIsSignedInteger(rhs_qt);
+ break :blk are_integers and !are_same_sign;
+ };
if (used == .unused) {
// common case
// c: lhs += rhs
@@ -3295,15 +3302,18 @@ fn transCreateCompoundAssign(
const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
- var rhs_node = if (is_shift)
+ var rhs_node = if (is_shift or requires_int_cast)
try transExprCoercing(rp, scope, rhs, .used, .r_value)
else
try transExpr(rp, scope, rhs, .used, .r_value);
- if (is_shift) {
+ if (is_shift or requires_int_cast) {
const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
- const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
- cast_node.params()[0] = rhs_type;
+ const cast_to_type = if (is_shift)
+ try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc)
+ else
+ try transQualType(rp, getExprQualType(rp.c, lhs), loc);
+ cast_node.params()[0] = cast_to_type;
_ = try appendToken(rp.c, .Comma, ",");
cast_node.params()[1] = rhs_node;
cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
@@ -3358,10 +3368,13 @@ fn transCreateCompoundAssign(
const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
- if (is_shift) {
+ if (is_shift or requires_int_cast) {
const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
- const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
- cast_node.params()[0] = rhs_type;
+ const cast_to_type = if (is_shift)
+ try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc)
+ else
+ try transQualType(rp, getExprQualType(rp.c, lhs), loc);
+ cast_node.params()[0] = cast_to_type;
_ = try appendToken(rp.c, .Comma, ",");
cast_node.params()[1] = rhs_node;
cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
test/run_translated_c.zig
@@ -268,5 +268,77 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ if (count != 4) abort();
\\ return 0;
\\}
- ,"");
+ , "");
+
+ cases.add("array value type casts properly",
+ \\#include <stdlib.h>
+ \\unsigned int choose[53][10];
+ \\static int hash_binary(int k)
+ \\{
+ \\ choose[0][k] = 3;
+ \\ int sum = 0;
+ \\ sum += choose[0][k];
+ \\ return sum;
+ \\}
+ \\
+ \\int main() {
+ \\ int s = hash_binary(4);
+ \\ if (s != 3) abort();
+ \\ return 0;
+ \\}
+ , "");
+
+ cases.add("array value type casts properly use +=",
+ \\#include <stdlib.h>
+ \\static int hash_binary(int k)
+ \\{
+ \\ unsigned int choose[1][1] = {{3}};
+ \\ int sum = -1;
+ \\ int prev = 0;
+ \\ prev = sum += choose[0][0];
+ \\ if (sum != 2) abort();
+ \\ return sum + prev;
+ \\}
+ \\
+ \\int main() {
+ \\ int x = hash_binary(4);
+ \\ if (x != 4) abort();
+ \\ return 0;
+ \\}
+ , "");
+
+ cases.add("ensure array casts outisde +=",
+ \\#include <stdlib.h>
+ \\static int hash_binary(int k)
+ \\{
+ \\ unsigned int choose[3] = {1, 2, 3};
+ \\ int sum = -2;
+ \\ int prev = sum + choose[k];
+ \\ if (prev != 0) abort();
+ \\ return sum + prev;
+ \\}
+ \\
+ \\int main() {
+ \\ int x = hash_binary(1);
+ \\ if (x != -2) abort();
+ \\ return 0;
+ \\}
+ , "");
+
+ cases.add("array cast int to uint",
+ \\#include <stdlib.h>
+ \\static unsigned int hash_binary(int k)
+ \\{
+ \\ int choose[3] = {-1, -2, 3};
+ \\ unsigned int sum = 2;
+ \\ sum += choose[k];
+ \\ return sum;
+ \\}
+ \\
+ \\int main() {
+ \\ unsigned int x = hash_binary(1);
+ \\ if (x != 0) abort();
+ \\ return 0;
+ \\}
+ , "");
}