| 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 | 1293 | } |
| 1294 | 1294 | |
| 1295 | 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 | 1329 | fn transCompoundStmtInline( |
test/run_translated_c.zig+48| ... | ... | @@ -195,4 +195,52 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 195 | 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 | } |