From a553947a51bc5858ff40fb47dfe41daaa9ff75bf Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 20 Aug 2020 10:45:55 +0300 Subject: [PATCH] translate-c: correctly put static and extern local variables in global scope --- src-self-hosted/translate_c.zig | 25 ++++++++++++++++--------- test/run_translated_c.zig | 14 ++++++++++++++ test/translate_c.zig | 17 ++++++++++++++++- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 6c6e3f0c7e..6628f5b99e 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -498,7 +498,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { _ = try transRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl)); }, .Var => { - return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl)); + return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl), null); }, .Empty => { // Do nothing @@ -679,12 +679,13 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { return addTopLevelDecl(c, fn_name, &proto_node.base); } -fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { - const var_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, var_decl))); +/// if mangled_name is not null, this var decl was declared in a block scope. +fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl, mangled_name: ?[]const u8) Error!void { + const var_name = mangled_name orelse try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, var_decl))); if (c.global_scope.sym_table.contains(var_name)) return; // Avoid processing this decl twice const rp = makeRestorePoint(c); - const visib_tok = try appendToken(c, .Keyword_pub, "pub"); + const visib_tok = if (mangled_name) |_| null else try appendToken(c, .Keyword_pub, "pub"); const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None) null @@ -1582,15 +1583,22 @@ fn transDeclStmtOne( .Var => { const var_decl = @ptrCast(*const ZigClangVarDecl, decl); - const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None) - null - else - try appendToken(c, .Keyword_threadlocal, "threadlocal"); const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); const name = try c.str(ZigClangNamedDecl_getName_bytes_begin( @ptrCast(*const ZigClangNamedDecl, var_decl), )); const mangled_name = try block_scope.makeMangledName(c, name); + + switch (ZigClangVarDecl_getStorageClass(var_decl)) { + .Extern, .Static => { + // This is actually a global variable, put it in the global scope and reference it. + // `_ = mangled_name;` + try visitVarDecl(rp.c, var_decl, mangled_name); + return try maybeSuppressResult(rp, scope, .unused, try transCreateNodeIdentifier(rp.c, mangled_name)); + }, + else => {}, + } + const mut_tok = if (ZigClangQualType_isConstQualified(qual_type)) try appendToken(c, .Keyword_const, "const") else @@ -1618,7 +1626,6 @@ fn transDeclStmtOne( .mut_token = mut_tok, .semicolon_token = semicolon_token, }, .{ - .thread_local_token = thread_local_token, .eq_token = eq_token, .type_node = type_node, .init_node = init_node, diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index 3fa183ce3b..2b27e3085e 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -3,6 +3,20 @@ const tests = @import("tests.zig"); const nl = std.cstr.line_sep; pub fn addCases(cases: *tests.RunTranslatedCContext) void { + cases.add("static variable in block scope", + \\#include + \\int foo() { + \\ static int bar; + \\ bar += 1; + \\ return bar; + \\} + \\int main() { + \\ foo(); + \\ foo(); + \\ if (foo() != 3) abort(); + \\} + , ""); + cases.add("array initializer", \\#include \\int main(int argc, char **argv) { diff --git a/test/translate_c.zig b/test/translate_c.zig index bfbae2b65e..41f1e78294 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3,6 +3,20 @@ const std = @import("std"); const CrossTarget = std.zig.CrossTarget; pub fn addCases(cases: *tests.TranslateCContext) void { + cases.add("extern variable in block scope", + \\float bar; + \\int foo() { + \\ _Thread_local static int bar = 2; + \\} + , &[_][]const u8{ + \\pub export var bar: f32 = @import("std").mem.zeroes(f32); + \\threadlocal var bar_1: c_int = 2; + \\pub export fn foo() c_int { + \\ _ = bar_1; + \\ return 0; + \\} + }); + cases.add("missing return stmt", \\int foo() {} \\int bar() { @@ -480,8 +494,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ static const char v2[] = "2.2.2"; \\} , &[_][]const u8{ + \\const v2: [*c]const u8 = "2.2.2"; \\pub export fn foo() void { - \\ const v2: [*c]const u8 = "2.2.2"; + \\ _ = v2; \\} });