Build a getter function for a flexible array field in a C record
e.g. T items[] or T items[0]. The generated function returns a [*c] pointer
to the flexible array with the correct const and volatile qualifiers
fn createFlexibleMemberFn(
t: *Translator,
member_name: []const u8,
field_name: []const u8,
) Error!ZigNode
fn createFlexibleMemberFn(
t: *Translator,
member_name: []const u8,
field_name: []const u8,
) Error!ZigNode {
// Use `_self` instead of the conventional `self` to avoid the Zig error
// "function parameter shadows declaration of 'self'".
// `processContainerMemberFns` merges C functions matching a struct's name
// prefix into the struct as `pub const` aliases (e.g. `foo_self()` becomes
// `pub const self = __root.foo_self`). A parameter also named `self` would
// then shadow that declaration, which Zig rejects.
const self_param_name = "_self";
const self_param = try ZigTag.identifier.create(t.arena, self_param_name);
const self_type = try ZigTag.typeof.create(t.arena, self_param);
const fn_params = try t.arena.alloc(ast.Payload.Param, 1);
fn_params[0] = .{
.name = self_param_name,
.type = ZigTag.@"anytype".init(),
.is_noalias = false,
};
// @typeInfo(@TypeOf(self.*.<field_name>)).pointer.child
const dereffed = try ZigTag.deref.create(t.arena, self_param);
const field_access = try ZigTag.field_access.create(t.arena, .{ .lhs = dereffed, .field_name = field_name });
const type_of = try ZigTag.typeof.create(t.arena, field_access);
const type_info = try ZigTag.typeinfo.create(t.arena, type_of);
const array_info = try ZigTag.field_access.create(t.arena, .{ .lhs = type_info, .field_name = "array" });
const child_info = try ZigTag.field_access.create(t.arena, .{ .lhs = array_info, .field_name = "child" });
const return_type = try t.createHelperCallNode(.FlexibleArrayType, &.{ self_type, child_info });
// return @ptrCast(&self.*.<field_name>);
const address_of = try ZigTag.address_of.create(t.arena, field_access);
const aligned = try ZigTag.align_cast.create(t.arena, address_of);
const casted = try ZigTag.ptr_cast.create(t.arena, aligned);
const return_stmt = try ZigTag.@"return".create(t.arena, casted);
const body = try ZigTag.block_single.create(t.arena, return_stmt);
return ZigTag.func.create(t.arena, .{
.is_pub = true,
.is_extern = false,
.is_export = false,
.is_inline = false,
.is_var_args = false,
.name = member_name,
.linksection_string = null,
.explicit_callconv = null,
.params = fn_params,
.return_type = return_type,
.body = body,
.alignment = null,
});
}