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(
32683268 const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);
32693269 const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);
32703270 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 };
32723279 if (used == .unused) {
32733280 // common case
32743281 // c: lhs += rhs
......@@ -3295,15 +3302,18 @@ fn transCreateCompoundAssign(
32953302
32963303 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
32973304 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)
32993306 try transExprCoercing(rp, scope, rhs, .used, .r_value)
33003307 else
33013308 try transExpr(rp, scope, rhs, .used, .r_value);
33023309
3303 if (is_shift) {
3310 if (is_shift or requires_int_cast) {
33043311 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
3305 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
3306 cast_node.params()[0] = rhs_type;
3312 const cast_to_type = if (is_shift)
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;
33073317 _ = try appendToken(rp.c, .Comma, ",");
33083318 cast_node.params()[1] = rhs_node;
33093319 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
......@@ -3358,10 +3368,13 @@ fn transCreateCompoundAssign(
33583368 const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
33593369 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
33603370
3361 if (is_shift) {
3371 if (is_shift or requires_int_cast) {
33623372 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
3363 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
3364 cast_node.params()[0] = rhs_type;
3373 const cast_to_type = if (is_shift)
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;
33653378 _ = try appendToken(rp.c, .Comma, ",");
33663379 cast_node.params()[1] = rhs_node;
33673380 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 {
268268 \\ if (count != 4) abort();
269269 \\ return 0;
270270 \\}
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 , "");
272344}