translate-c: get all run-translated-c tests passing

This commit is contained in:
Veikka Tuominen 2021-02-15 16:07:21 +02:00
parent 77a11e6873
commit 78fba4e021
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
4 changed files with 120 additions and 132 deletions

View File

@ -3669,12 +3669,12 @@ test "zig fmt: hexadeciaml float literals with underscore separators" {
);
}
//test "zig fmt: C var args" {
// try testCanonical(
// \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
// \\
// );
//}
test "zig fmt: C var args" {
try testCanonical(
\\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
\\
);
}
//test "zig fmt: Only indent multiline string literals in function calls" {
// try testCanonical(

View File

@ -1308,7 +1308,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S
.r_paren => break,
.comma => {
try renderToken(ais, tree, last_param_token, .space); // ,
last_param_token += 1;
continue;
},
else => {}, // Parameter type without a name.
}

View File

@ -990,7 +990,10 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
}));
}
break :blk try Tag.@"enum".create(c.arena, try c.arena.dupe(ast.Payload.Enum.Field, fields.items));
break :blk try Tag.@"enum".create(c.arena, .{
.int_type = init_arg_expr,
.fields = try c.arena.dupe(ast.Payload.Enum.Field, fields.items),
});
} else blk: {
_ = try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {});
break :blk Tag.opaque_literal.init();
@ -1540,8 +1543,8 @@ fn finishBoolExpr(
}
},
.Pointer => {
// node == null
return Tag.equal.create(c.arena, .{ .lhs = node, .rhs = Tag.null_literal.init() });
// node != null
return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.null_literal.init() });
},
.Typedef => {
const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
@ -1675,7 +1678,8 @@ fn transStringLiteralAsArray(
const ty = expr_base.getType().getTypePtr();
const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);
const arr_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc());
const elem_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc());
const arr_type = try Tag.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_type });
const init_list = try c.arena.alloc(Node, array_size);
var i: c_uint = 0;
@ -2668,7 +2672,7 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
return Tag.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used));
},
.LNot => {
return Tag.not.create(c.arena, try transExpr(c, scope, op_expr, .used));
return Tag.not.create(c.arena, try transBoolExpr(c, scope, op_expr, .used));
},
.Extension => {
return transExpr(c, scope, stmt.getSubExpr(), used);
@ -2969,8 +2973,15 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node {
fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node {
// TODO use something more accurate
const dbl = stmt.getValueAsApproximateDouble();
const node = try transCreateNodeNumber(c, dbl, .float);
var dbl = stmt.getValueAsApproximateDouble();
const is_negative = dbl < 0;
if (is_negative) dbl = -dbl;
const str = try std.fmt.allocPrint(c.arena, "{d}", .{dbl});
var node = if (dbl == std.math.floor(dbl))
try Tag.integer_literal.create(c.arena, str)
else
try Tag.float_literal.create(c.arena, str);
if (is_negative) node = try Tag.negate.create(c.arena, node);
return maybeSuppressResult(c, scope, used, node);
}
@ -3004,8 +3015,11 @@ fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang
},
};
defer cond_scope.deinit();
const cond_node = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
var then_body = try Tag.identifier.create(c.arena, mangled_name);
const cond_ident = try Tag.identifier.create(c.arena, mangled_name);
const ty = getExprQualType(c, cond_expr).getTypePtr();
const cond_node = try finishBoolExpr(c, &cond_scope.base, cond_expr.getBeginLoc(), ty, cond_ident, .used);
var then_body = cond_ident;
if (!res_is_bool and isBoolRes(init_node)) {
then_body = try Tag.bool_to_int.create(c.arena, then_body);
}
@ -3489,11 +3503,13 @@ fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node {
else => @compileError("unimplemented"),
}
const big: math.big.int.Const = .{ .limbs = limbs, .positive = !is_negative };
const big: math.big.int.Const = .{ .limbs = limbs, .positive = true };
const str = big.toStringAlloc(c.arena, 10, false) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
};
return Tag.integer_literal.create(c.arena, str);
const res = try Tag.integer_literal.create(c.arena, str);
if (is_negative) return Tag.negate.create(c.arena, res);
return res;
}
fn transCreateNodeNumber(c: *Context, num: anytype, num_kind: enum { int, float }) !Node {
@ -3567,7 +3583,7 @@ fn transCreateNodeShiftOp(
const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);
const rhs = try transExprCoercing(c, scope, rhs_expr, .used);
const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });
const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs });
return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);
}
@ -3622,7 +3638,8 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
const is_volatile = child_qt.isVolatileQualified();
const elem_type = try transQualType(c, child_qt, source_loc);
if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) {
return Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
const ptr = try Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
return Tag.optional_type.create(c.arena, ptr);
}
return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });

