authorgravatar for ian.simonson@protonmail.comIan Simonson <ian.simonson@protonmail.com> 2020-06-24 19:04:56+10:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-07-02 14:05:12+00:00
log70cc1751ca69dd77625c703445713d067215b5d9
tree2cf83a064f93a958055b4f0e5278586a77260204
parent8b82c40104802c9351b30ef7c5a41e7829ab6d2a

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

2 files changed, 94 insertions(+), 9 deletions(-)

src-self-hosted/translate_c.zig+21-8
...@@ -3268,7 +3268,14 @@ fn transCreateCompoundAssign(...@@ -3268,7 +3268,14 @@ fn transCreateCompoundAssign(
3268 const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);3268 const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);
3269 const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);3269 const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);
3270 const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);3270 const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);
3271 const is_signed = cIsSignedInteger(getExprQualType(rp.c, lhs));3271 const lhs_qt = getExprQualType(rp.c, lhs);
3272 const rhs_qt = getExprQualType(rp.c, rhs);
3273 const is_signed = cIsSignedInteger(lhs_qt);
3274 const requires_int_cast = blk: {
3275 const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt);
3276 const are_same_sign = cIsSignedInteger(lhs_qt) == cIsSignedInteger(rhs_qt);
3277 break :blk are_integers and !are_same_sign;
3278 };
3272 if (used == .unused) {3279 if (used == .unused) {
3273 // common case3280 // common case
3274 // c: lhs += rhs3281 // c: lhs += rhs
...@@ -3295,15 +3302,18 @@ fn transCreateCompoundAssign(...@@ -3295,15 +3302,18 @@ fn transCreateCompoundAssign(
32953302
3296 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);3303 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
3297 const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);3304 const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
3298 var rhs_node = if (is_shift)3305 var rhs_node = if (is_shift or requires_int_cast)
3299 try transExprCoercing(rp, scope, rhs, .used, .r_value)3306 try transExprCoercing(rp, scope, rhs, .used, .r_value)
3300 else3307 else
3301 try transExpr(rp, scope, rhs, .used, .r_value);3308 try transExpr(rp, scope, rhs, .used, .r_value);
33023309
3303 if (is_shift) {3310 if (is_shift or requires_int_cast) {
3304 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);3311 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
3305 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);3312 const cast_to_type = if (is_shift)
3306 cast_node.params()[0] = rhs_type;3313 try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc)
3314 else
3315 try transQualType(rp, getExprQualType(rp.c, lhs), loc);
3316 cast_node.params()[0] = cast_to_type;
3307 _ = try appendToken(rp.c, .Comma, ",");3317 _ = try appendToken(rp.c, .Comma, ",");
3308 cast_node.params()[1] = rhs_node;3318 cast_node.params()[1] = rhs_node;
3309 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");3319 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
...@@ -3358,10 +3368,13 @@ fn transCreateCompoundAssign(...@@ -3358,10 +3368,13 @@ fn transCreateCompoundAssign(
3358 const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);3368 const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
3359 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);3369 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
33603370
3361 if (is_shift) {3371 if (is_shift or requires_int_cast) {
3362 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);3372 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
3363 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);3373 const cast_to_type = if (is_shift)
3364 cast_node.params()[0] = rhs_type;3374 try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc)
3375 else
3376 try transQualType(rp, getExprQualType(rp.c, lhs), loc);
3377 cast_node.params()[0] = cast_to_type;
3365 _ = try appendToken(rp.c, .Comma, ",");3378 _ = try appendToken(rp.c, .Comma, ",");
3366 cast_node.params()[1] = rhs_node;3379 cast_node.params()[1] = rhs_node;
3367 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");3380 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
test/run_translated_c.zig+73-1
...@@ -268,5 +268,77 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -268,5 +268,77 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
268 \\ if (count != 4) abort();268 \\ if (count != 4) abort();
269 \\ return 0;269 \\ return 0;
270 \\}270 \\}
271 ,"");271 , "");
272
273 cases.add("array value type casts properly",
274 \\#include <stdlib.h>
275 \\unsigned int choose[53][10];
276 \\static int hash_binary(int k)
277 \\{
278 \\ choose[0][k] = 3;
279 \\ int sum = 0;
280 \\ sum += choose[0][k];
281 \\ return sum;
282 \\}
283 \\
284 \\int main() {
285 \\ int s = hash_binary(4);
286 \\ if (s != 3) abort();
287 \\ return 0;
288 \\}
289 , "");
290
291 cases.add("array value type casts properly use +=",
292 \\#include <stdlib.h>
293 \\static int hash_binary(int k)
294 \\{
295 \\ unsigned int choose[1][1] = {{3}};
296 \\ int sum = -1;
297 \\ int prev = 0;
298 \\ prev = sum += choose[0][0];
299 \\ if (sum != 2) abort();
300 \\ return sum + prev;
301 \\}
302 \\
303 \\int main() {
304 \\ int x = hash_binary(4);
305 \\ if (x != 4) abort();
306 \\ return 0;
307 \\}
308 , "");
309
310 cases.add("ensure array casts outisde +=",
311 \\#include <stdlib.h>
312 \\static int hash_binary(int k)
313 \\{
314 \\ unsigned int choose[3] = {1, 2, 3};
315 \\ int sum = -2;
316 \\ int prev = sum + choose[k];
317 \\ if (prev != 0) abort();
318 \\ return sum + prev;
319 \\}
320 \\
321 \\int main() {
322 \\ int x = hash_binary(1);
323 \\ if (x != -2) abort();
324 \\ return 0;
325 \\}
326 , "");
327
328 cases.add("array cast int to uint",
329 \\#include <stdlib.h>
330 \\static unsigned int hash_binary(int k)
331 \\{
332 \\ int choose[3] = {-1, -2, 3};
333 \\ unsigned int sum = 2;
334 \\ sum += choose[k];
335 \\ return sum;
336 \\}
337 \\
338 \\int main() {
339 \\ unsigned int x = hash_binary(1);
340 \\ if (x != 0) abort();
341 \\ return 0;
342 \\}
343 , "");
272}344}