translate-c-2 fix expression grouping bugs
parent
f54e7d6c99
commit
62bfff5e87
|
@ -1629,7 +1629,7 @@ fn renderExpression(
|
|||
.If => {
|
||||
const if_node = @fieldParentPtr(ast.Node.If, "base", base);
|
||||
|
||||
const lparen = tree.prevToken(if_node.condition.firstToken());
|
||||
const lparen = tree.nextToken(if_node.if_token);
|
||||
const rparen = tree.nextToken(if_node.condition.lastToken());
|
||||
|
||||
try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if
|
||||
|
|
|
@ -954,13 +954,6 @@ fn transBinaryOperator(
|
|||
}
|
||||
const lhs_node = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
|
||||
switch (op) {
|
||||
.PtrMemD, .PtrMemI, .Cmp => return revertAndWarn(
|
||||
rp,
|
||||
error.UnsupportedTranslation,
|
||||
ZigClangBinaryOperator_getBeginLoc(stmt),
|
||||
"TODO: handle more C binary operators: {}",
|
||||
.{op},
|
||||
),
|
||||
.Add => {
|
||||
if (cIsUnsignedInteger(qt)) {
|
||||
op_token = try appendToken(rp.c, .PlusPercent, "+%");
|
||||
|
@ -1205,6 +1198,26 @@ fn transBoolExpr(
|
|||
undefined;
|
||||
var res = try transExpr(rp, scope, expr, used, lrvalue);
|
||||
|
||||
if (isBoolRes(res))
|
||||
return res;
|
||||
const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
|
||||
const node = try finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used);
|
||||
|
||||
if (grouped) {
|
||||
const rparen = try appendToken(rp.c, .RParen, ")");
|
||||
const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
|
||||
grouped_expr.* = .{
|
||||
.lparen = lparen,
|
||||
.expr = node,
|
||||
.rparen = rparen,
|
||||
};
|
||||
return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
|
||||
} else {
|
||||
return maybeSuppressResult(rp, scope, used, node);
|
||||
}
|
||||
}
|
||||
|
||||
fn isBoolRes(res: *ast.Node) bool {
|
||||
switch (res.id) {
|
||||
.InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
|
||||
.BoolOr,
|
||||
|
@ -1215,23 +1228,20 @@ fn transBoolExpr(
|
|||
.GreaterThan,
|
||||
.LessOrEqual,
|
||||
.GreaterOrEqual,
|
||||
=> return res,
|
||||
=> return true,
|
||||
|
||||
else => {},
|
||||
},
|
||||
|
||||
.PrefixOp => switch (@fieldParentPtr(ast.Node.PrefixOp, "base", res).op) {
|
||||
.BoolNot => return res,
|
||||
.BoolNot => return true,
|
||||
|
||||
else => {},
|
||||
},
|
||||
|
||||
.BoolLiteral => return res,
|
||||
|
||||
.BoolLiteral => return true,
|
||||
.GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr),
|
||||
else => {},
|
||||
}
|
||||
const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
|
||||
return finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used, grouped);
|
||||
return false;
|
||||
}
|
||||
|
||||
fn finishBoolExpr(
|
||||
|
@ -1241,14 +1251,13 @@ fn finishBoolExpr(
|
|||
ty: *const ZigClangType,
|
||||
node: *ast.Node,
|
||||
used: ResultUsed,
|
||||
grouped: bool,
|
||||
) TransError!*ast.Node {
|
||||
switch (ZigClangType_getTypeClass(ty)) {
|
||||
.Builtin => {
|
||||
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
|
||||
|
||||
switch (ZigClangBuiltinType_getKind(builtin_ty)) {
|
||||
.Bool,
|
||||
.Bool => return node,
|
||||
.Char_U,
|
||||
.UChar,
|
||||
.Char_S,
|
||||
|
@ -1276,12 +1285,12 @@ fn finishBoolExpr(
|
|||
=> {
|
||||
const op_token = try appendToken(rp.c, .BangEqual, "!=");
|
||||
const rhs_node = try transCreateNodeInt(rp.c, 0);
|
||||
return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);
|
||||
return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
|
||||
},
|
||||
.NullPtr => {
|
||||
const op_token = try appendToken(rp.c, .EqualEqual, "==");
|
||||
const rhs_node = try transCreateNodeNullLiteral(rp.c);
|
||||
return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, grouped);
|
||||
return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, false);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
@ -1289,13 +1298,13 @@ fn finishBoolExpr(
|
|||
.Pointer => {
|
||||
const op_token = try appendToken(rp.c, .BangEqual, "!=");
|
||||
const rhs_node = try transCreateNodeNullLiteral(rp.c);
|
||||
return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, grouped);
|
||||
return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
|
||||
},
|
||||
.Typedef => {
|
||||
const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
|
||||
const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
|
||||
const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
|
||||
return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(underlying_type), node, used, grouped);
|
||||
return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(underlying_type), node, used);
|
||||
},
|
||||
.Enum => {
|
||||
const enum_ty = @ptrCast(*const ZigClangEnumType, ty);
|
||||
|
@ -1305,12 +1314,12 @@ fn finishBoolExpr(
|
|||
|
||||
const op_token = try appendToken(rp.c, .BangEqual, "!=");
|
||||
const rhs_node = try transCreateNodeInt(rp.c, 0);
|
||||
return transCreateNodeInfixOp(rp, scope, &builtin_node.base, .BangEqual, op_token, rhs_node, used, grouped);
|
||||
return transCreateNodeInfixOp(rp, scope, &builtin_node.base, .BangEqual, op_token, rhs_node, used, false);
|
||||
},
|
||||
.Elaborated => {
|
||||
const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
|
||||
const named_type = ZigClangElaboratedType_getNamedType(elaborated_ty);
|
||||
return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(named_type), node, used, grouped);
|
||||
return finishBoolExpr(rp, scope, loc, ZigClangQualType_getTypePtr(named_type), node, used);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
@ -2009,8 +2018,8 @@ fn transFloatingLiteral(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangFl
|
|||
}
|
||||
|
||||
fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangConditionalOperator, used: ResultUsed) TransError!*ast.Node {
|
||||
const gropued = scope.id == .Condition;
|
||||
const lparen = if (gropued) try appendToken(rp.c, .LParen, "(") else undefined;
|
||||
const grouped = scope.id == .Condition;
|
||||
const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;
|
||||
const if_node = try transCreateNodeIf(rp.c);
|
||||
var cond_scope = Scope{
|
||||
.parent = scope,
|
||||
|
@ -2029,7 +2038,7 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla
|
|||
if_node.@"else" = try transCreateNodeElse(rp.c);
|
||||
if_node.@"else".?.body = try transExpr(rp, scope, false_expr, .used, .r_value);
|
||||
|
||||
if (gropued) {
|
||||
if (grouped) {
|
||||
const rparen = try appendToken(rp.c, .RParen, ")");
|
||||
const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
|
||||
grouped_expr.* = .{
|
||||
|
|
|
@ -1400,17 +1400,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\pub const Bar = enum_Bar;
|
||||
});
|
||||
|
||||
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
|
||||
cases.add_2("bitwise binary operators, simpler parens",
|
||||
\\int max(int a, int b) {
|
||||
\\ int c = (a & b);
|
||||
\\ int d = (a | b);
|
||||
\\ return (c ^ d);
|
||||
\\ return (a & b) ^ (a | b);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ var c: c_int = (a & b);
|
||||
\\ var d: c_int = (a | b);
|
||||
\\ return (c ^ d);
|
||||
\\ return ((a & b) ^ (a | b));
|
||||
\\}
|
||||
});
|
||||
|
||||
|
@ -1438,17 +1434,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("==, !=, no if", // TODO remove this test after `if` conversion supported, and switch "==, !=" to addC_both
|
||||
cases.add_2("==, !=",
|
||||
\\int max(int a, int b) {
|
||||
\\ int c = (a == b);
|
||||
\\ int d = (a != b);
|
||||
\\ return (c != d);
|
||||
\\ if (a == b)
|
||||
\\ return a;
|
||||
\\ if (a != b)
|
||||
\\ return b;
|
||||
\\ return a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ var c: c_int = (a == b);
|
||||
\\ var d: c_int = (a != b);
|
||||
\\ return (c != d);
|
||||
\\ if ((a == b)) return a;
|
||||
\\ if ((a != b)) return b;
|
||||
\\ return a;
|
||||
\\}
|
||||
});
|
||||
|
||||
|
@ -1464,6 +1462,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("typedeffed bool expression",
|
||||
\\typedef char* yes;
|
||||
\\void foo(void) {
|
||||
\\ yes a;
|
||||
\\ if (a) 2;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub const yes = [*c]u8;
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: yes = undefined;
|
||||
\\ if (a != null) _ = 2;
|
||||
\\}
|
||||
});
|
||||
|
||||
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
|
||||
|
||||
cases.addAllowWarnings("simple data types",
|
||||
|
@ -1575,31 +1587,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\}
|
||||
});
|
||||
|
||||
cases.addC("==, !=",
|
||||
\\int max(int a, int b) {
|
||||
\\ if (a == b)
|
||||
\\ return a;
|
||||
\\ if (a != b)
|
||||
\\ return b;
|
||||
\\ return a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ if (a == b) return a;
|
||||
\\ if (a != b) return b;
|
||||
\\ return a;
|
||||
\\}
|
||||
});
|
||||
cases.addC("bitwise binary operators",
|
||||
\\int max(int a, int b) {
|
||||
\\ return (a & b) ^ (a | b);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ return (a & b) ^ (a | b);
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("logical and, logical or",
|
||||
\\int max(int a, int b) {
|
||||
\\ if (a < b || a == b)
|
||||
|
@ -2596,4 +2583,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\ }
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("==, !=",
|
||||
\\int max(int a, int b) {
|
||||
\\ if (a == b)
|
||||
\\ return a;
|
||||
\\ if (a != b)
|
||||
\\ return b;
|
||||
\\ return a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ if (a == b) return a;
|
||||
\\ if (a != b) return b;
|
||||
\\ return a;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("bitwise binary operators",
|
||||
\\int max(int a, int b) {
|
||||
\\ return (a & b) ^ (a | b);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ return (a & b) ^ (a | b);
|
||||
\\}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue