| author | |
| committer | |
| log | e6fa0beb335ad8ecff005fef924c2a39ed748c56 |
| tree | 51d8dbed193e84d0c0e5843be5acf35ce141b359 |
| parent | a08675723cd39e3001327aa52b8af4b1c7bb0f32 |
Pre-requisite for having a test case for #5062
In complex C statements which are outside of macros,
it is valid C to perform e.g. a bitor between an
integer and a boolean `5 | (8 == 9)`
Currently this results in a zig error after translating
as `c_int | bool` is invalid Zig.
Detects if a sub-expression of a numeric operator is
boolean and if so converts it to int2 files changed, 79 insertions(+), 1 deletions(-)
src-self-hosted/translate_c.zig+31-1| ... | @@ -1293,7 +1293,37 @@ fn transBinaryOperator( | ... | @@ -1293,7 +1293,37 @@ fn transBinaryOperator( |
| 1293 | } | 1293 | } |
| 1294 | 1294 | ||
| 1295 | const rhs_node = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); | 1295 | const rhs_node = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); |
| 1296 | return transCreateNodeInfixOp(rp, scope, lhs_node, op_id, op_token, rhs_node, result_used, true); | 1296 | |
| 1297 | const is_lhs_bool = isBoolRes(lhs_node); | ||
| 1298 | const is_rhs_bool = isBoolRes(rhs_node); | ||
| 1299 | |||
| 1300 | if (!is_lhs_bool and !is_rhs_bool) { | ||
| 1301 | return transCreateNodeInfixOp(rp, scope, lhs_node, op_id, op_token, rhs_node, result_used, true); | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | const lhs = if (is_lhs_bool) init: { | ||
| 1305 | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt"); | ||
| 1306 | try cast_node.params.push(lhs_node); | ||
| 1307 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | ||
| 1308 | break :init &cast_node.base; | ||
| 1309 | } else lhs_node; | ||
| 1310 | |||
| 1311 | const rhs = if (is_rhs_bool) init: { | ||
| 1312 | const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt"); | ||
| 1313 | try cast_node.params.push(rhs_node); | ||
| 1314 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | ||
| 1315 | break :init &cast_node.base; | ||
| 1316 | } else rhs_node; | ||
| 1317 | |||
| 1318 | const node = try rp.c.a().create(ast.Node.InfixOp); | ||
| 1319 | |||
| 1320 | node.* = .{ | ||
| 1321 | .op_token = op_token, | ||
| 1322 | .lhs = lhs, | ||
| 1323 | .op = op_id, | ||
| 1324 | .rhs = rhs, | ||
| 1325 | }; | ||
| 1326 | return maybeSuppressResult(rp, scope, result_used, &node.base); | ||
| 1297 | } | 1327 | } |
| 1298 | 1328 | ||
| 1299 | fn transCompoundStmtInline( | 1329 | fn transCompoundStmtInline( |
test/run_translated_c.zig+48| ... | @@ -195,4 +195,52 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { | ... | @@ -195,4 +195,52 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 195 | \\ return 0; | 195 | \\ return 0; |
| 196 | \\} | 196 | \\} |
| 197 | , ""); | 197 | , ""); |
| 198 | |||
| 199 | cases.add("case boolean expression converted to int", | ||
| 200 | \\#include <stdlib.h> | ||
| 201 | \\int main(int argc, char **argv) { | ||
| 202 | \\ int value = 1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9; | ||
| 203 | \\ if (value != 4224) abort(); | ||
| 204 | \\ return 0; | ||
| 205 | \\} | ||
| 206 | , ""); | ||
| 207 | |||
| 208 | cases.add("case boolean expression on left converted to int", | ||
| 209 | \\#include <stdlib.h> | ||
| 210 | \\int main(int argc, char **argv) { | ||
| 211 | \\ int value = 8 == 9 | 1 + 2 * 3 + 4 * 5 + 6 << 7; | ||
| 212 | \\ if (value != 4224) abort(); | ||
| 213 | \\ return 0; | ||
| 214 | \\} | ||
| 215 | , ""); | ||
| 216 | |||
| 217 | cases.add("case boolean and operator+ converts bool to int", | ||
| 218 | \\#include <stdlib.h> | ||
| 219 | \\int main(int argc, char **argv) { | ||
| 220 | \\ int value = (8 == 9) + 3; | ||
| 221 | \\ int value2 = 3 + (8 == 9); | ||
| 222 | \\ if (value != value2) abort(); | ||
| 223 | \\ return 0; | ||
| 224 | \\} | ||
| 225 | , ""); | ||
| 226 | |||
| 227 | cases.add("case boolean and operator<", | ||
| 228 | \\#include <stdlib.h> | ||
| 229 | \\int main(int argc, char **argv) { | ||
| 230 | \\ int value = (8 == 9) < 3; | ||
| 231 | \\ if (value == 0) abort(); | ||
| 232 | \\ return 0; | ||
| 233 | \\} | ||
| 234 | , ""); | ||
| 235 | |||
| 236 | cases.add("case boolean and operator*", | ||
| 237 | \\#include <stdlib.h> | ||
| 238 | \\int main(int argc, char **argv) { | ||
| 239 | \\ int value = (8 == 9) * 3; | ||
| 240 | \\ int value2 = 3 * (9 == 9); | ||
| 241 | \\ if (value != 0) abort(); | ||
| 242 | \\ if (value2 == 0) abort(); | ||
| 243 | \\ return 0; | ||
| 244 | \\} | ||
| 245 | , ""); | ||
| 198 | } | 246 | } |