View File

@ -491,7 +491,10 @@ pub const Payload = struct {
pub const Enum = struct {
base: Payload,
data: []Field,
data: struct {
int_type: Node,
fields: []Field,
},
pub const Field = struct {
name: []const u8,
@ -825,11 +828,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.main_token = try c.addToken(.identifier, "void"),
.data = undefined,
}),
.@"anytype" => return c.addNode(.{
.tag = .@"anytype",
.main_token = try c.addToken(.keyword_anytype, "anytype"),
.data = undefined,
}),
.noreturn_type => return c.addNode(.{
.tag = .identifier,
.main_token = try c.addToken(.identifier, "noreturn"),
@ -946,7 +944,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const payload = node.castTag(.char_literal).?.data;
return c.addNode(.{
.tag = .identifier,
.main_token = try c.addToken(.string_literal, payload),
.main_token = try c.addToken(.char_literal, payload),
.data = undefined,
});
},
@ -1268,7 +1266,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const lhs = try c.addNode(.{
.tag = .identifier,
.main_token = try c.addToken(.identifier, "_"),
.data = .{ .lhs = undefined, .rhs = undefined },
.data = undefined,
});
return c.addNode(.{
.tag = .assign,
@ -1510,7 +1508,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.rhs = try c.addNode(.{
.tag = .integer_literal,
.main_token = try c.addTokenFmt(.integer_literal, "{d}", .{payload.count}),
.data = .{ .lhs = undefined, .rhs = undefined },
.data = undefined,
}),
},
});
@ -1519,7 +1517,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const payload = node.castTag(.empty_array).?.data;
const type_expr = try renderArrayType(c, 0, payload);
return renderArrayInit(c, 0, &.{});
return renderArrayInit(c, type_expr, &.{});
},
.array_init => {
const payload = node.castTag(.array_init).?.data;
@ -1534,15 +1532,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
.@"struct", .@"union" => return renderRecord(c, node),
.@"enum" => {
const payload = node.castTag(.@"enum").?.data;
_ = try c.addToken(.keyword_extern, "extern");
const enum_tok = try c.addToken(.keyword_enum, "enum");
_ = try c.addToken(.l_paren, "(");
const arg_expr = try renderNode(c, payload.int_type);
_ = try c.addToken(.r_paren, ")");
_ = try c.addToken(.l_brace, "{");
const members = try c.gpa.alloc(NodeIndex, std.math.max(payload.len + 1, 1));
const members = try c.gpa.alloc(NodeIndex, std.math.max(payload.fields.len + 1, 1));
defer c.gpa.free(members);
members[0] = 0;
members[1] = 0;
for (payload) |field, i| {
for (payload.fields) |field, i| {
const name_tok = try c.addIdentifier(field.name);
const value_expr = if (field.value) |some| blk: {
_ = try c.addToken(.equal, "=");
@ -1560,7 +1560,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
_ = try c.addToken(.comma, ",");
}
// make non-exhaustive
members[payload.len] = try c.addNode(.{
members[payload.fields.len] = try c.addNode(.{
.tag = .container_field_init,
.main_token = try c.addIdentifier("_"),
.data = .{
@ -1571,26 +1571,18 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
_ = try c.addToken(.comma, ",");
_ = try c.addToken(.r_brace, "}");
if (members.len <= 2) {
return c.addNode(.{
.tag = .container_decl_two_comma,
.main_token = enum_tok,
.data = .{
.lhs = members[0],
.rhs = members[1],
},
});
} else {
const span = try c.listToSpan(members);
return c.addNode(.{
.tag = .container_decl_comma,
.main_token = enum_tok,
.data = .{
.lhs = span.start,
.rhs = span.end,
},
});
}
const span = try c.listToSpan(members);
return c.addNode(.{
.tag = .container_decl_arg_comma,
.main_token = enum_tok,
.data = .{
.lhs = arg_expr,
.rhs = try c.addExtra(NodeSubRange{
.start = span.start,
.end = span.end,
}),
},
});
},
.enum_redecl => {
const payload = node.castTag(.enum_redecl).?.data;
@ -1701,12 +1693,16 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
});
}
},
.@"anytype" => unreachable, // Handled in renderParams
}
}
fn renderRecord(c: *Context, node: Node) !NodeIndex {
const payload = @fieldParentPtr(Payload.Record, "base", node.ptr_otherwise).data;
if (payload.is_packed) _ = try c.addToken(.keyword_packed, "packed");
if (payload.is_packed)
_ = try c.addToken(.keyword_packed, "packed")
else
_ = try c.addToken(.keyword_extern, "extern");
const kind_tok = if (node.tag() == .@"struct")
try c.addToken(.keyword_struct, "struct")
else
@ -1829,7 +1825,7 @@ fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
const len_expr = try c.addNode(.{
.tag = .integer_literal,
.main_token = try c.addTokenFmt(.integer_literal, "{d}", .{len}),
.data = .{ .lhs = undefined, .rhs = undefined },
.data = undefined,
});
_ = try c.addToken(.r_bracket, "]");
const elem_type_expr = try renderNode(c, elem_type);
@ -1920,6 +1916,8 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.negate_wrap,
.bit_not,
.func,
.call,
.array_type,
=> {
// no grouping needed
return renderNode(c, node);
@ -1954,7 +1952,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.array_cat,
.array_filler,
.@"if",
.call,
.@"enum",
.@"struct",
.@"union",
@ -1962,7 +1959,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.tuple,
.container_init,
.block,
.array_type,
=> return c.addNode(.{
.tag = .grouped_expression,
.main_token = try c.addToken(.l_paren, "("),
@ -2161,7 +2157,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .integer_literal,
.main_token = try c.addTokenFmt(.integer_literal, "{d}", .{some}),
.data = .{ .lhs = undefined, .rhs = undefined },
.data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@ -2173,7 +2169,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .string_literal,
.main_token = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(some)}),
.data = .{ .lhs = undefined, .rhs = undefined },
.data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@ -2232,39 +2228,10 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const fn_token = try c.addToken(.keyword_fn, "fn");
if (payload.name) |some| _ = try c.addIdentifier(some);
_ = try c.addToken(.l_paren, "(");
const first = if (payload.params.len != 0) blk: {
const param = payload.params[0];
if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
if (param.name) |some| {
_ = try c.addIdentifier(some);
_ = try c.addToken(.colon, ":");
}
break :blk try renderNode(c, param.type);
} else 0;
const params = try renderParams(c, payload.params, payload.is_var_args);
defer params.deinit();
var span: NodeSubRange = undefined;
if (payload.params.len > 1) {
var params = try c.gpa.alloc(NodeIndex, payload.params.len);
defer c.gpa.free(params);
params[0] = first;
for (payload.params[1..]) |param, i| {
_ = try c.addToken(.comma, ",");
if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
if (param.name) |some| {
_ = try c.addIdentifier(some);
_ = try c.addToken(.colon, ":");
}
params[i + 1] = try renderNode(c, param.type);
}
span = try c.listToSpan(params);
}
if (payload.is_var_args) {
if (payload.params.len != 0) _ = try c.addToken(.comma, ",");
_ = try c.addToken(.ellipsis3, "...");
}
_ = try c.addToken(.r_paren, ")");
if (params.items.len > 1) span = try c.listToSpan(params.items);
const align_expr = if (payload.alignment) |some| blk: {
_ = try c.addToken(.keyword_align, "align");
@ -2272,7 +2239,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .integer_literal,
.main_token = try c.addTokenFmt(.integer_literal, "{d}", .{some}),
.data = .{ .lhs = undefined, .rhs = undefined },
.data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@ -2284,7 +2251,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .string_literal,
.main_token = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(some)}),
.data = .{ .lhs = undefined, .rhs = undefined },
.data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@ -2296,8 +2263,8 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
_ = try c.addToken(.period, ".");
const res = try c.addNode(.{
.tag = .enum_literal,
.main_token = try c.addTokenFmt(.identifier, "{}", .{some}),
.data = .{ .lhs = undefined, .rhs = undefined },
.main_token = try c.addTokenFmt(.identifier, "{s}", .{@tagName(some)}),
.data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@ -2307,12 +2274,12 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const fn_proto = try blk: {
if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
if (payload.params.len < 2)
if (params.items.len < 2)
break :blk c.addNode(.{
.tag = .fn_proto_simple,
.main_token = fn_token,
.data = .{
.lhs = first,
.lhs = params.items[0],
.rhs = return_type_expr,
},
})
@ -2329,13 +2296,13 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
},
});
}
if (payload.params.len < 2)
if (params.items.len < 2)
break :blk c.addNode(.{
.tag = .fn_proto_one,
.main_token = fn_token,
.data = .{
.lhs = try c.addExtra(std.zig.ast.Node.FnProtoOne{
.param = first,
.param = params.items[0],
.align_expr = align_expr,
.section_expr = section_expr,
.callconv_expr = callconv_expr,
@ -2383,35 +2350,10 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
const fn_token = try c.addToken(.keyword_fn, "fn");
_ = try c.addIdentifier(payload.name);
_ = try c.addToken(.l_paren, "(");
const first = if (payload.params.len != 0) blk: {
const param = payload.params[0];
if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
if (param.name) |some| {
_ = try c.addIdentifier(some);
_ = try c.addToken(.colon, ":");
}
break :blk try renderNode(c, param.type);
} else 0;
const params = try renderParams(c, payload.params, false);
defer params.deinit();
var span: NodeSubRange = undefined;
if (payload.params.len > 1) {
var params = try c.gpa.alloc(NodeIndex, payload.params.len);
defer c.gpa.free(params);
params[0] = first;
for (payload.params[1..]) |param, i| {
_ = try c.addToken(.comma, ",");
if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
if (param.name) |some| {
_ = try c.addIdentifier(some);
_ = try c.addToken(.colon, ":");
}
params[i + 1] = try renderNode(c, param.type);
}
span = try c.listToSpan(params);
}
_ = try c.addToken(.r_paren, ")");
if (params.items.len > 1) span = try c.listToSpan(params.items);
const callconv_expr = blk: {
_ = try c.addToken(.keyword_callconv, "callconv");
@ -2420,7 +2362,7 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
const res = try c.addNode(.{
.tag = .enum_literal,
.main_token = try c.addToken(.identifier, "Inline"),
.data = .{ .lhs = undefined, .rhs = undefined },
.data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
@ -2428,13 +2370,13 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
const return_type_expr = try renderNode(c, payload.return_type);
const fn_proto = try blk: {
if (payload.params.len < 2)
if (params.items.len < 2)
break :blk c.addNode(.{
.tag = .fn_proto_one,
.main_token = fn_token,
.data = .{
.lhs = try c.addExtra(std.zig.ast.Node.FnProtoOne{
.param = first,
.param = params.items[0],
.align_expr = 0,
.section_expr = 0,
.callconv_expr = callconv_expr,
@ -2467,3 +2409,32 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
},
});
}
fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) {
_ = try c.addToken(.l_paren, "(");
var rendered = std.ArrayList(NodeIndex).init(c.gpa);
errdefer rendered.deinit();
try rendered.ensureCapacity(std.math.max(params.len, 1));
for (params) |param, i| {
if (i != 0) _ = try c.addToken(.comma, ",");
if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
if (param.name) |some| {
_ = try c.addIdentifier(some);
_ = try c.addToken(.colon, ":");
}
if (param.type.tag() == .@"anytype") {
_ = try c.addToken(.keyword_anytype, "anytype");
continue;
}
rendered.appendAssumeCapacity(try renderNode(c, param.type));
}
if (is_var_args) {
if (params.len != 0) _ = try c.addToken(.comma, ",");
_ = try c.addToken(.ellipsis3, "...");
}
_ = try c.addToken(.r_paren, ")");
if (rendered.items.len == 0) rendered.appendAssumeCapacity(0);
return rendered;
}