| author | |
| committer | |
| log | 70cc1751ca69dd77625c703445713d067215b5d9 |
| tree | 2cf83a064f93a958055b4f0e5278586a77260204 |
| parent | 8b82c40104802c9351b30ef7c5a41e7829ab6d2a |
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 type2 files changed, 94 insertions(+), 9 deletions(-)
src-self-hosted/translate_c.zig+21-8| ... | ... | @@ -3268,7 +3268,14 @@ fn transCreateCompoundAssign( |
| 3268 | 3268 | const lhs = ZigClangCompoundAssignOperator_getLHS(stmt); |
| 3269 | 3269 | const rhs = ZigClangCompoundAssignOperator_getRHS(stmt); |
| 3270 | 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 | 3279 | if (used == .unused) { |
| 3273 | 3280 | // common case |
| 3274 | 3281 | // c: lhs += rhs |
| ... | ... | @@ -3295,15 +3302,18 @@ fn transCreateCompoundAssign( |
| 3295 | 3302 | |
| 3296 | 3303 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); |
| 3297 | 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 | 3306 | try transExprCoercing(rp, scope, rhs, .used, .r_value) |
| 3300 | 3307 | else |
| 3301 | 3308 | try transExpr(rp, scope, rhs, .used, .r_value); |
| 3302 | 3309 | |
| 3303 | if (is_shift) { | |
| 3310 | if (is_shift or requires_int_cast) { | |
| 3304 | 3311 | 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; | |
| 3307 | 3317 | _ = try appendToken(rp.c, .Comma, ","); |
| 3308 | 3318 | cast_node.params()[1] = rhs_node; |
| 3309 | 3319 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| ... | ... | @@ -3358,10 +3368,13 @@ fn transCreateCompoundAssign( |
| 3358 | 3368 | const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes); |
| 3359 | 3369 | var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); |
| 3360 | 3370 | |
| 3361 | if (is_shift) { | |
| 3371 | if (is_shift or requires_int_cast) { | |
| 3362 | 3372 | 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; | |
| 3365 | 3378 | _ = try appendToken(rp.c, .Comma, ","); |
| 3366 | 3379 | cast_node.params()[1] = rhs_node; |
| 3367 | 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 | 268 | \\ if (count != 4) abort(); |
| 269 | 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 | } |