mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
translate-c: translate extern unknown-length arrays using @extern
Resolves: #14743
This commit is contained in:
parent
c93e0d8618
commit
a8bd55e085
@ -784,9 +784,9 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
|
||||
|
||||
const qual_type = var_decl.getTypeSourceInfo_getType();
|
||||
const storage_class = var_decl.getStorageClass();
|
||||
const is_const = qual_type.isConstQualified();
|
||||
const has_init = var_decl.hasInit();
|
||||
const decl_init = var_decl.getInit();
|
||||
var is_const = qual_type.isConstQualified();
|
||||
|
||||
// In C extern variables with initializers behave like Zig exports.
|
||||
// extern int foo = 2;
|
||||
@ -843,6 +843,20 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
|
||||
|
||||
// std.mem.zeroes(T)
|
||||
init_node = try Tag.std_mem_zeroes.create(c.arena, type_node);
|
||||
} else if (qual_type.getTypeClass() == .IncompleteArray) {
|
||||
// Oh no, an extern array of unknown size! These are really fun because there's no
|
||||
// direct equivalent in Zig. To translate correctly, we'll have to create a C-pointer
|
||||
// to the data initialized via @extern.
|
||||
|
||||
const name_str = try std.fmt.allocPrint(c.arena, "\"{s}\"", .{var_name});
|
||||
init_node = try Tag.builtin_extern.create(c.arena, .{
|
||||
.type = type_node,
|
||||
.name = try Tag.string_literal.create(c.arena, name_str),
|
||||
});
|
||||
|
||||
// Since this is really a pointer to the underlying data, we tweak a few properties.
|
||||
is_extern = false;
|
||||
is_const = true;
|
||||
}
|
||||
|
||||
const linksection_string = blk: {
|
||||
|
||||
@ -158,6 +158,8 @@ pub const Node = extern union {
|
||||
vector_zero_init,
|
||||
/// @shuffle(type, a, b, mask)
|
||||
shuffle,
|
||||
/// @extern(ty, .{ .name = n })
|
||||
builtin_extern,
|
||||
|
||||
/// @import("std").zig.c_translation.MacroArithmetic.<op>(lhs, rhs)
|
||||
macro_arithmetic,
|
||||
@ -373,6 +375,7 @@ pub const Node = extern union {
|
||||
.field_access => Payload.FieldAccess,
|
||||
.string_slice => Payload.StringSlice,
|
||||
.shuffle => Payload.Shuffle,
|
||||
.builtin_extern => Payload.Extern,
|
||||
.macro_arithmetic => Payload.MacroArithmetic,
|
||||
};
|
||||
}
|
||||
@ -718,6 +721,14 @@ pub const Payload = struct {
|
||||
},
|
||||
};
|
||||
|
||||
pub const Extern = struct {
|
||||
base: Payload,
|
||||
data: struct {
|
||||
type: Node,
|
||||
name: Node,
|
||||
},
|
||||
};
|
||||
|
||||
pub const MacroArithmetic = struct {
|
||||
base: Payload,
|
||||
data: struct {
|
||||
@ -1409,6 +1420,22 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
|
||||
payload.mask_vector,
|
||||
});
|
||||
},
|
||||
.builtin_extern => {
|
||||
const payload = node.castTag(.builtin_extern).?.data;
|
||||
|
||||
var info_inits: [1]Payload.ContainerInitDot.Initializer = .{
|
||||
.{ .name = "name", .value = payload.name },
|
||||
};
|
||||
var info_payload: Payload.ContainerInitDot = .{
|
||||
.base = .{ .tag = .container_init_dot },
|
||||
.data = &info_inits,
|
||||
};
|
||||
|
||||
return renderBuiltinCall(c, "@extern", &.{
|
||||
payload.type,
|
||||
.{ .ptr_otherwise = &info_payload.base },
|
||||
});
|
||||
},
|
||||
.macro_arithmetic => {
|
||||
const payload = node.castTag(.macro_arithmetic).?.data;
|
||||
const op = @tagName(payload.op);
|
||||
@ -2348,6 +2375,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
|
||||
.div_exact,
|
||||
.offset_of,
|
||||
.shuffle,
|
||||
.builtin_extern,
|
||||
.static_local_var,
|
||||
.mut_str,
|
||||
.macro_arithmetic,
|
||||
|
||||
@ -3948,4 +3948,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
}
|
||||
|
||||
cases.add("extern array of unknown length",
|
||||
\\extern int foo[];
|
||||
, &[_][]const u8{
|
||||
\\const foo: [*c]c_int = @extern([*c]c_int, .{
|
||||
\\ .name = "foo",
|
||||
\\});
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user