Commit a8bd55e085
Changed files (3)
src
translate_c
test
src/translate_c/ast.zig
@@ -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,
src/translate_c.zig
@@ -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: {
test/translate_c.zig
@@ -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",
+ \\});
+ });
}