mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
disallow extern variables with initializers
This commit is contained in:
parent
a553947a51
commit
d25674a51e
8 changed files with 23 additions and 11 deletions
|
|
@ -41,7 +41,7 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;
|
||||||
/// on this operating system. However when building object files or libraries,
|
/// on this operating system. However when building object files or libraries,
|
||||||
/// the system libc won't be linked until the final executable. So we
|
/// the system libc won't be linked until the final executable. So we
|
||||||
/// export a weak symbol here, to be overridden by the real one.
|
/// export a weak symbol here, to be overridden by the real one.
|
||||||
pub extern "c" var _mh_execute_header: mach_hdr = undefined;
|
pub extern "c" var _mh_execute_header: mach_hdr;
|
||||||
comptime {
|
comptime {
|
||||||
if (std.Target.current.isDarwin()) {
|
if (std.Target.current.isDarwin()) {
|
||||||
@export(_mh_execute_header, .{ .name = "_mh_execute_header", .linkage = .Weak });
|
@export(_mh_execute_header, .{ .name = "_mh_execute_header", .linkage = .Weak });
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ comptime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern var _fltused: c_int = 1;
|
var _fltused: c_int = 1;
|
||||||
|
|
||||||
extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
|
extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
|
||||||
fn wasm_start() callconv(.C) void {
|
fn wasm_start() callconv(.C) void {
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,7 @@ fn __stack_chk_fail() callconv(.C) noreturn {
|
||||||
@panic("stack smashing detected");
|
@panic("stack smashing detected");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern var __stack_chk_guard: usize = blk: {
|
var __stack_chk_guard: usize = blk: {
|
||||||
var buf = [1]u8{0} ** @sizeOf(usize);
|
var buf = [1]u8{0} ** @sizeOf(usize);
|
||||||
buf[@sizeOf(usize) - 1] = 255;
|
buf[@sizeOf(usize) - 1] = 255;
|
||||||
buf[@sizeOf(usize) - 2] = '\n';
|
buf[@sizeOf(usize) - 2] = '\n';
|
||||||
|
|
|
||||||
|
|
@ -324,10 +324,10 @@ pub const Fn = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Var = struct {
|
pub const Var = struct {
|
||||||
|
/// if is_extern == true this is undefined
|
||||||
init: Value,
|
init: Value,
|
||||||
owner_decl: *Decl,
|
owner_decl: *Decl,
|
||||||
|
|
||||||
has_init: bool,
|
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
is_mutable: bool,
|
is_mutable: bool,
|
||||||
is_threadlocal: bool,
|
is_threadlocal: bool,
|
||||||
|
|
@ -1456,7 +1456,11 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
|
||||||
const is_extern = blk: {
|
const is_extern = blk: {
|
||||||
const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse
|
const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse
|
||||||
break :blk false;
|
break :blk false;
|
||||||
break :blk tree.token_ids[maybe_extern_token] == .Keyword_extern;
|
if (tree.token_ids[maybe_extern_token] != .Keyword_extern) break :blk false;
|
||||||
|
if (var_decl.getTrailer("init_node")) |some| {
|
||||||
|
return self.failNode(&block_scope.base, some, "extern variables have no initializers", .{});
|
||||||
|
}
|
||||||
|
break :blk true;
|
||||||
};
|
};
|
||||||
if (var_decl.getTrailer("lib_name")) |lib_name| {
|
if (var_decl.getTrailer("lib_name")) |lib_name| {
|
||||||
assert(is_extern);
|
assert(is_extern);
|
||||||
|
|
@ -1569,7 +1573,6 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
|
||||||
new_variable.* = .{
|
new_variable.* = .{
|
||||||
.owner_decl = decl,
|
.owner_decl = decl,
|
||||||
.init = value orelse undefined,
|
.init = value orelse undefined,
|
||||||
.has_init = value != null,
|
|
||||||
.is_extern = is_extern,
|
.is_extern = is_extern,
|
||||||
.is_mutable = is_mutable,
|
.is_mutable = is_mutable,
|
||||||
.is_threadlocal = is_threadlocal,
|
.is_threadlocal = is_threadlocal,
|
||||||
|
|
@ -2440,7 +2443,7 @@ fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) Inner
|
||||||
const variable = tv.val.cast(Value.Payload.Variable).?.variable;
|
const variable = tv.val.cast(Value.Payload.Variable).?.variable;
|
||||||
|
|
||||||
const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty);
|
const ty = try self.singlePtrType(scope, src, variable.is_mutable, tv.ty);
|
||||||
if (!variable.is_mutable and !variable.is_extern and variable.has_init) {
|
if (!variable.is_mutable and !variable.is_extern) {
|
||||||
const val_payload = try scope.arena().create(Value.Payload.RefVal);
|
const val_payload = try scope.arena().create(Value.Payload.RefVal);
|
||||||
val_payload.* = .{ .val = variable.init };
|
val_payload.* = .{ .val = variable.init };
|
||||||
return self.constInst(scope, src, .{
|
return self.constInst(scope, src, .{
|
||||||
|
|
|
||||||
|
|
@ -680,6 +680,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B
|
||||||
AstNode *var_decl = ast_parse_var_decl(pc);
|
AstNode *var_decl = ast_parse_var_decl(pc);
|
||||||
if (var_decl != nullptr) {
|
if (var_decl != nullptr) {
|
||||||
assert(var_decl->type == NodeTypeVariableDeclaration);
|
assert(var_decl->type == NodeTypeVariableDeclaration);
|
||||||
|
if (first->id == TokenIdKeywordExtern && var_decl->data.variable_declaration.expr != nullptr) {
|
||||||
|
ast_error(pc, first, "extern variables have no initializers");
|
||||||
|
}
|
||||||
var_decl->line = first->start_line;
|
var_decl->line = first->start_line;
|
||||||
var_decl->column = first->start_column;
|
var_decl->column = first->start_column;
|
||||||
var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
|
var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,12 @@ const tests = @import("tests.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
|
cases.addTest("reject extern variables with initializers",
|
||||||
|
\\extern var foo: int = 2;
|
||||||
|
, &[_][]const u8{
|
||||||
|
"tmp.zig:1:1: error: extern variables have no initializers",
|
||||||
|
});
|
||||||
|
|
||||||
cases.addTest("duplicate/unused labels",
|
cases.addTest("duplicate/unused labels",
|
||||||
\\comptime {
|
\\comptime {
|
||||||
\\ blk: { blk: while (false) {} }
|
\\ blk: { blk: while (false) {} }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
extern var internal_integer: usize = 1;
|
var internal_integer: usize = 1;
|
||||||
extern var obj1_integer: usize = 421;
|
var obj1_integer: usize = 421;
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
@export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal });
|
@export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal });
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
extern var internal_integer: usize = 2;
|
var internal_integer: usize = 2;
|
||||||
extern var obj2_integer: usize = 422;
|
var obj2_integer: usize = 422;
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
@export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal });
|
@export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal });
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue