authorgravatar for ian.simonson@protonmail.comIan Simonson <ian.simonson@protonmail.com> 2020-04-30 08:38:36+10:00
committergravatar for ian.simonson@protonmail.comIan Simonson <ian.simonson@protonmail.com> 2020-04-30 12:48:27+10:00
loge6fa0beb335ad8ecff005fef924c2a39ed748c56
tree51d8dbed193e84d0c0e5843be5acf35ce141b359
parenta08675723cd39e3001327aa52b8af4b1c7bb0f32

Translate-C convert bools to int in complex expressions

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 int

2 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 }
12941294
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}
12981328
1299fn transCompoundStmtInline(1329fn 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}