Translate-c fix rhs not cast on array access

Closes #5671. Checks if the rhs is integral and of
differing or the same signedness. If they are different
does an @intCast to the lhs type
This commit is contained in:
Ian Simonson 2020-06-24 19:04:56 +10:00 committed by Veikka Tuominen
parent 8b82c40104
commit 70cc1751ca
2 changed files with 94 additions and 9 deletions

View File

@ -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, ")");

View File

@ -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;
\\}
, "");
}