authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-20 18:35:31-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-20 18:35:31-04:00
log9cfcd0c29677e11f76846b006757ff49e05e3d6f
tree285973ffaab76ee3ca831a9663f15be62c44d32b
parent1ca49b92c650e9b8988a35983e202cdb9c7ba6e7
parent717e2a365d9b5103f855668e4765cc154203a2bf
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6103 from Vexu/extern

Disallow extern variables with initializers.

13 files changed, 122 insertions(+), 33 deletions(-)

lib/std/c/darwin.zig+3-2
...@@ -46,10 +46,11 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;...@@ -46,10 +46,11 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;
46/// on this operating system. However when building object files or libraries,46/// on this operating system. However when building object files or libraries,
47/// the system libc won't be linked until the final executable. So we47/// the system libc won't be linked until the final executable. So we
48/// export a weak symbol here, to be overridden by the real one.48/// export a weak symbol here, to be overridden by the real one.
49pub extern "c" var _mh_execute_header: mach_hdr = undefined;49var dummy_execute_header: mach_hdr = undefined;
50pub extern var _mh_execute_header: mach_hdr;
50comptime {51comptime {
51 if (std.Target.current.isDarwin()) {52 if (std.Target.current.isDarwin()) {
52 @export(_mh_execute_header, .{ .name = "_mh_execute_header", .linkage = .Weak });53 @export(dummy_execute_header, .{ .name = "_mh_execute_header", .linkage = .Weak });
53 }54 }
54}55}
5556
lib/std/mem.zig+19-1
...@@ -226,9 +226,19 @@ pub fn zeroes(comptime T: type) T {...@@ -226,9 +226,19 @@ pub fn zeroes(comptime T: type) T {
226 .Vector => |info| {226 .Vector => |info| {
227 return @splat(info.len, zeroes(info.child));227 return @splat(info.len, zeroes(info.child));
228 },228 },
229 .Union => |info| {
230 if (comptime meta.containerLayout(T) == .Extern) {
231 // The C language specification states that (global) unions
232 // should be zero initialized to the first named member.
233 var item: T = undefined;
234 @field(item, info.fields[0].name) = zeroes(@TypeOf(@field(item, info.fields[0].name)));
235 return item;
236 }
237
238 @compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
239 },
229 .ErrorUnion,240 .ErrorUnion,
230 .ErrorSet,241 .ErrorSet,
231 .Union,
232 .Fn,242 .Fn,
233 .BoundFn,243 .BoundFn,
234 .Type,244 .Type,
...@@ -317,6 +327,14 @@ test "mem.zeroes" {...@@ -317,6 +327,14 @@ test "mem.zeroes" {
317 for (b.sentinel) |e| {327 for (b.sentinel) |e| {
318 testing.expectEqual(@as(u8, 0), e);328 testing.expectEqual(@as(u8, 0), e);
319 }329 }
330
331 const C_union = extern union {
332 a: u8,
333 b: u32,
334 };
335
336 var c = zeroes(C_union);
337 testing.expectEqual(@as(u8, 0), c.a);
320}338}
321339
322/// Sets a slice to zeroes.340/// Sets a slice to zeroes.
lib/std/special/c.zig+1-1
...@@ -40,7 +40,7 @@ comptime {...@@ -40,7 +40,7 @@ comptime {
40 }40 }
41}41}
4242
43extern var _fltused: c_int = 1;43var _fltused: c_int = 1;
4444
45extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;45extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
46fn wasm_start() callconv(.C) void {46fn wasm_start() callconv(.C) void {
lib/std/special/compiler_rt.zig+1-1
...@@ -340,7 +340,7 @@ fn __stack_chk_fail() callconv(.C) noreturn {...@@ -340,7 +340,7 @@ fn __stack_chk_fail() callconv(.C) noreturn {
340 @panic("stack smashing detected");340 @panic("stack smashing detected");
341}341}
342342
343extern var __stack_chk_guard: usize = blk: {343var __stack_chk_guard: usize = blk: {
344 var buf = [1]u8{0} ** @sizeOf(usize);344 var buf = [1]u8{0} ** @sizeOf(usize);
345 buf[@sizeOf(usize) - 1] = 255;345 buf[@sizeOf(usize) - 1] = 255;
346 buf[@sizeOf(usize) - 2] = '\n';346 buf[@sizeOf(usize) - 2] = '\n';
src-self-hosted/Module.zig+7-4
...@@ -324,10 +324,10 @@ pub const Fn = struct {...@@ -324,10 +324,10 @@ pub const Fn = struct {
324};324};
325325
326pub const Var = struct {326pub const Var = struct {
327 /// if is_extern == true this is undefined
327 init: Value,328 init: Value,
328 owner_decl: *Decl,329 owner_decl: *Decl,
329330
330 has_init: bool,
331 is_extern: bool,331 is_extern: bool,
332 is_mutable: bool,332 is_mutable: bool,
333 is_threadlocal: bool,333 is_threadlocal: bool,
...@@ -1456,7 +1456,11 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1456,7 +1456,11 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1456 const is_extern = blk: {1456 const is_extern = blk: {
1457 const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse1457 const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse
1458 break :blk false;1458 break :blk false;
1459 break :blk tree.token_ids[maybe_extern_token] == .Keyword_extern;1459 if (tree.token_ids[maybe_extern_token] != .Keyword_extern) break :blk false;
1460 if (var_decl.getTrailer("init_node")) |some| {
1461 return self.failNode(&block_scope.base, some, "extern variables have no initializers", .{});
1462 }
1463 break :blk true;
1460 };1464 };
1461 if (var_decl.getTrailer("lib_name")) |lib_name| {1465 if (var_decl.getTrailer("lib_name")) |lib_name| {
1462 assert(is_extern);1466 assert(is_extern);
...@@ -1569,7 +1573,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1569,7 +1573,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1569 new_variable.* = .{1573 new_variable.* = .{
1570 .owner_decl = decl,1574 .owner_decl = decl,
1571 .init = value orelse undefined,1575 .init = value orelse undefined,
1572 .has_init = value != null,
1573 .is_extern = is_extern,1576 .is_extern = is_extern,
1574 .is_mutable = is_mutable,1577 .is_mutable = is_mutable,
1575 .is_threadlocal = is_threadlocal,1578 .is_threadlocal = is_threadlocal,
...@@ -2440,7 +2443,7 @@ fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) Inner...@@ -2440,7 +2443,7 @@ fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) Inner
2440 const variable = tv.val.cast(Value.Payload.Variable).?.variable;2443 const variable = tv.val.cast(Value.Payload.Variable).?.variable;
24412444
2442 const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty);2445 const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty);
2443 if (!variable.is_mutable and !variable.is_extern and variable.has_init) {2446 if (!variable.is_mutable and !variable.is_extern) {
2444 const val_payload = try scope.arena().create(Value.Payload.RefVal);2447 const val_payload = try scope.arena().create(Value.Payload.RefVal);
2445 val_payload.* = .{ .val = variable.init };2448 val_payload.* = .{ .val = variable.init };
2446 return self.constInst(scope, src, .{2449 return self.constInst(scope, src, .{
src-self-hosted/translate_c.zig+41-13
...@@ -498,7 +498,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {...@@ -498,7 +498,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
498 _ = try transRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));498 _ = try transRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl));
499 },499 },
500 .Var => {500 .Var => {
501 return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl));501 return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl), null);
502 },502 },
503 .Empty => {503 .Empty => {
504 // Do nothing504 // Do nothing
...@@ -679,12 +679,13 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -679,12 +679,13 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
679 return addTopLevelDecl(c, fn_name, &proto_node.base);679 return addTopLevelDecl(c, fn_name, &proto_node.base);
680}680}
681681
682fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {682/// if mangled_name is not null, this var decl was declared in a block scope.
683 const var_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, var_decl)));683fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl, mangled_name: ?[]const u8) Error!void {
684 const var_name = mangled_name orelse try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, var_decl)));
684 if (c.global_scope.sym_table.contains(var_name))685 if (c.global_scope.sym_table.contains(var_name))
685 return; // Avoid processing this decl twice686 return; // Avoid processing this decl twice
686 const rp = makeRestorePoint(c);687 const rp = makeRestorePoint(c);
687 const visib_tok = try appendToken(c, .Keyword_pub, "pub");688 const visib_tok = if (mangled_name) |_| null else try appendToken(c, .Keyword_pub, "pub");
688689
689 const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None)690 const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None)
690 null691 null
...@@ -701,8 +702,14 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -701,8 +702,14 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
701 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);702 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
702 const storage_class = ZigClangVarDecl_getStorageClass(var_decl);703 const storage_class = ZigClangVarDecl_getStorageClass(var_decl);
703 const is_const = ZigClangQualType_isConstQualified(qual_type);704 const is_const = ZigClangQualType_isConstQualified(qual_type);
704705 const has_init = ZigClangVarDecl_hasInit(var_decl);
705 const extern_tok = if (storage_class == .Extern)706
707 // In C extern variables with initializers behave like Zig exports.
708 // extern int foo = 2;
709 // does the same as:
710 // extern int foo;
711 // int foo = 2;
712 const extern_tok = if (storage_class == .Extern and !has_init)
706 try appendToken(c, .Keyword_extern, "extern")713 try appendToken(c, .Keyword_extern, "extern")
707 else if (storage_class != .Static)714 else if (storage_class != .Static)
708 try appendToken(c, .Keyword_export, "export")715 try appendToken(c, .Keyword_export, "export")
...@@ -730,7 +737,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -730,7 +737,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
730 // If the initialization expression is not present, initialize with undefined.737 // If the initialization expression is not present, initialize with undefined.
731 // If it is an integer literal, we can skip the @as since it will be redundant738 // If it is an integer literal, we can skip the @as since it will be redundant
732 // with the variable type.739 // with the variable type.
733 if (ZigClangVarDecl_hasInit(var_decl)) {740 if (has_init) {
734 eq_tok = try appendToken(c, .Equal, "=");741 eq_tok = try appendToken(c, .Equal, "=");
735 init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr|742 init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr|
736 transExprCoercing(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) {743 transExprCoercing(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) {
...@@ -745,7 +752,22 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -745,7 +752,22 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
745 try transCreateNodeUndefinedLiteral(c);752 try transCreateNodeUndefinedLiteral(c);
746 } else if (storage_class != .Extern) {753 } else if (storage_class != .Extern) {
747 eq_tok = try appendToken(c, .Equal, "=");754 eq_tok = try appendToken(c, .Equal, "=");
748 init_node = try transCreateNodeIdentifierUnchecked(c, "undefined");755 // The C language specification states that variables with static or threadlocal
756 // storage without an initializer are initialized to a zero value.
757
758 // @import("std").mem.zeroes(T)
759 const import_fn_call = try c.createBuiltinCall("@import", 1);
760 const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
761 import_fn_call.params()[0] = std_node;
762 import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
763 const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "mem");
764 const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "zeroes");
765
766 const zero_init_call = try c.createCall(outer_field_access, 1);
767 zero_init_call.params()[0] = type_node;
768 zero_init_call.rtoken = try appendToken(c, .RParen, ")");
769
770 init_node = &zero_init_call.base;
749 }771 }
750772
751 const linksection_expr = blk: {773 const linksection_expr = blk: {
...@@ -1561,15 +1583,22 @@ fn transDeclStmtOne(...@@ -1561,15 +1583,22 @@ fn transDeclStmtOne(
1561 .Var => {1583 .Var => {
1562 const var_decl = @ptrCast(*const ZigClangVarDecl, decl);1584 const var_decl = @ptrCast(*const ZigClangVarDecl, decl);
15631585
1564 const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None)
1565 null
1566 else
1567 try appendToken(c, .Keyword_threadlocal, "threadlocal");
1568 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);1586 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
1569 const name = try c.str(ZigClangNamedDecl_getName_bytes_begin(1587 const name = try c.str(ZigClangNamedDecl_getName_bytes_begin(
1570 @ptrCast(*const ZigClangNamedDecl, var_decl),1588 @ptrCast(*const ZigClangNamedDecl, var_decl),
1571 ));1589 ));
1572 const mangled_name = try block_scope.makeMangledName(c, name);1590 const mangled_name = try block_scope.makeMangledName(c, name);
1591
1592 switch (ZigClangVarDecl_getStorageClass(var_decl)) {
1593 .Extern, .Static => {
1594 // This is actually a global variable, put it in the global scope and reference it.
1595 // `_ = mangled_name;`
1596 try visitVarDecl(rp.c, var_decl, mangled_name);
1597 return try maybeSuppressResult(rp, scope, .unused, try transCreateNodeIdentifier(rp.c, mangled_name));
1598 },
1599 else => {},
1600 }
1601
1573 const mut_tok = if (ZigClangQualType_isConstQualified(qual_type))1602 const mut_tok = if (ZigClangQualType_isConstQualified(qual_type))
1574 try appendToken(c, .Keyword_const, "const")1603 try appendToken(c, .Keyword_const, "const")
1575 else1604 else
...@@ -1597,7 +1626,6 @@ fn transDeclStmtOne(...@@ -1597,7 +1626,6 @@ fn transDeclStmtOne(
1597 .mut_token = mut_tok,1626 .mut_token = mut_tok,
1598 .semicolon_token = semicolon_token,1627 .semicolon_token = semicolon_token,
1599 }, .{1628 }, .{
1600 .thread_local_token = thread_local_token,
1601 .eq_token = eq_token,1629 .eq_token = eq_token,
1602 .type_node = type_node,1630 .type_node = type_node,
1603 .init_node = init_node,1631 .init_node = init_node,
src/codegen.cpp+5-4
...@@ -292,13 +292,14 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {...@@ -292,13 +292,14 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
292 }292 }
293}293}
294294
295static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {295static LLVMLinkage to_llvm_linkage(GlobalLinkageId id, bool is_extern) {
296 switch (id) {296 switch (id) {
297 case GlobalLinkageIdInternal:297 case GlobalLinkageIdInternal:
298 return LLVMInternalLinkage;298 return LLVMInternalLinkage;
299 case GlobalLinkageIdStrong:299 case GlobalLinkageIdStrong:
300 return LLVMExternalLinkage;300 return LLVMExternalLinkage;
301 case GlobalLinkageIdWeak:301 case GlobalLinkageIdWeak:
302 if (is_extern) return LLVMExternalWeakLinkage;
302 return LLVMWeakODRLinkage;303 return LLVMWeakODRLinkage;
303 case GlobalLinkageIdLinkOnce:304 case GlobalLinkageIdLinkOnce:
304 return LLVMLinkOnceODRLinkage;305 return LLVMLinkOnceODRLinkage;
...@@ -521,7 +522,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {...@@ -521,7 +522,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
521 }522 }
522523
523524
524 LLVMSetLinkage(llvm_fn, to_llvm_linkage(linkage));525 LLVMSetLinkage(llvm_fn, to_llvm_linkage(linkage, fn->body_node == nullptr));
525526
526 if (linkage == GlobalLinkageIdInternal) {527 if (linkage == GlobalLinkageIdInternal) {
527 LLVMSetUnnamedAddr(llvm_fn, true);528 LLVMSetUnnamedAddr(llvm_fn, true);
...@@ -7962,7 +7963,7 @@ static void do_code_gen(CodeGen *g) {...@@ -7962,7 +7963,7 @@ static void do_code_gen(CodeGen *g) {
7962 global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name);7963 global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name);
7963 // TODO debug info for the extern variable7964 // TODO debug info for the extern variable
79647965
7965 LLVMSetLinkage(global_value, to_llvm_linkage(linkage));7966 LLVMSetLinkage(global_value, to_llvm_linkage(linkage, true));
7966 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);7967 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
7967 LLVMSetAlignment(global_value, var->align_bytes);7968 LLVMSetAlignment(global_value, var->align_bytes);
7968 LLVMSetGlobalConstant(global_value, var->gen_is_const);7969 LLVMSetGlobalConstant(global_value, var->gen_is_const);
...@@ -7975,7 +7976,7 @@ static void do_code_gen(CodeGen *g) {...@@ -7975,7 +7976,7 @@ static void do_code_gen(CodeGen *g) {
7975 global_value = var->const_value->llvm_global;7976 global_value = var->const_value->llvm_global;
79767977
7977 if (exported) {7978 if (exported) {
7978 LLVMSetLinkage(global_value, to_llvm_linkage(linkage));7979 LLVMSetLinkage(global_value, to_llvm_linkage(linkage, false));
7979 maybe_export_dll(g, global_value, GlobalLinkageIdStrong);7980 maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
7980 }7981 }
7981 if (var->section_name) {7982 if (var->section_name) {
src/parser.cpp+3
...@@ -680,6 +680,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B...@@ -680,6 +680,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B
680 AstNode *var_decl = ast_parse_var_decl(pc);680 AstNode *var_decl = ast_parse_var_decl(pc);
681 if (var_decl != nullptr) {681 if (var_decl != nullptr) {
682 assert(var_decl->type == NodeTypeVariableDeclaration);682 assert(var_decl->type == NodeTypeVariableDeclaration);
683 if (first->id == TokenIdKeywordExtern && var_decl->data.variable_declaration.expr != nullptr) {
684 ast_error(pc, first, "extern variables have no initializers");
685 }
683 var_decl->line = first->start_line;686 var_decl->line = first->start_line;
684 var_decl->column = first->start_column;687 var_decl->column = first->start_column;
685 var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;688 var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
test/compile_errors.zig+6
...@@ -2,6 +2,12 @@ const tests = @import("tests.zig");...@@ -2,6 +2,12 @@ const tests = @import("tests.zig");
2const std = @import("std");2const std = @import("std");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.addTest("reject extern variables with initializers",
6 \\extern var foo: int = 2;
7 , &[_][]const u8{
8 "tmp.zig:1:1: error: extern variables have no initializers",
9 });
10
5 cases.addTest("duplicate/unused labels",11 cases.addTest("duplicate/unused labels",
6 \\comptime {12 \\comptime {
7 \\ blk: { blk: while (false) {} }13 \\ blk: { blk: while (false) {} }
test/run_translated_c.zig+14
...@@ -3,6 +3,20 @@ const tests = @import("tests.zig");...@@ -3,6 +3,20 @@ const tests = @import("tests.zig");
3const nl = std.cstr.line_sep;3const nl = std.cstr.line_sep;
44
5pub fn addCases(cases: *tests.RunTranslatedCContext) void {5pub fn addCases(cases: *tests.RunTranslatedCContext) void {
6 cases.add("static variable in block scope",
7 \\#include <stdlib.h>
8 \\int foo() {
9 \\ static int bar;
10 \\ bar += 1;
11 \\ return bar;
12 \\}
13 \\int main() {
14 \\ foo();
15 \\ foo();
16 \\ if (foo() != 3) abort();
17 \\}
18 , "");
19
6 cases.add("array initializer",20 cases.add("array initializer",
7 \\#include <stdlib.h>21 \\#include <stdlib.h>
8 \\int main(int argc, char **argv) {22 \\int main(int argc, char **argv) {
test/standalone/global_linkage/obj1.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1extern var internal_integer: usize = 1;1var internal_integer: usize = 1;
2extern var obj1_integer: usize = 421;2var obj1_integer: usize = 421;
33
4comptime {4comptime {
5 @export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal });5 @export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal });
test/standalone/global_linkage/obj2.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1extern var internal_integer: usize = 2;1var internal_integer: usize = 2;
2extern var obj2_integer: usize = 422;2var obj2_integer: usize = 422;
33
4comptime {4comptime {
5 @export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal });5 @export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal });
test/translate_c.zig+18-3
...@@ -3,6 +3,20 @@ const std = @import("std");...@@ -3,6 +3,20 @@ const std = @import("std");
3const CrossTarget = std.zig.CrossTarget;3const CrossTarget = std.zig.CrossTarget;
44
5pub fn addCases(cases: *tests.TranslateCContext) void {5pub fn addCases(cases: *tests.TranslateCContext) void {
6 cases.add("extern variable in block scope",
7 \\float bar;
8 \\int foo() {
9 \\ _Thread_local static int bar = 2;
10 \\}
11 , &[_][]const u8{
12 \\pub export var bar: f32 = @import("std").mem.zeroes(f32);
13 \\threadlocal var bar_1: c_int = 2;
14 \\pub export fn foo() c_int {
15 \\ _ = bar_1;
16 \\ return 0;
17 \\}
18 });
19
6 cases.add("missing return stmt",20 cases.add("missing return stmt",
7 \\int foo() {}21 \\int foo() {}
8 \\int bar() {22 \\int bar() {
...@@ -466,7 +480,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -466,7 +480,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
466 , &[_][]const u8{480 , &[_][]const u8{
467 \\pub extern var extern_var: c_int;481 \\pub extern var extern_var: c_int;
468 \\pub const int_var: c_int = 13;482 \\pub const int_var: c_int = 13;
469 \\pub export var foo: c_int = undefined;483 \\pub export var foo: c_int = @import("std").mem.zeroes(c_int);
470 });484 });
471485
472 cases.add("const ptr initializer",486 cases.add("const ptr initializer",
...@@ -480,8 +494,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -480,8 +494,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
480 \\ static const char v2[] = "2.2.2";494 \\ static const char v2[] = "2.2.2";
481 \\}495 \\}
482 , &[_][]const u8{496 , &[_][]const u8{
497 \\const v2: [*c]const u8 = "2.2.2";
483 \\pub export fn foo() void {498 \\pub export fn foo() void {
484 \\ const v2: [*c]const u8 = "2.2.2";499 \\ _ = v2;
485 \\}500 \\}
486 });501 });
487502
...@@ -1327,7 +1342,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1327,7 +1342,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1327 \\static char arr1[] = "hello";1342 \\static char arr1[] = "hello";
1328 \\char arr2[] = "hello";1343 \\char arr2[] = "hello";
1329 , &[_][]const u8{1344 , &[_][]const u8{
1330 \\pub extern var arr0: [*c]u8 = "hello";1345 \\pub export var arr0: [*c]u8 = "hello";
1331 \\pub var arr1: [*c]u8 = "hello";1346 \\pub var arr1: [*c]u8 = "hello";
1332 \\pub export var arr2: [*c]u8 = "hello";1347 \\pub export var arr2: [*c]u8 = "hello";
1333 });1348 });