authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 13:30:34+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 13:32:19+02:00
log62bfff5e8774413856d0c548f0fd73a4b5134f7f
tree0283bf0ea4ea0d679125327ecdfaef532d7b8061
parentf54e7d6c99b6fbeedcaf91e643e4e3a02e8f1d81
signature Commit is signed but in an unrecognized format.

translate-c-2 fix expression grouping bugs


3 files changed, 88 insertions(+), 66 deletions(-)

lib/std/zig/render.zig+1-1
......@@ -1629,7 +1629,7 @@ fn renderExpression(
16291629 .If => {
16301630 const if_node = @fieldParentPtr(ast.Node.If, "base", base);
16311631
1632 const lparen = tree.prevToken(if_node.condition.firstToken());
1632 const lparen = tree.nextToken(if_node.if_token);
16331633 const rparen = tree.nextToken(if_node.condition.lastToken());
16341634
16351635 try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if
src-self-hosted/translate_c.zig+35-26
......@@ -954,13 +954,6 @@ fn transBinaryOperator(
954954 }
955955 const lhs_node = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
956956 switch (op) {
957 .PtrMemD, .PtrMemI, .Cmp => return revertAndWarn(
958 rp,
959 error.UnsupportedTranslation,
960 ZigClangBinaryOperator_getBeginLoc(stmt),
961 "TODO: handle more C binary operators: {}",
962 .{op},
963 ),
964957 .Add => {
965958 if (cIsUnsignedInteger(qt)) {
966959 op_token = try appendToken(rp.c, .PlusPercent, "+%");
......@@ -1205,6 +1198,26 @@ fn transBoolExpr(
12051198 undefined;
12061199 var res = try transExpr(rp, scope, expr, used, lrvalue);
12071200
1201 if (isBoolRes(res))
1202 return res;
1203 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
1204 const node = try finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used);
1205
1206 if (grouped) {
1207 const rparen = try appendToken(rp.c, .RParen, ")");
1208 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
1209 grouped_expr.* = .{
1210 .lparen = lparen,
1211 .expr = node,
1212 .rparen = rparen,
1213 };
1214 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
1215 } else {
1216 return maybeSuppressResult(rp, scope, used, node);
1217 }
1218}
1219
1220fn isBoolRes(res: *ast.Node) bool {
12081221 switch (res.id) {
12091222 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
12101223 .BoolOr,
......@@ -1215,23 +1228,20 @@ fn transBoolExpr(
12151228 .GreaterThan,
12161229 .LessOrEqual,
12171230 .GreaterOrEqual,
1218 => return res,
1231 => return true,
12191232
12201233 else => {},
12211234 },
1222
12231235 .PrefixOp => switch (@fieldParentPtr(ast.Node.PrefixOp, "base", res).op) {
1224 .BoolNot => return res,
1236 .BoolNot => return true,
12251237
12261238 else => {},
12271239 },
1228
1229 .BoolLiteral => return res,
1230
1240 .BoolLiteral => return true,
1241 .GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr),
12311242 else => {},
12321243 }
1233 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
1234 return finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used, grouped);
1244 return false;
12351245}
12361246
12371247fn finishBoolExpr(
......@@ -1241,14 +1251,13 @@ fn finishBoolExpr(
12411251 ty: *const ZigClangType,
12421252 node: *ast.Node,
12431253 used: ResultUsed,
1244 grouped: bool,
12451254) TransError!*ast.Node {
12461255 switch (ZigClangType_getTypeClass(ty)) {
12471256 .Builtin => {
12481257 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
12491258
12501259 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
1251 .Bool,
1260 .Bool => return node,
12521261 .Char_U,
12531262 .UChar,
12541263 .Char_S,
......@@ -1276,12 +1285,12 @@ fn finishBoolExpr(
12761285 => {
12771286 const op_token = try appendToken(rp.c, .BangEqual, "!=");
12781287 const rhs_node = try transCreateNodeInt(rp.c, 0);
1279 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);
1288 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
12801289 },
12811290 .NullPtr => {
12821291 const op_token = try appendToken(rp.c, .EqualEqual, "==");
12831292 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1284 return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, grouped);
1293 return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, false);
12851294 },
12861295 else => {},
12871296 }
......@@ -1289,13 +1298,13 @@ fn finishBoolExpr(
12891298 .Pointer => {
12901299 const op_token = try appendToken(rp.c, .BangEqual, "!=");
12911300 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1292 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);
1301 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
12931302 },
12941303 .Typedef => {
12951304 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
12961305 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
12971306 const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
1298 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(underlying_type), node, used, grouped);
1307 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(underlying_type), node, used);
12991308 },
13001309 .Enum => {
13011310 const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
......@@ -1305,12 +1314,12 @@ fn finishBoolExpr(
13051314
13061315 const op_token = try appendToken(rp.c, .BangEqual, "!=");
13071316 const rhs_node = try transCreateNodeInt(rp.c, 0);
1308 return transCreateNodeInfixOp(rp, scope, &builtin_node.base, .BangEqual, op_token, rhs_node, used, grouped);
1317 return transCreateNodeInfixOp(rp, scope, &builtin_node.base, .BangEqual, op_token, rhs_node, used, false);
13091318 },
13101319 .Elaborated => {
13111320 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
13121321 const named_type = ZigClangElaboratedType_getNamedType(elaborated_ty);
1313 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(named_type), node, used, grouped);
1322 return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(named_type), node, used);
13141323 },
13151324 else => {},
13161325 }
......@@ -2009,8 +2018,8 @@ fn transFloatingLiteral(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangFl
20092018}
20102019
20112020fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangConditionalOperator, used: ResultUsed) TransError!*ast.Node {
2012 const gropued = scope.id == .Condition;
2013 const lparen = if (gropued) try appendToken(rp.c, .LParen, "(") else undefined;
2021 const grouped = scope.id == .Condition;
2022 const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;
20142023 const if_node = try transCreateNodeIf(rp.c);
20152024 var cond_scope = Scope{
20162025 .parent = scope,
......@@ -2029,7 +2038,7 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla
20292038 if_node.@"else" = try transCreateNodeElse(rp.c);
20302039 if_node.@"else".?.body = try transExpr(rp, scope, false_expr, .used, .r_value);
20312040
2032 if (gropued) {
2041 if (grouped) {
20332042 const rparen = try appendToken(rp.c, .RParen, ")");
20342043 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
20352044 grouped_expr.* = .{
test/translate_c.zig+52-39
......@@ -1400,17 +1400,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14001400 \\pub const Bar = enum_Bar;
14011401 });
14021402
1403 cases.add_2("bitwise binary operators, simpler parens", // TODO can combine with "bitwise binary operators" when parens are correctly preserved/not added in translate-c-2
1403 cases.add_2("bitwise binary operators, simpler parens",
14041404 \\int max(int a, int b) {
1405 \\ int c = (a & b);
1406 \\ int d = (a | b);
1407 \\ return (c ^ d);
1405 \\ return (a & b) ^ (a | b);
14081406 \\}
14091407 , &[_][]const u8{
14101408 \\pub export fn max(a: c_int, b: c_int) c_int {
1411 \\ var c: c_int = (a & b);
1412 \\ var d: c_int = (a | b);
1413 \\ return (c ^ d);
1409 \\ return ((a & b) ^ (a | b));
14141410 \\}
14151411 });
14161412
......@@ -1438,17 +1434,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14381434 \\}
14391435 });
14401436
1441 cases.add_2("==, !=, no if", // TODO remove this test after `if` conversion supported, and switch "==, !=" to addC_both
1437 cases.add_2("==, !=",
14421438 \\int max(int a, int b) {
1443 \\ int c = (a == b);
1444 \\ int d = (a != b);
1445 \\ return (c != d);
1439 \\ if (a == b)
1440 \\ return a;
1441 \\ if (a != b)
1442 \\ return b;
1443 \\ return a;
14461444 \\}
14471445 , &[_][]const u8{
14481446 \\pub export fn max(a: c_int, b: c_int) c_int {
1449 \\ var c: c_int = (a == b);
1450 \\ var d: c_int = (a != b);
1451 \\ return (c != d);
1447 \\ if ((a == b)) return a;
1448 \\ if ((a != b)) return b;
1449 \\ return a;
14521450 \\}
14531451 });
14541452
......@@ -1464,6 +1462,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14641462 \\}
14651463 });
14661464
1465 cases.add_2("typedeffed bool expression",
1466 \\typedef char* yes;
1467 \\void foo(void) {
1468 \\ yes a;
1469 \\ if (a) 2;
1470 \\}
1471 , &[_][]const u8{
1472 \\pub const yes = [*c]u8;
1473 \\pub export fn foo() void {
1474 \\ var a: yes = undefined;
1475 \\ if (a != null) _ = 2;
1476 \\}
1477 });
1478
14671479 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
14681480
14691481 cases.addAllowWarnings("simple data types",
......@@ -1575,31 +1587,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15751587 \\}
15761588 });
15771589
1578 cases.addC("==, !=",
1579 \\int max(int a, int b) {
1580 \\ if (a == b)
1581 \\ return a;
1582 \\ if (a != b)
1583 \\ return b;
1584 \\ return a;
1585 \\}
1586 , &[_][]const u8{
1587 \\pub export fn max(a: c_int, b: c_int) c_int {
1588 \\ if (a == b) return a;
1589 \\ if (a != b) return b;
1590 \\ return a;
1591 \\}
1592 });
1593 cases.addC("bitwise binary operators",
1594 \\int max(int a, int b) {
1595 \\ return (a & b) ^ (a | b);
1596 \\}
1597 , &[_][]const u8{
1598 \\pub export fn max(a: c_int, b: c_int) c_int {
1599 \\ return (a & b) ^ (a | b);
1600 \\}
1601 });
1602
16031590 cases.addC("logical and, logical or",
16041591 \\int max(int a, int b) {
16051592 \\ if (a < b || a == b)
......@@ -2596,4 +2583,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
25962583 \\ }
25972584 \\}
25982585 });
2586
2587 cases.addC("==, !=",
2588 \\int max(int a, int b) {
2589 \\ if (a == b)
2590 \\ return a;
2591 \\ if (a != b)
2592 \\ return b;
2593 \\ return a;
2594 \\}
2595 , &[_][]const u8{
2596 \\pub export fn max(a: c_int, b: c_int) c_int {
2597 \\ if (a == b) return a;
2598 \\ if (a != b) return b;
2599 \\ return a;
2600 \\}
2601 });
2602
2603 cases.addC("bitwise binary operators",
2604 \\int max(int a, int b) {
2605 \\ return (a & b) ^ (a | b);
2606 \\}
2607 , &[_][]const u8{
2608 \\pub export fn max(a: c_int, b: c_int) c_int {
2609 \\ return (a & b) ^ (a | b);
2610 \\}
2611 });
25992612}