Commit f91ff9a746
Changed files (3)
src
translate_c
test
src/translate_c/ast.zig
@@ -576,6 +576,7 @@ pub const Payload = struct {
name: []const u8,
type: Node,
alignment: ?c_uint,
+ default_value: ?Node,
};
};
@@ -2095,34 +2096,47 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
_ = try c.addToken(.colon, ":");
const type_expr = try renderNode(c, field.type);
- const alignment = field.alignment orelse {
- members[i] = try c.addNode(.{
- .tag = .container_field_init,
- .main_token = name_tok,
- .data = .{
- .lhs = type_expr,
- .rhs = 0,
- },
+ const align_expr = if (field.alignment) |alignment| blk: {
+ _ = try c.addToken(.keyword_align, "align");
+ _ = try c.addToken(.l_paren, "(");
+ const align_expr = try c.addNode(.{
+ .tag = .number_literal,
+ .main_token = try c.addTokenFmt(.number_literal, "{d}", .{alignment}),
+ .data = undefined,
});
- _ = try c.addToken(.comma, ",");
- continue;
- };
- _ = try c.addToken(.keyword_align, "align");
- _ = try c.addToken(.l_paren, "(");
- const align_expr = try c.addNode(.{
- .tag = .number_literal,
- .main_token = try c.addTokenFmt(.number_literal, "{d}", .{alignment}),
- .data = undefined,
- });
- _ = try c.addToken(.r_paren, ")");
+ _ = try c.addToken(.r_paren, ")");
+ break :blk align_expr;
+ } else 0;
- members[i] = try c.addNode(.{
+ const value_expr = if (field.default_value) |value| blk: {
+ _ = try c.addToken(.equal, "=");
+ break :blk try renderNode(c, value);
+ } else 0;
+
+ members[i] = try c.addNode(if (align_expr == 0) .{
+ .tag = .container_field_init,
+ .main_token = name_tok,
+ .data = .{
+ .lhs = type_expr,
+ .rhs = value_expr,
+ },
+ } else if (value_expr == 0) .{
.tag = .container_field_align,
.main_token = name_tok,
.data = .{
.lhs = type_expr,
.rhs = align_expr,
},
+ } else .{
+ .tag = .container_field,
+ .main_token = name_tok,
+ .data = .{
+ .lhs = type_expr,
+ .rhs = try c.addExtra(std.zig.Ast.Node.ContainerField{
+ .align_expr = align_expr,
+ .value_expr = value_expr,
+ }),
+ },
});
_ = try c.addToken(.comma, ",");
}
src/translate_c.zig
@@ -1229,6 +1229,14 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD
else
ClangAlignment.forField(c, field_decl, record_def).zigAlignment();
+ // C99 introduced designated initializers for structs. Omitted fields are implicitly
+ // initialized to zero. Some C APIs are designed with this in mind. Defaulting to zero
+ // values for translated struct fields permits Zig code to comfortably use such an API.
+ const default_value = if (record_decl.isStruct())
+ try Tag.std_mem_zeroes.create(c.arena, field_type)
+ else
+ null;
+
if (is_anon) {
try c.decl_table.putNoClobber(c.gpa, @intFromPtr(field_decl.getCanonicalDecl()), field_name);
}
@@ -1237,6 +1245,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD
.name = field_name,
.type = field_type,
.alignment = alignment,
+ .default_value = default_value,
});
}
test/translate_c.zig
@@ -98,8 +98,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
++ " " ++ default_enum_type ++
\\;
\\pub const Bar = extern struct {
- \\ a: c_int,
- \\ b: c_int,
+ \\ a: c_int = @import("std").mem.zeroes(c_int),
+ \\ b: c_int = @import("std").mem.zeroes(c_int),
\\};
});
@@ -149,11 +149,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define PTR void *
, &[_][]const u8{
\\pub const struct_Bar_1 = extern struct {
- \\ a: c_int,
+ \\ a: c_int = @import("std").mem.zeroes(c_int),
\\};
\\pub const struct_Foo = extern struct {
- \\ a: c_int,
- \\ b: struct_Bar_1,
+ \\ a: c_int = @import("std").mem.zeroes(c_int),
+ \\ b: struct_Bar_1 = @import("std").mem.zeroes(struct_Bar_1),
\\};
\\pub export var a: struct_Foo = struct_Foo{
\\ .a = 0,
@@ -183,9 +183,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub export fn foo() void {
\\ const struct_Foo = extern struct {
- \\ A: c_int,
- \\ B: c_int,
- \\ C: c_int,
+ \\ A: c_int = @import("std").mem.zeroes(c_int),
+ \\ B: c_int = @import("std").mem.zeroes(c_int),
+ \\ C: c_int = @import("std").mem.zeroes(c_int),
\\ };
\\ var a: struct_Foo = struct_Foo{
\\ .A = @as(c_int, 0),
@@ -195,9 +195,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ _ = @TypeOf(a);
\\ {
\\ const struct_Foo_1 = extern struct {
- \\ A: c_int,
- \\ B: c_int,
- \\ C: c_int,
+ \\ A: c_int = @import("std").mem.zeroes(c_int),
+ \\ B: c_int = @import("std").mem.zeroes(c_int),
+ \\ C: c_int = @import("std").mem.zeroes(c_int),
\\ };
\\ var a_2: struct_Foo_1 = struct_Foo_1{
\\ .A = @as(c_int, 0),
@@ -286,7 +286,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\source.h:1:9: warning: struct demoted to opaque type - unable to translate type of field foo
\\pub const Foo = opaque {};
\\pub const Bar = extern struct {
- \\ bar: ?*Foo,
+ \\ bar: ?*Foo = @import("std").mem.zeroes(?*Foo),
\\};
});
@@ -375,10 +375,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define B A(0.f)
, &[_][]const u8{
\\pub const struct_Color = extern struct {
- \\ r: u8,
- \\ g: u8,
- \\ b: u8,
- \\ a: u8,
+ \\ r: u8 = @import("std").mem.zeroes(u8),
+ \\ g: u8 = @import("std").mem.zeroes(u8),
+ \\ b: u8 = @import("std").mem.zeroes(u8),
+ \\ a: u8 = @import("std").mem.zeroes(u8),
\\};
\\pub const Color = struct_Color;
,
@@ -389,14 +389,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const LIGHTGRAY = @import("std").mem.zeroInit(CLITERAL(Color), .{ @as(c_int, 200), @as(c_int, 200), @as(c_int, 200), @as(c_int, 255) });
,
\\pub const struct_boom_t = extern struct {
- \\ i1: c_int,
+ \\ i1: c_int = @import("std").mem.zeroes(c_int),
\\};
\\pub const boom_t = struct_boom_t;
,
\\pub const FOO = @import("std").mem.zeroInit(boom_t, .{@as(c_int, 1)});
,
\\pub const MyCStruct = extern struct {
- \\ x: f32,
+ \\ x: f32 = @import("std").mem.zeroes(f32),
\\};
,
\\pub inline fn A(_x: anytype) MyCStruct {
@@ -452,7 +452,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
, &[_][]const u8{
\\pub const struct_foo = extern struct {
- \\ bar: c_short align(1),
+ \\ bar: c_short align(1) = @import("std").mem.zeroes(c_short),
\\};
});
@@ -461,7 +461,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\struct bar { int x; int y[0]; };
, &[_][]const u8{
\\pub const struct_foo = extern struct {
- \\ x: c_int align(4),
+ \\ x: c_int align(4) = @import("std").mem.zeroes(c_int),
\\ pub fn y(self: anytype) @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int) {
\\ const Intermediate = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), u8);
\\ const ReturnType = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int);
@@ -469,7 +469,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ }
\\};
\\pub const struct_bar = extern struct {
- \\ x: c_int align(4),
+ \\ x: c_int align(4) = @import("std").mem.zeroes(c_int),
\\ pub fn y(self: anytype) @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int) {
\\ const Intermediate = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), u8);
\\ const ReturnType = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int);
@@ -545,7 +545,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\source.h:4:8: warning: struct demoted to opaque type - unable to translate type of field abufused
\\pub const struct_arcan_shmif_page = opaque {};
\\pub const struct_arcan_shmif_cont = extern struct {
- \\ addr: ?*struct_arcan_shmif_page,
+ \\ addr: ?*struct_arcan_shmif_page = @import("std").mem.zeroes(?*struct_arcan_shmif_page),
\\};
});
@@ -562,10 +562,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const fnptr_ty = ?*const fn () callconv(.C) void;
\\pub const fnptr_attr_ty = ?*const fn () callconv(.C) void;
\\pub const struct_foo = extern struct {
- \\ foo: ?*const fn () callconv(.C) void,
- \\ bar: ?*const fn () callconv(.C) void,
- \\ baz: fnptr_ty,
- \\ qux: fnptr_attr_ty,
+ \\ foo: ?*const fn () callconv(.C) void = @import("std").mem.zeroes(?*const fn () callconv(.C) void),
+ \\ bar: ?*const fn () callconv(.C) void = @import("std").mem.zeroes(?*const fn () callconv(.C) void),
+ \\ baz: fnptr_ty = @import("std").mem.zeroes(fnptr_ty),
+ \\ qux: fnptr_attr_ty = @import("std").mem.zeroes(fnptr_attr_ty),
\\};
});
@@ -624,14 +624,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\void foo(outer *x) { x->y = x->x; }
, &[_][]const u8{
\\const struct_unnamed_2 = extern struct {
- \\ y: c_int,
+ \\ y: c_int = @import("std").mem.zeroes(c_int),
\\};
\\const union_unnamed_1 = extern union {
\\ x: u8,
\\ unnamed_0: struct_unnamed_2,
\\};
\\pub const outer = extern struct {
- \\ unnamed_0: union_unnamed_1,
+ \\ unnamed_0: union_unnamed_1 = @import("std").mem.zeroes(union_unnamed_1),
\\};
\\pub export fn foo(arg_x: [*c]outer) void {
\\ var x = arg_x;
@@ -669,12 +669,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\foo s3 = { 123 };
, &[_][]const u8{
\\pub const foo = extern struct {
- \\ x: c_int,
+ \\ x: c_int = @import("std").mem.zeroes(c_int),
\\};
\\const struct_unnamed_1 = extern struct {
- \\ x: f64,
- \\ y: f64,
- \\ z: f64,
+ \\ x: f64 = @import("std").mem.zeroes(f64),
+ \\ y: f64 = @import("std").mem.zeroes(f64),
+ \\ z: f64 = @import("std").mem.zeroes(f64),
\\};
\\pub export var s0: struct_unnamed_1 = struct_unnamed_1{
\\ .x = 1.2,
@@ -682,12 +682,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ .z = 0,
\\};
\\const struct_unnamed_2 = extern struct {
- \\ sec: c_int,
- \\ min: c_int,
- \\ hour: c_int,
- \\ day: c_int,
- \\ mon: c_int,
- \\ year: c_int,
+ \\ sec: c_int = @import("std").mem.zeroes(c_int),
+ \\ min: c_int = @import("std").mem.zeroes(c_int),
+ \\ hour: c_int = @import("std").mem.zeroes(c_int),
+ \\ day: c_int = @import("std").mem.zeroes(c_int),
+ \\ mon: c_int = @import("std").mem.zeroes(c_int),
+ \\ year: c_int = @import("std").mem.zeroes(c_int),
\\};
\\pub export var s1: struct_unnamed_2 = struct_unnamed_2{
\\ .sec = @as(c_int, 30),
@@ -698,8 +698,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ .year = @as(c_int, 2014),
\\};
\\const struct_unnamed_3 = extern struct {
- \\ x: c_int,
- \\ y: c_int,
+ \\ x: c_int = @import("std").mem.zeroes(c_int),
+ \\ y: c_int = @import("std").mem.zeroes(c_int),
\\};
\\pub export var s2: struct_unnamed_3 = struct_unnamed_3{
\\ .x = @as(c_int, 1),
@@ -730,9 +730,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\struct {int x,y,z;} __attribute__((packed)) s0 = {1, 2};
, &[_][]const u8{
\\const struct_unnamed_1 = extern struct {
- \\ x: c_int align(1),
- \\ y: c_int align(1),
- \\ z: c_int align(1),
+ \\ x: c_int align(1) = @import("std").mem.zeroes(c_int),
+ \\ y: c_int align(1) = @import("std").mem.zeroes(c_int),
+ \\ z: c_int align(1) = @import("std").mem.zeroes(c_int),
\\};
\\pub export var s0: struct_unnamed_1 = struct_unnamed_1{
\\ .x = @as(c_int, 1),
@@ -977,8 +977,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub const lws_callback_function = fn () callconv(.C) void;
\\pub const struct_Foo = extern struct {
- \\ func: ?*const fn () callconv(.C) void,
- \\ callback_http: ?*const lws_callback_function,
+ \\ func: ?*const fn () callconv(.C) void = @import("std").mem.zeroes(?*const fn () callconv(.C) void),
+ \\ callback_http: ?*const lws_callback_function = @import("std").mem.zeroes(?*const lws_callback_function),
\\};
});
@@ -993,7 +993,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const struct_Foo = opaque {};
,
\\pub const struct_Bar = extern struct {
- \\ foo: ?*struct_Foo,
+ \\ foo: ?*struct_Foo = @import("std").mem.zeroes(?*struct_Foo),
\\};
});
@@ -1025,13 +1025,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
, &[_][]const u8{
\\pub const struct_Foo = extern struct {
- \\ a: [*c]Foo,
+ \\ a: [*c]Foo = @import("std").mem.zeroes([*c]Foo),
\\};
,
\\pub const Foo = struct_Foo;
,
\\pub const struct_Bar = extern struct {
- \\ a: [*c]Foo,
+ \\ a: [*c]Foo = @import("std").mem.zeroes([*c]Foo),
\\};
,
\\pub const Bar = struct_Bar;
@@ -1044,8 +1044,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
, &[_][]const u8{
\\const struct_Foo = extern struct {
- \\ x: c_int,
- \\ y: [*c]u8,
+ \\ x: c_int = @import("std").mem.zeroes(c_int),
+ \\ y: [*c]u8 = @import("std").mem.zeroes([*c]u8),
\\};
,
\\pub const Foo = struct_Foo;
@@ -1057,7 +1057,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
, &[_][]const u8{
\\pub const struct_Foo = extern struct {
- \\ derp: ?*const fn ([*c]struct_Foo) callconv(.C) void,
+ \\ derp: ?*const fn ([*c]struct_Foo) callconv(.C) void = @import("std").mem.zeroes(?*const fn ([*c]struct_Foo) callconv(.C) void),
\\};
,
\\pub const Foo = struct_Foo;
@@ -1101,11 +1101,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
, &[_][]const u8{
\\pub const struct_Bar = extern struct {
- \\ next: [*c]struct_Foo,
+ \\ next: [*c]struct_Foo = @import("std").mem.zeroes([*c]struct_Foo),
\\};
,
\\pub const struct_Foo = extern struct {
- \\ next: [*c]struct_Bar,
+ \\ next: [*c]struct_Bar = @import("std").mem.zeroes([*c]struct_Bar),
\\};
});
@@ -1121,7 +1121,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
, &[_][]const u8{
\\pub const struct_comptime = extern struct {
- \\ @"defer": c_int,
+ \\ @"defer": c_int = @import("std").mem.zeroes(c_int),
\\};
,
\\pub const @"comptime" = struct_comptime;
@@ -1421,8 +1421,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
// even though the parent struct is
// this is consistent with GCC docs
\\const struct_unnamed_1 = extern struct {
- \\ a: u8,
- \\ b: c_int,
+ \\ a: u8 = @import("std").mem.zeroes(u8),
+ \\ b: c_int = @import("std").mem.zeroes(c_int),
\\};
,
\\pub const union_Foo = extern union {
@@ -1448,8 +1448,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
// have an independent packed declaration on
// the nested type (see GCC docs for details)
\\const struct_unnamed_1 = extern struct {
- \\ a: u8 align(1),
- \\ b: c_int align(1),
+ \\ a: u8 align(1) = @import("std").mem.zeroes(u8),
+ \\ b: c_int align(1) = @import("std").mem.zeroes(c_int),
\\};
,
\\pub const union_Foo = extern union {
@@ -1905,8 +1905,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
++ " " ++ default_enum_type ++
\\;
\\pub const struct_Baz = extern struct {
- \\ l: enum_unnamed_2,
- \\ m: d,
+ \\ l: enum_unnamed_2 = @import("std").mem.zeroes(enum_unnamed_2),
+ \\ m: d = @import("std").mem.zeroes(d),
\\};
\\pub const n: c_int = 0;
\\pub const o: c_int = 1;
@@ -2010,7 +2010,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const PFNGLCLEARPROC = ?*const fn (GLbitfield) callconv(.C) void;
\\pub const OpenGLProc = ?*const fn () callconv(.C) void;
\\const struct_unnamed_1 = extern struct {
- \\ Clear: PFNGLCLEARPROC,
+ \\ Clear: PFNGLCLEARPROC = @import("std").mem.zeroes(PFNGLCLEARPROC),
\\};
\\pub const union_OpenGLProcs = extern union {
\\ ptr: [1]OpenGLProc,
@@ -2362,10 +2362,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
, &[_][]const u8{
\\pub const struct_Bar_1 = extern struct {
- \\ b: c_int,
+ \\ b: c_int = @import("std").mem.zeroes(c_int),
\\};
\\pub const struct_Foo = extern struct {
- \\ c: struct_Bar_1,
+ \\ c: struct_Bar_1 = @import("std").mem.zeroes(struct_Bar_1),
\\};
});
}
@@ -2576,8 +2576,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\void func(struct Foo *a, enum Bar **b);
, &[_][]const u8{
\\pub const struct_Foo = extern struct {
- \\ x: c_int,
- \\ y: c_int,
+ \\ x: c_int = @import("std").mem.zeroes(c_int),
+ \\ y: c_int = @import("std").mem.zeroes(c_int),
\\};
\\pub const BarA: c_int = 0;
\\pub const BarB: c_int = 1;
@@ -2694,7 +2694,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
, &[_][]const u8{
\\pub const struct_Foo = extern struct {
- \\ b: c_int,
+ \\ b: c_int = @import("std").mem.zeroes(c_int),
\\};
\\pub extern var a: struct_Foo;
\\pub export var b: f32 = 2.0;
@@ -3604,12 +3604,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\} ONENAMEWITHSTRUCT;
, &[_][]const u8{
\\pub const struct_NAMED = extern struct {
- \\ name: c_long,
+ \\ name: c_long = @import("std").mem.zeroes(c_long),
\\};
\\pub const NAMED = struct_NAMED;
\\pub const struct_ONENAMEWITHSTRUCT = extern struct {
- \\ unnamed_0: struct_NAMED,
- \\ b: c_long,
+ \\ unnamed_0: struct_NAMED = = @import("std").mem.zeroes(struct_NAMED),
+ \\ b: c_long = @import("std").mem.zeroes(c_long),
\\};
});
} else {
@@ -3626,11 +3626,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\} ONENAMEWITHSTRUCT;
, &[_][]const u8{
\\pub const struct_NAMED = extern struct {
- \\ name: c_long,
+ \\ name: c_long = @import("std").mem.zeroes(c_long),
\\};
\\pub const NAMED = struct_NAMED;
\\pub const struct_ONENAMEWITHSTRUCT = extern struct {
- \\ b: c_long,
+ \\ b: c_long = @import("std").mem.zeroes(c_long),
\\};
});
}
@@ -3645,11 +3645,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\const struct_unnamed_1 = extern struct {};
\\pub const struct_a = extern struct {
- \\ unnamed_0: struct_unnamed_1,
+ \\ unnamed_0: struct_unnamed_1 = @import("std").mem.zeroes(struct_unnamed_1),
\\};
\\const struct_unnamed_2 = extern struct {};
\\pub const struct_b = extern struct {
- \\ unnamed_0: struct_unnamed_2,
+ \\ unnamed_0: struct_unnamed_2 = @import("std").mem.zeroes(struct_unnamed_2),
\\};
});
@@ -3783,8 +3783,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const struct_inner = opaque {};
,
\\pub const struct_outer = extern struct {
- \\ thing: c_int,
- \\ sub_struct: struct_inner,
+ \\ thing: c_int = @import("std").mem.zeroes(c_int),
+ \\ sub_struct: struct_inner = @import("std").mem.zeroes(struct_inner),
\\};
,
\\warning: unable to translate function, demoted to extern
@@ -3812,8 +3812,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
, &[_][]const u8{
\\pub const struct_FOO = extern struct {
- \\ x: c_int,
- \\ y: c_int,
+ \\ x: c_int = @import("std").mem.zeroes(c_int),
+ \\ y: c_int = @import("std").mem.zeroes(c_int),
\\};
\\pub export fn bar() c_int {
\\ const foo = struct {
@@ -4143,7 +4143,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\const char *struct_foo = "hello world";
, &[_][]const u8{
\\pub const struct_foo_1 = extern struct {
- \\ x: c_int,
+ \\ x: c_int = @import("std").mem.zeroes(c_int),
\\};
,
\\pub const foo = struct_foo_1;