authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-20 11:04:42+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-20 11:35:33+03:00
logd25674a51ec09640b0140a541a156869b3e03f81
treeb83dfe45ade9704364c06624942a8b2bccf1c02e
parenta553947a51bc5858ff40fb47dfe41daaa9ff75bf
signaturelock-open Commit is signed but in an unrecognized format.

disallow extern variables with initializers


8 files changed, 23 insertions(+), 11 deletions(-)

lib/std/c/darwin.zig+1-1
...@@ -41,7 +41,7 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;...@@ -41,7 +41,7 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;
41/// on this operating system. However when building object files or libraries,41/// on this operating system. However when building object files or libraries,
42/// the system libc won't be linked until the final executable. So we42/// the system libc won't be linked until the final executable. So we
43/// export a weak symbol here, to be overridden by the real one.43/// export a weak symbol here, to be overridden by the real one.
44pub extern "c" var _mh_execute_header: mach_hdr = undefined;44pub extern "c" var _mh_execute_header: mach_hdr;
45comptime {45comptime {
46 if (std.Target.current.isDarwin()) {46 if (std.Target.current.isDarwin()) {
47 @export(_mh_execute_header, .{ .name = "_mh_execute_header", .linkage = .Weak });47 @export(_mh_execute_header, .{ .name = "_mh_execute_header", .linkage = .Weak });
lib/std/special/c.zig+1-1
...@@ -35,7 +35,7 @@ comptime {...@@ -35,7 +35,7 @@ comptime {
35 }35 }
36}36}
3737
38extern var _fltused: c_int = 1;38var _fltused: c_int = 1;
3939
40extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;40extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
41fn wasm_start() callconv(.C) void {41fn wasm_start() callconv(.C) void {
lib/std/special/compiler_rt.zig+1-1
...@@ -335,7 +335,7 @@ fn __stack_chk_fail() callconv(.C) noreturn {...@@ -335,7 +335,7 @@ fn __stack_chk_fail() callconv(.C) noreturn {
335 @panic("stack smashing detected");335 @panic("stack smashing detected");
336}336}
337337
338extern var __stack_chk_guard: usize = blk: {338var __stack_chk_guard: usize = blk: {
339 var buf = [1]u8{0} ** @sizeOf(usize);339 var buf = [1]u8{0} ** @sizeOf(usize);
340 buf[@sizeOf(usize) - 1] = 255;340 buf[@sizeOf(usize) - 1] = 255;
341 buf[@sizeOf(usize) - 2] = '\n';341 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/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/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 });