mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
translate-c: correct translation of global variables
* externs with intializers are translated as exports * non extern without explicit initialization are zero initalized
This commit is contained in:
parent
91de5c212f
commit
adc5bce5e8
@ -221,9 +221,19 @@ pub fn zeroes(comptime T: type) T {
|
||||
.Vector => |info| {
|
||||
return @splat(info.len, zeroes(info.child));
|
||||
},
|
||||
.Union => |info| {
|
||||
if (comptime meta.containerLayout(T) == .Extern) {
|
||||
// The C language specification states that (global) unions
|
||||
// should be zero initialized to the first named member.
|
||||
var item: T = undefined;
|
||||
@field(item, info.fields[0].name) = zeroes(@TypeOf(@field(item, info.fields[0].name)));
|
||||
return item;
|
||||
}
|
||||
|
||||
@compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
|
||||
},
|
||||
.ErrorUnion,
|
||||
.ErrorSet,
|
||||
.Union,
|
||||
.Fn,
|
||||
.BoundFn,
|
||||
.Type,
|
||||
@ -312,6 +322,14 @@ test "mem.zeroes" {
|
||||
for (b.sentinel) |e| {
|
||||
testing.expectEqual(@as(u8, 0), e);
|
||||
}
|
||||
|
||||
const C_union = extern union {
|
||||
a: u8,
|
||||
b: u32,
|
||||
};
|
||||
|
||||
var c = zeroes(C_union);
|
||||
testing.expectEqual(@as(u8, 0), c.a);
|
||||
}
|
||||
|
||||
/// Sets a slice to zeroes.
|
||||
|
||||
@ -701,8 +701,14 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
|
||||
const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
|
||||
const storage_class = ZigClangVarDecl_getStorageClass(var_decl);
|
||||
const is_const = ZigClangQualType_isConstQualified(qual_type);
|
||||
const has_init = ZigClangVarDecl_hasInit(var_decl);
|
||||
|
||||
const extern_tok = if (storage_class == .Extern)
|
||||
// In C extern variables with initializers behave like Zig exports.
|
||||
// extern int foo = 2;
|
||||
// does the same as:
|
||||
// extern int foo;
|
||||
// int foo = 2;
|
||||
const extern_tok = if (storage_class == .Extern and !has_init)
|
||||
try appendToken(c, .Keyword_extern, "extern")
|
||||
else if (storage_class != .Static)
|
||||
try appendToken(c, .Keyword_export, "export")
|
||||
@ -730,7 +736,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
|
||||
// If the initialization expression is not present, initialize with undefined.
|
||||
// If it is an integer literal, we can skip the @as since it will be redundant
|
||||
// with the variable type.
|
||||
if (ZigClangVarDecl_hasInit(var_decl)) {
|
||||
if (has_init) {
|
||||
eq_tok = try appendToken(c, .Equal, "=");
|
||||
init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr|
|
||||
transExprCoercing(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) {
|
||||
@ -745,7 +751,22 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
|
||||
try transCreateNodeUndefinedLiteral(c);
|
||||
} else if (storage_class != .Extern) {
|
||||
eq_tok = try appendToken(c, .Equal, "=");
|
||||
init_node = try transCreateNodeIdentifierUnchecked(c, "undefined");
|
||||
// The C language specification states that variables with static or threadlocal
|
||||
// storage without an initializer are initialized to a zero value.
|
||||
|
||||
// @import("std").mem.zeroes(T)
|
||||
const import_fn_call = try c.createBuiltinCall("@import", 1);
|
||||
const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
|
||||
import_fn_call.params()[0] = std_node;
|
||||
import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
|
||||
const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "mem");
|
||||
const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "zeroes");
|
||||
|
||||
const zero_init_call = try c.createCall(outer_field_access, 1);
|
||||
zero_init_call.params()[0] = type_node;
|
||||
zero_init_call.rtoken = try appendToken(c, .RParen, ")");
|
||||
|
||||
init_node = &zero_init_call.base;
|
||||
}
|
||||
|
||||
const linksection_expr = blk: {
|
||||
|
||||
@ -466,7 +466,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, &[_][]const u8{
|
||||
\\pub extern var extern_var: c_int;
|
||||
\\pub const int_var: c_int = 13;
|
||||
\\pub export var foo: c_int = undefined;
|
||||
\\pub export var foo: c_int = @import("std").mem.zeroes(c_int);
|
||||
});
|
||||
|
||||
cases.add("const ptr initializer",
|
||||
@ -1327,7 +1327,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\static char arr1[] = "hello";
|
||||
\\char arr2[] = "hello";
|
||||
, &[_][]const u8{
|
||||
\\pub extern var arr0: [*c]u8 = "hello";
|
||||
\\pub export var arr0: [*c]u8 = "hello";
|
||||
\\pub var arr1: [*c]u8 = "hello";
|
||||
\\pub export var arr2: [*c]u8 = "hello";
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user