diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2023-03-07 22:24:50 +0000 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2023-03-12 19:07:06 +0200 |
| commit | a8bd55e0853f7f80c9cd843ec54813425e4276bc (patch) | |
| tree | 43c45d380722b2f9b32a650d0b4e30a8d1788ff3 /src | |
| parent | c93e0d86187cb589d6726acd36f741f3d87a96be (diff) | |
| download | zig-a8bd55e0853f7f80c9cd843ec54813425e4276bc.tar.gz zig-a8bd55e0853f7f80c9cd843ec54813425e4276bc.zip | |
translate-c: translate extern unknown-length arrays using @extern
Resolves: #14743
Diffstat (limited to 'src')
| -rw-r--r-- | src/translate_c.zig | 16 | ||||
| -rw-r--r-- | src/translate_c/ast.zig | 28 |
2 files changed, 43 insertions, 1 deletions
diff --git a/src/translate_c.zig b/src/translate_c.zig index 5b2b1c2df5..698f750afb 100644 --- a/src/translate_c.zig +++ b/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: { diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index 81a19eb39d..688235c2d3 100644 --- a/src/translate_c/ast.zig +++ b/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, |
