diff --git a/doc/langref.html.in b/doc/langref.html.in index 9d48238843..7ffbcc0110 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2780,10 +2780,16 @@ fn noop4() align(4) void {} test "function alignment" { try expect(derp() == 1234); - try expect(@TypeOf(noop1) == fn () align(1) void); - try expect(@TypeOf(noop4) == fn () align(4) void); + try expect(@TypeOf(derp) == fn () i32); + try expect(@TypeOf(&derp) == *align(@sizeOf(usize) * 2) const fn () i32); + noop1(); + try expect(@TypeOf(noop1) == fn () void); + try expect(@TypeOf(&noop1) == *align(1) const fn () void); + noop4(); + try expect(@TypeOf(noop4) == fn () void); + try expect(@TypeOf(&noop4) == *align(4) const fn () void); } {#code_end#}

diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index d9e72f2019..0238d35c7d 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -420,7 +420,6 @@ pub const Type = union(enum) { /// therefore must be kept in sync with the compiler implementation. pub const Fn = struct { calling_convention: CallingConvention, - alignment: comptime_int, is_generic: bool, is_var_args: bool, /// TODO change the language spec to make this not optional. diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index 8dd122c3ba..8442ac9fe0 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -1053,10 +1053,10 @@ pub const sigset_t = u32; pub const empty_sigset: sigset_t = 0; pub const SIG = struct { - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); - pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(5)); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); + pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(5); /// block specified signal set pub const BLOCK = 1; @@ -1150,7 +1150,7 @@ pub const siginfo_t = extern struct { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. pub const Sigaction = extern struct { - pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void; handler: extern union { diff --git a/lib/std/c/dragonfly.zig b/lib/std/c/dragonfly.zig index 8cbdd22c40..183a81bba2 100644 --- a/lib/std/c/dragonfly.zig +++ b/lib/std/c/dragonfly.zig @@ -616,9 +616,9 @@ pub const S = struct { pub const BADSIG = SIG.ERR; pub const SIG = struct { - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); pub const BLOCK = 1; pub const UNBLOCK = 2; @@ -690,7 +690,7 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS }; pub const sig_atomic_t = c_int; pub const Sigaction = extern struct { - pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void; /// signal handler diff --git a/lib/std/c/freebsd.zig b/lib/std/c/freebsd.zig index 94854cf090..a89ca30968 100644 --- a/lib/std/c/freebsd.zig +++ b/lib/std/c/freebsd.zig @@ -695,9 +695,9 @@ pub const SIG = struct { pub const UNBLOCK = 2; pub const SETMASK = 3; - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); pub const WORDS = 4; pub const MAXSIG = 128; @@ -1171,7 +1171,7 @@ const NSIG = 32; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void; /// signal handler diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig index 723d953d2d..12b5201acd 100644 --- a/lib/std/c/haiku.zig +++ b/lib/std/c/haiku.zig @@ -441,9 +441,9 @@ pub const SA = struct { }; pub const SIG = struct { - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); pub const HUP = 1; pub const INT = 2; @@ -690,7 +690,7 @@ const NSIG = 32; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = *const fn (i32) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; /// signal handler __sigaction_u: extern union { diff --git a/lib/std/c/netbsd.zig b/lib/std/c/netbsd.zig index 475fd55e22..c06857787a 100644 --- a/lib/std/c/netbsd.zig +++ b/lib/std/c/netbsd.zig @@ -800,9 +800,9 @@ pub const winsize = extern struct { const NSIG = 32; pub const SIG = struct { - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); pub const WORDS = 4; pub const MAXSIG = 128; @@ -864,7 +864,7 @@ pub const SIG = struct { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void; /// signal handler diff --git a/lib/std/c/openbsd.zig b/lib/std/c/openbsd.zig index 75a4d6e0e8..4fd450cd5c 100644 --- a/lib/std/c/openbsd.zig +++ b/lib/std/c/openbsd.zig @@ -795,11 +795,11 @@ pub const winsize = extern struct { const NSIG = 33; pub const SIG = struct { - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); - pub const CATCH = @as(?Sigaction.handler_fn, @ptrFromInt(2)); - pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(3)); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); + pub const CATCH: ?Sigaction.handler_fn = @ptrFromInt(2); + pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(3); pub const HUP = 1; pub const INT = 2; @@ -842,7 +842,7 @@ pub const SIG = struct { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void; /// signal handler diff --git a/lib/std/c/solaris.zig b/lib/std/c/solaris.zig index ef64acd43b..838b6985cc 100644 --- a/lib/std/c/solaris.zig +++ b/lib/std/c/solaris.zig @@ -798,10 +798,10 @@ pub const winsize = extern struct { const NSIG = 75; pub const SIG = struct { - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); - pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(2)); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); + pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(2); pub const WORDS = 4; pub const MAXSIG = 75; @@ -874,7 +874,7 @@ pub const SIG = struct { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void; /// signal options diff --git a/lib/std/meta.zig b/lib/std/meta.zig index f7b418d71d..da0f629748 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -57,10 +57,9 @@ test stringToEnum { } /// Returns the alignment of type T. -/// Note that if T is a pointer or function type the result is different than -/// the one returned by @alignOf(T). +/// Note that if T is a pointer type the result is different than the one +/// returned by @alignOf(T). /// If T is a pointer type the alignment of the type it points to is returned. -/// If T is a function type the alignment a target-dependent value is returned. pub fn alignment(comptime T: type) comptime_int { return switch (@typeInfo(T)) { .Optional => |info| switch (@typeInfo(info.child)) { @@ -68,7 +67,6 @@ pub fn alignment(comptime T: type) comptime_int { else => @alignOf(T), }, .Pointer => |info| info.alignment, - .Fn => |info| info.alignment, else => @alignOf(T), }; } @@ -80,7 +78,8 @@ test alignment { try testing.expect(alignment([]align(1) u8) == 1); try testing.expect(alignment([]align(2) u8) == 2); try testing.expect(alignment(fn () void) > 0); - try testing.expect(alignment(fn () align(128) void) == 128); + try testing.expect(alignment(*const fn () void) > 0); + try testing.expect(alignment(*align(128) const fn () void) == 128); } /// Given a parameterized type (array, vector, pointer, optional), returns the "child type". diff --git a/lib/std/os/emscripten.zig b/lib/std/os/emscripten.zig index 04c3996f15..924b2dd0b2 100644 --- a/lib/std/os/emscripten.zig +++ b/lib/std/os/emscripten.zig @@ -689,13 +689,13 @@ pub const SIG = struct { pub const SYS = 31; pub const UNUSED = SIG.SYS; - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(std.math.maxInt(usize))); - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(std.math.maxInt(usize)); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); }; pub const Sigaction = extern struct { - pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void; handler: extern union { diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 3892e4326a..a5cdab18ce 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1327,16 +1327,14 @@ pub fn flock(fd: fd_t, operation: i32) usize { return syscall2(.flock, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, operation)))); } -var vdso_clock_gettime = @as(?*const anyopaque, @ptrCast(&init_vdso_clock_gettime)); - // We must follow the C calling convention when we call into the VDSO -const vdso_clock_gettime_ty = *align(1) const fn (i32, *timespec) callconv(.C) usize; +const VdsoClockGettime = *align(1) const fn (i32, *timespec) callconv(.C) usize; +var vdso_clock_gettime: ?VdsoClockGettime = &init_vdso_clock_gettime; pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { if (@hasDecl(VDSO, "CGT_SYM")) { - const ptr = @atomicLoad(?*const anyopaque, &vdso_clock_gettime, .unordered); - if (ptr) |fn_ptr| { - const f = @as(vdso_clock_gettime_ty, @ptrCast(fn_ptr)); + const ptr = @atomicLoad(?VdsoClockGettime, &vdso_clock_gettime, .unordered); + if (ptr) |f| { const rc = f(clk_id, tp); switch (rc) { 0, @as(usize, @bitCast(-@as(isize, @intFromEnum(E.INVAL)))) => return rc, @@ -1348,15 +1346,12 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { } fn init_vdso_clock_gettime(clk: i32, ts: *timespec) callconv(.C) usize { - const ptr = @as(?*const anyopaque, @ptrFromInt(vdso.lookup(VDSO.CGT_VER, VDSO.CGT_SYM))); + const ptr: ?VdsoClockGettime = @ptrFromInt(vdso.lookup(VDSO.CGT_VER, VDSO.CGT_SYM)); // Note that we may not have a VDSO at all, update the stub address anyway // so that clock_gettime will fall back on the good old (and slow) syscall - @atomicStore(?*const anyopaque, &vdso_clock_gettime, ptr, .monotonic); + @atomicStore(?VdsoClockGettime, &vdso_clock_gettime, ptr, .monotonic); // Call into the VDSO if available - if (ptr) |fn_ptr| { - const f = @as(vdso_clock_gettime_ty, @ptrCast(fn_ptr)); - return f(clk, ts); - } + if (ptr) |f| return f(clk, ts); return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS)))); } @@ -2516,9 +2511,9 @@ pub const SIG = if (is_mips) struct { pub const SYS = 31; pub const UNUSED = SIG.SYS; - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); } else if (is_sparc) struct { pub const BLOCK = 1; pub const UNBLOCK = 2; @@ -2560,9 +2555,9 @@ pub const SIG = if (is_mips) struct { pub const PWR = LOST; pub const IO = SIG.POLL; - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); } else struct { pub const BLOCK = 0; pub const UNBLOCK = 1; @@ -2603,9 +2598,9 @@ pub const SIG = if (is_mips) struct { pub const SYS = 31; pub const UNUSED = SIG.SYS; - pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize))); - pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0)); - pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1)); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); }; pub const kernel_rwf = u32; @@ -3709,7 +3704,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30; const k_sigaction_funcs = struct { - const handler = ?*const fn (c_int) align(1) callconv(.C) void; + const handler = ?*align(1) const fn (c_int) callconv(.C) void; const restorer = *const fn () callconv(.C) void; }; @@ -3736,7 +3731,7 @@ pub const k_sigaction = switch (native_arch) { /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { - pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void; + pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void; handler: extern union { diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 364e49ae8f..54efe22b8d 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -1369,16 +1369,16 @@ fn fnProtoExpr( break :is_var_args false; }; - const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { - break :inst try expr(&block_scope, scope, coerced_align_ri, fn_proto.ast.align_expr); - }; + if (fn_proto.ast.align_expr != 0) { + return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{}); + } if (fn_proto.ast.addrspace_expr != 0) { - return astgen.failNode(fn_proto.ast.addrspace_expr, "addrspace not allowed on function prototypes", .{}); + return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{}); } if (fn_proto.ast.section_expr != 0) { - return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{}); + return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{}); } const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) @@ -1394,7 +1394,7 @@ fn fnProtoExpr( const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; const is_inferred_error = token_tags[maybe_bang] == .bang; if (is_inferred_error) { - return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); + return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{}); } const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type); @@ -1403,7 +1403,7 @@ fn fnProtoExpr( .cc_ref = cc, .cc_gz = null, - .align_ref = align_ref, + .align_ref = .none, .align_gz = null, .ret_ref = ret_ty, .ret_gz = null, diff --git a/src/InternPool.zig b/src/InternPool.zig index 832927071e..8611a67564 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -765,16 +765,10 @@ pub const Key = union(enum) { /// Tells whether a parameter is noalias. See `paramIsNoalias` helper /// method for accessing this. noalias_bits: u32, - /// `none` indicates the function has the default alignment for - /// function code on the target. In this case, this field *must* be set - /// to `none`, otherwise the `InternPool` equality and hashing - /// functions will return incorrect results. - alignment: Alignment, cc: std.builtin.CallingConvention, is_var_args: bool, is_generic: bool, is_noinline: bool, - align_is_generic: bool, cc_is_generic: bool, section_is_generic: bool, addrspace_is_generic: bool, @@ -794,7 +788,6 @@ pub const Key = union(enum) { a.return_type == b.return_type and a.comptime_bits == b.comptime_bits and a.noalias_bits == b.noalias_bits and - a.alignment == b.alignment and a.cc == b.cc and a.is_var_args == b.is_var_args and a.is_generic == b.is_generic and @@ -808,7 +801,6 @@ pub const Key = union(enum) { std.hash.autoHash(hasher, self.return_type); std.hash.autoHash(hasher, self.comptime_bits); std.hash.autoHash(hasher, self.noalias_bits); - std.hash.autoHash(hasher, self.alignment); std.hash.autoHash(hasher, self.cc); std.hash.autoHash(hasher, self.is_var_args); std.hash.autoHash(hasher, self.is_generic); @@ -3587,18 +3579,16 @@ pub const Tag = enum(u8) { flags: Flags, pub const Flags = packed struct(u32) { - alignment: Alignment, cc: std.builtin.CallingConvention, is_var_args: bool, is_generic: bool, has_comptime_bits: bool, has_noalias_bits: bool, is_noinline: bool, - align_is_generic: bool, cc_is_generic: bool, section_is_generic: bool, addrspace_is_generic: bool, - _: u9 = 0, + _: u16 = 0, }; }; @@ -4918,11 +4908,9 @@ fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType { .return_type = type_function.data.return_type, .comptime_bits = comptime_bits, .noalias_bits = noalias_bits, - .alignment = type_function.data.flags.alignment, .cc = type_function.data.flags.cc, .is_var_args = type_function.data.flags.is_var_args, .is_noinline = type_function.data.flags.is_noinline, - .align_is_generic = type_function.data.flags.align_is_generic, .cc_is_generic = type_function.data.flags.cc_is_generic, .section_is_generic = type_function.data.flags.section_is_generic, .addrspace_is_generic = type_function.data.flags.addrspace_is_generic, @@ -6211,8 +6199,6 @@ pub const GetFuncTypeKey = struct { comptime_bits: u32 = 0, noalias_bits: u32 = 0, /// `null` means generic. - alignment: ?Alignment = .none, - /// `null` means generic. cc: ?std.builtin.CallingConvention = .Unspecified, is_var_args: bool = false, is_generic: bool = false, @@ -6242,14 +6228,12 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat .params_len = params_len, .return_type = key.return_type, .flags = .{ - .alignment = key.alignment orelse .none, .cc = key.cc orelse .Unspecified, .is_var_args = key.is_var_args, .has_comptime_bits = key.comptime_bits != 0, .has_noalias_bits = key.noalias_bits != 0, .is_generic = key.is_generic, .is_noinline = key.is_noinline, - .align_is_generic = key.alignment == null, .cc_is_generic = key.cc == null, .section_is_generic = key.section_is_generic, .addrspace_is_generic = key.addrspace_is_generic, @@ -6433,14 +6417,12 @@ pub fn getFuncDeclIes(ip: *InternPool, gpa: Allocator, key: GetFuncDeclIesKey) A .params_len = params_len, .return_type = @enumFromInt(ip.items.len - 2), .flags = .{ - .alignment = key.alignment orelse .none, .cc = key.cc orelse .Unspecified, .is_var_args = key.is_var_args, .has_comptime_bits = key.comptime_bits != 0, .has_noalias_bits = key.noalias_bits != 0, .is_generic = key.is_generic, .is_noinline = key.is_noinline, - .align_is_generic = key.alignment == null, .cc_is_generic = key.cc == null, .section_is_generic = key.section_is_generic, .addrspace_is_generic = key.addrspace_is_generic, @@ -6553,7 +6535,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) .param_types = arg.param_types, .return_type = arg.bare_return_type, .noalias_bits = arg.noalias_bits, - .alignment = arg.alignment, .cc = arg.cc, .is_noinline = arg.is_noinline, }); @@ -6610,6 +6591,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) func_index, func_extra_index, func_ty, + arg.alignment, arg.section, ); } @@ -6673,14 +6655,12 @@ pub fn getFuncInstanceIes( .params_len = params_len, .return_type = error_union_type, .flags = .{ - .alignment = arg.alignment, .cc = arg.cc, .is_var_args = false, .has_comptime_bits = false, .has_noalias_bits = arg.noalias_bits != 0, .is_generic = false, .is_noinline = arg.is_noinline, - .align_is_generic = false, .cc_is_generic = false, .section_is_generic = false, .addrspace_is_generic = false, @@ -6741,6 +6721,7 @@ pub fn getFuncInstanceIes( func_index, func_extra_index, func_ty, + arg.alignment, arg.section, ); } @@ -6752,6 +6733,7 @@ fn finishFuncInstance( func_index: Index, func_extra_index: u32, func_ty: Index, + alignment: Alignment, section: OptionalNullTerminatedString, ) Allocator.Error!Index { const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner)); @@ -6764,7 +6746,7 @@ fn finishFuncInstance( .owns_tv = true, .ty = @import("type.zig").Type.fromInterned(func_ty), .val = @import("Value.zig").fromInterned(func_index), - .alignment = .none, + .alignment = alignment, .@"linksection" = section, .@"addrspace" = fn_owner_decl.@"addrspace", .analysis = .complete, diff --git a/src/Module.zig b/src/Module.zig index 8f6def21ae..bfc5a35e10 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3596,6 +3596,18 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { log.debug("semaDecl '{d}'", .{@intFromEnum(decl_index)}); + const old_has_tv = decl.has_tv; + // The following values are ignored if `!old_has_tv` + const old_ty = decl.ty; + const old_val = decl.val; + const old_align = decl.alignment; + const old_linksection = decl.@"linksection"; + const old_addrspace = decl.@"addrspace"; + const old_is_inline = if (decl.getOwnedFunction(mod)) |prev_func| + prev_func.analysis(ip).state == .inline_only + else + false; + const decl_inst = decl.zir_decl_index.unwrap().?.resolve(ip); const gpa = mod.gpa; @@ -3733,141 +3745,96 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { }; } - switch (ip.indexToKey(decl_tv.val.toIntern())) { - .func => |func| { - const owns_tv = func.owner_decl == decl_index; - if (owns_tv) { - var prev_type_has_bits = false; - var prev_is_inline = false; - var type_changed = true; - - if (decl.has_tv) { - prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod); - type_changed = !decl.ty.eql(decl_tv.ty, mod); - if (decl.getOwnedFunction(mod)) |prev_func| { - prev_is_inline = prev_func.analysis(ip).state == .inline_only; - } - } - - decl.ty = decl_tv.ty; - decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); - // linksection, align, and addrspace were already set by Sema - decl.has_tv = true; - decl.owns_tv = owns_tv; - decl.analysis = .complete; - - const is_inline = decl.ty.fnCallingConvention(mod) == .Inline; - if (decl.is_exported) { - const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) }; - if (is_inline) { - return sema.fail(&block_scope, export_src, "export of inline function", .{}); - } - // The scope needs to have the decl in it. - try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); - } - // TODO: align, linksection, addrspace? - const changed = type_changed or is_inline != prev_is_inline; - return .{ - .invalidate_decl_val = changed, - .invalidate_decl_ref = changed, - }; - } - }, - else => {}, - } - - decl.owns_tv = false; - var queue_linker_work = false; - var is_extern = false; + var queue_linker_work = true; + var is_func = false; + var is_inline = false; switch (decl_tv.val.toIntern()) { .generic_poison => unreachable, .unreachable_value => unreachable, else => switch (ip.indexToKey(decl_tv.val.toIntern())) { - .variable => |variable| if (variable.decl == decl_index) { - decl.owns_tv = true; - queue_linker_work = true; + .variable => |variable| { + decl.owns_tv = variable.decl == decl_index; + queue_linker_work = decl.owns_tv; }, - .extern_func => |extern_fn| if (extern_fn.decl == decl_index) { - decl.owns_tv = true; - queue_linker_work = true; - is_extern = true; + .extern_func => |extern_func| { + decl.owns_tv = extern_func.decl == decl_index; + queue_linker_work = decl.owns_tv; + is_func = decl.owns_tv; }, - .func => {}, - - else => { - queue_linker_work = true; + .func => |func| { + decl.owns_tv = func.owner_decl == decl_index; + queue_linker_work = false; + is_inline = decl.owns_tv and decl_tv.ty.fnCallingConvention(mod) == .Inline; + is_func = decl.owns_tv; }, + + else => {}, }, } - const old_has_tv = decl.has_tv; - // The following values are ignored if `!old_has_tv` - const old_ty = decl.ty; - const old_val = decl.val; - const old_align = decl.alignment; - const old_linksection = decl.@"linksection"; - const old_addrspace = decl.@"addrspace"; - decl.ty = decl_tv.ty; decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); - decl.alignment = blk: { - const align_body = decl_bodies.align_body orelse break :blk .none; - const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst); - break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref); - }; - decl.@"linksection" = blk: { - const linksection_body = decl_bodies.linksection_body orelse break :blk .none; - const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst); - const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{ - .needed_comptime_reason = "linksection must be comptime-known", - }); - if (mem.indexOfScalar(u8, bytes, 0) != null) { - return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{}); - } else if (bytes.len == 0) { - return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); - } - const section = try ip.getOrPutString(gpa, bytes); - break :blk section.toOptional(); - }; - decl.@"addrspace" = blk: { - const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) { - .variable => .variable, - .extern_func, .func => .function, - else => .constant, + // Function linksection, align, and addrspace were already set by Sema + if (!is_func) { + decl.alignment = blk: { + const align_body = decl_bodies.align_body orelse break :blk .none; + const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst); + break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref); }; - - const target = sema.mod.getTarget(); - - const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) { - .function => target_util.defaultAddressSpace(target, .function), - .variable => target_util.defaultAddressSpace(target, .global_mutable), - .constant => target_util.defaultAddressSpace(target, .global_constant), - else => unreachable, + decl.@"linksection" = blk: { + const linksection_body = decl_bodies.linksection_body orelse break :blk .none; + const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst); + const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{ + .needed_comptime_reason = "linksection must be comptime-known", + }); + if (mem.indexOfScalar(u8, bytes, 0) != null) { + return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{}); + } else if (bytes.len == 0) { + return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); + } + const section = try ip.getOrPutString(gpa, bytes); + break :blk section.toOptional(); }; - const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst); - break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx); - }; + decl.@"addrspace" = blk: { + const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) { + .variable => .variable, + .extern_func, .func => .function, + else => .constant, + }; + + const target = sema.mod.getTarget(); + + const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) { + .function => target_util.defaultAddressSpace(target, .function), + .variable => target_util.defaultAddressSpace(target, .global_mutable), + .constant => target_util.defaultAddressSpace(target, .global_constant), + else => unreachable, + }; + const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst); + break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx); + }; + } decl.has_tv = true; decl.analysis = .complete; const result: SemaDeclResult = if (old_has_tv) .{ - .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or !decl.val.eql(old_val, decl.ty, mod), + .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or + !decl.val.eql(old_val, decl.ty, mod) or + is_inline != old_is_inline, .invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or decl.alignment != old_align or decl.@"linksection" != old_linksection or - decl.@"addrspace" != old_addrspace, + decl.@"addrspace" != old_addrspace or + is_inline != old_is_inline, } else .{ .invalidate_decl_val = true, .invalidate_decl_ref = true, }; - const has_runtime_bits = is_extern or - (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty)); - + const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl.ty)); if (has_runtime_bits) { - // Needed for codegen_decl which will call updateDecl and then the // codegen backend wants full access to the Decl Type. try sema.resolveTypeFully(decl.ty); @@ -3881,6 +3848,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { if (decl.is_exported) { const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) }; + if (is_inline) return sema.fail(&block_scope, export_src, "export of inline function", .{}); // The scope needs to have the decl in it. try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); } diff --git a/src/Sema.zig b/src/Sema.zig index 54d5e6df7d..cf103e7230 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7605,7 +7605,6 @@ fn analyzeCall( .param_types = new_param_types, .return_type = owner_info.return_type, .noalias_bits = owner_info.noalias_bits, - .alignment = if (owner_info.align_is_generic) null else owner_info.alignment, .cc = if (owner_info.cc_is_generic) null else owner_info.cc, .is_var_args = owner_info.is_var_args, .is_noinline = owner_info.is_noinline, @@ -9629,7 +9628,6 @@ fn funcCommon( .comptime_bits = comptime_bits, .return_type = bare_return_type.toIntern(), .cc = cc, - .alignment = alignment, .section_is_generic = section == .generic, .addrspace_is_generic = address_space == null, .is_var_args = var_args, @@ -9640,6 +9638,7 @@ fn funcCommon( if (is_extern) { assert(comptime_bits == 0); assert(cc != null); + assert(alignment != null); assert(section != .generic); assert(address_space != null); assert(!is_generic); @@ -17623,8 +17622,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const field_values = .{ // calling_convention: CallingConvention, (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(), - // alignment: comptime_int, - (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod).toByteUnits(0))).toIntern(), // is_generic: bool, Value.makeBool(func_ty_info.is_generic).toIntern(), // is_var_args: bool, @@ -19701,12 +19698,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air if (inst_data.size != .One) { return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{}); } - const fn_align = mod.typeToFunc(elem_ty).?.alignment; - if (inst_data.flags.has_align and abi_align != .none and fn_align != .none and - abi_align != fn_align) - { - return sema.fail(block, align_src, "function pointer alignment disagrees with function alignment", .{}); - } } else if (inst_data.size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) { return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{}); } else if (inst_data.size == .C) { @@ -21030,7 +21021,6 @@ fn zirReify( .needed_comptime_reason = "operand to @Type must be comptime-known", }); const union_val = ip.indexToKey(val.toIntern()).un; - const target = mod.getTarget(); if (try Value.fromInterned(union_val.val).anyUndef(mod)) return sema.failWithUseOfUndef(block, src); const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?; switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) { @@ -21171,12 +21161,6 @@ fn zirReify( if (ptr_size != .One) { return sema.fail(block, src, "function pointers must be single pointers", .{}); } - const fn_align = mod.typeToFunc(elem_ty).?.alignment; - if (abi_align != .none and fn_align != .none and - abi_align != fn_align) - { - return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{}); - } } else if (ptr_size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) { return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); } else if (ptr_size == .C) { @@ -21429,10 +21413,6 @@ fn zirReify( ip, try ip.getOrPutString(gpa, "calling_convention"), ).?); - const alignment_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, "alignment"), - ).?); const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, try ip.getOrPutString(gpa, "is_generic"), @@ -21461,11 +21441,6 @@ fn zirReify( try sema.checkCallConvSupportsVarArgs(block, src, cc); } - const alignment = alignment: { - const alignment = try sema.validateAlignAllowZero(block, src, try alignment_val.toUnsignedIntAdvanced(sema)); - const default = target_util.defaultFunctionAlignment(target); - break :alignment if (alignment == default) .none else alignment; - }; const return_type = return_type_val.optionalValue(mod) orelse return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{}); @@ -21510,7 +21485,6 @@ fn zirReify( .param_types = param_types, .noalias_bits = noalias_bits, .return_type = return_type.toIntern(), - .alignment = alignment, .cc = cc, .is_var_args = is_var_args, }); @@ -32536,16 +32510,21 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn const mod = sema.mod; try sema.ensureDeclAnalyzed(decl_index); - const decl = mod.declPtr(decl_index); - const decl_tv = try decl.typedValue(); + const decl_tv = try mod.declPtr(decl_index).typedValue(); + const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) { + .variable => |variable| variable.decl, + .extern_func => |extern_func| extern_func.decl, + .func => |func| func.owner_decl, + else => decl_index, + }); // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type try sema.declareDependency(.{ .decl_val = decl_index }); const ptr_ty = try sema.ptrType(.{ .child = decl_tv.ty.toIntern(), .flags = .{ - .alignment = decl.alignment, - .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true, - .address_space = decl.@"addrspace", + .alignment = owner_decl.alignment, + .is_const = if (decl_tv.val.getVariable(mod)) |variable| variable.is_const else true, + .address_space = owner_decl.@"addrspace", }, }); if (analyze_fn_body) { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 8d630480e2..928cc995dc 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1635,7 +1635,7 @@ pub const DeclGen = struct { switch (kind) { .forward => {}, - .complete => if (fn_info.alignment.toByteUnitsOptional()) |a| { + .complete => if (fn_decl.alignment.toByteUnitsOptional()) |a| { try w.print("{}zig_align_fn({})", .{ trailing, a }); trailing = .maybe_space; }, @@ -1666,7 +1666,7 @@ pub const DeclGen = struct { switch (kind) { .forward => { - if (fn_info.alignment.toByteUnitsOptional()) |a| { + if (fn_decl.alignment.toByteUnitsOptional()) |a| { try w.print(" zig_align_fn({})", .{a}); } switch (name) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2a5a187e0d..909f5b056f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2949,8 +2949,8 @@ pub const Object = struct { else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder), } - if (fn_info.alignment != .none) - function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder); + if (decl.alignment != .none) + function_index.setAlignment(decl.alignment.toLlvm(), &o.builder); // Function attributes that are independent of analysis results of the function body. try o.addCommonFnAttributes(&attributes, owner_mod); diff --git a/src/type.zig b/src/type.zig index 664498e353..9ea16d6224 100644 --- a/src/type.zig +++ b/src/type.zig @@ -396,9 +396,6 @@ pub const Type = struct { try writer.writeAll("..."); } try writer.writeAll(") "); - if (fn_info.alignment.toByteUnitsOptional()) |a| { - try writer.print("align({d}) ", .{a}); - } if (fn_info.cc != .Unspecified) { try writer.writeAll("callconv(."); try writer.writeAll(@tagName(fn_info.cc)); @@ -949,12 +946,7 @@ pub const Type = struct { }, // represents machine code; not a pointer - .func_type => |func_type| return .{ - .scalar = if (func_type.alignment != .none) - func_type.alignment - else - target_util.defaultFunctionAlignment(target), - }, + .func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) }, .simple_type => |t| switch (t) { .bool, diff --git a/test/behavior/align.zig b/test/behavior/align.zig index e00fbe6744..671e46501a 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -311,12 +311,6 @@ test "page aligned array on stack" { try expect(number2 == 43); } -fn derp() align(@sizeOf(usize) * 2) i32 { - return 1234; -} -fn noop1() align(1) void {} -fn noop4() align(4) void {} - test "function alignment" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; @@ -325,11 +319,25 @@ test "function alignment" { // function alignment is a compile error on wasm32/wasm64 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest; - try expect(derp() == 1234); - try expect(@TypeOf(noop1) == fn () align(1) void); - try expect(@TypeOf(noop4) == fn () align(4) void); - noop1(); - noop4(); + const S = struct { + fn alignExpr() align(@sizeOf(usize) * 2) i32 { + return 1234; + } + fn align1() align(1) void {} + fn align4() align(4) void {} + }; + + try expect(S.alignExpr() == 1234); + try expect(@TypeOf(S.alignExpr) == fn () i32); + try expect(@TypeOf(&S.alignExpr) == *align(@sizeOf(usize) * 2) const fn () i32); + + S.align1(); + try expect(@TypeOf(S.align1) == fn () void); + try expect(@TypeOf(&S.align1) == *align(1) const fn () void); + + S.align4(); + try expect(@TypeOf(S.align4) == fn () void); + try expect(@TypeOf(&S.align4) == *align(4) const fn () void); } test "implicitly decreasing fn alignment" { @@ -345,7 +353,7 @@ test "implicitly decreasing fn alignment" { try testImplicitlyDecreaseFnAlign(alignedBig, 5678); } -fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(1) i32, answer: i32) !void { +fn testImplicitlyDecreaseFnAlign(ptr: *align(1) const fn () i32, answer: i32) !void { try expect(ptr() == answer); } @@ -368,10 +376,10 @@ test "@alignCast functions" { try expect(fnExpectsOnly1(simple4) == 0x19); } -fn fnExpectsOnly1(ptr: *const fn () align(1) i32) i32 { +fn fnExpectsOnly1(ptr: *align(1) const fn () i32) i32 { return fnExpects4(@alignCast(ptr)); } -fn fnExpects4(ptr: *const fn () align(4) i32) i32 { +fn fnExpects4(ptr: *align(4) const fn () i32) i32 { return ptr(); } fn simple4() align(4) i32 { diff --git a/test/behavior/type.zig b/test/behavior/type.zig index da42672be6..c9290ecc31 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -527,7 +527,6 @@ test "Type.Fn" { { const fn_info = std.builtin.Type{ .Fn = .{ .calling_convention = .C, - .alignment = 0, .is_generic = false, .is_var_args = false, .return_type = void, @@ -643,7 +642,6 @@ test "reified function type params initialized with field pointer" { const Bar = @Type(.{ .Fn = .{ .calling_convention = .Unspecified, - .alignment = 0, .is_generic = false, .is_var_args = false, .return_type = void, diff --git a/test/behavior/type_info.zig b/test/behavior/type_info.zig index d4e3eb3b83..0d54b14c39 100644 --- a/test/behavior/type_info.zig +++ b/test/behavior/type_info.zig @@ -356,16 +356,38 @@ test "type info: function type info" { } fn testFunction() !void { - const fn_info = @typeInfo(@TypeOf(typeInfoFoo)); - try expect(fn_info == .Fn); - try expect(fn_info.Fn.alignment > 0); - try expect(fn_info.Fn.calling_convention == .C); - try expect(!fn_info.Fn.is_generic); - try expect(fn_info.Fn.params.len == 2); - try expect(fn_info.Fn.is_var_args); - try expect(fn_info.Fn.return_type.? == usize); - const fn_aligned_info = @typeInfo(@TypeOf(typeInfoFooAligned)); - try expect(fn_aligned_info.Fn.alignment == 4); + const foo_fn_type = @TypeOf(typeInfoFoo); + const foo_fn_info = @typeInfo(foo_fn_type); + try expect(foo_fn_info.Fn.calling_convention == .C); + try expect(!foo_fn_info.Fn.is_generic); + try expect(foo_fn_info.Fn.params.len == 2); + try expect(foo_fn_info.Fn.is_var_args); + try expect(foo_fn_info.Fn.return_type.? == usize); + const foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFoo)); + try expect(foo_ptr_fn_info.Pointer.size == .One); + try expect(foo_ptr_fn_info.Pointer.is_const); + try expect(!foo_ptr_fn_info.Pointer.is_volatile); + try expect(foo_ptr_fn_info.Pointer.address_space == .generic); + try expect(foo_ptr_fn_info.Pointer.child == foo_fn_type); + try expect(!foo_ptr_fn_info.Pointer.is_allowzero); + try expect(foo_ptr_fn_info.Pointer.sentinel == null); + + const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned); + const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type); + try expect(aligned_foo_fn_info.Fn.calling_convention == .C); + try expect(!aligned_foo_fn_info.Fn.is_generic); + try expect(aligned_foo_fn_info.Fn.params.len == 2); + try expect(aligned_foo_fn_info.Fn.is_var_args); + try expect(aligned_foo_fn_info.Fn.return_type.? == usize); + const aligned_foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFooAligned)); + try expect(aligned_foo_ptr_fn_info.Pointer.size == .One); + try expect(aligned_foo_ptr_fn_info.Pointer.is_const); + try expect(!aligned_foo_ptr_fn_info.Pointer.is_volatile); + try expect(aligned_foo_ptr_fn_info.Pointer.alignment == 4); + try expect(aligned_foo_ptr_fn_info.Pointer.address_space == .generic); + try expect(aligned_foo_ptr_fn_info.Pointer.child == aligned_foo_fn_type); + try expect(!aligned_foo_ptr_fn_info.Pointer.is_allowzero); + try expect(aligned_foo_ptr_fn_info.Pointer.sentinel == null); } extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.C) usize; diff --git a/test/behavior/typename.zig b/test/behavior/typename.zig index 80c9a0619e..c3eefc8de7 100644 --- a/test/behavior/typename.zig +++ b/test/behavior/typename.zig @@ -78,11 +78,9 @@ test "basic" { try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void)); try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void)); - try expectEqualStrings("fn () align(32) void", @typeName(fn () align(32) void)); try expectEqualStrings("fn () callconv(.C) void", @typeName(fn () callconv(.C) void)); - try expectEqualStrings("fn () align(32) callconv(.C) void", @typeName(fn () align(32) callconv(.C) void)); - try expectEqualStrings("fn (...) align(32) callconv(.C) void", @typeName(fn (...) align(32) callconv(.C) void)); - try expectEqualStrings("fn (u32, ...) align(32) callconv(.C) void", @typeName(fn (u32, ...) align(32) callconv(.C) void)); + try expectEqualStrings("fn (...) callconv(.C) void", @typeName(fn (...) callconv(.C) void)); + try expectEqualStrings("fn (u32, ...) callconv(.C) void", @typeName(fn (u32, ...) callconv(.C) void)); } test "top level decl" { diff --git a/test/cases/compile_errors/function_ptr_alignment.zig b/test/cases/compile_errors/function_ptr_alignment.zig index 995ef8d9b1..cf97e61f40 100644 --- a/test/cases/compile_errors/function_ptr_alignment.zig +++ b/test/cases/compile_errors/function_ptr_alignment.zig @@ -1,28 +1,16 @@ -comptime { - var a: *align(2) @TypeOf(foo) = undefined; - _ = &a; -} -fn foo() void {} +fn align1() align(1) void {} +fn align2() align(2) void {} comptime { - var a: *align(1) fn () void = undefined; - _ = &a; -} -comptime { - var a: *align(2) fn () align(2) void = undefined; - _ = &a; -} -comptime { - var a: *align(2) fn () void = undefined; - _ = &a; -} -comptime { - var a: *align(1) fn () align(2) void = undefined; - _ = &a; + _ = @as(*align(1) const fn () void, &align2); + _ = @as(*align(1) const fn () void, &align1); + _ = @as(*align(2) const fn () void, &align2); + _ = @as(*align(2) const fn () void, &align1); } // error // backend=stage2 // target=native // -// :20:19: error: function pointer alignment disagrees with function alignment +// :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void' +// :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2' diff --git a/test/cases/compile_errors/inferring_error_set_of_function_pointer.zig b/test/cases/compile_errors/inferring_error_set_of_function_pointer.zig deleted file mode 100644 index ce1b276360..0000000000 --- a/test/cases/compile_errors/inferring_error_set_of_function_pointer.zig +++ /dev/null @@ -1,9 +0,0 @@ -comptime { - const z: ?fn () !void = null; -} - -// error -// backend=stage2 -// target=native -// -// :2:21: error: function prototype may not have inferred error set diff --git a/test/cases/compile_errors/invalid_function_types.zig b/test/cases/compile_errors/invalid_function_types.zig new file mode 100644 index 0000000000..e4553d22f1 --- /dev/null +++ b/test/cases/compile_errors/invalid_function_types.zig @@ -0,0 +1,25 @@ +comptime { + _ = fn name() void; +} +comptime { + _ = fn () align(128) void; +} +comptime { + _ = fn () addrspace(.generic) void; +} +comptime { + _ = fn () linksection("section") void; +} +comptime { + _ = fn () !void; +} + +// error +// backend=stage2 +// target=native +// +// :2:12: error: function type cannot have a name +// :5:21: error: function type cannot have an alignment +// :8:26: error: function type cannot have an addrspace +// :11:27: error: function type cannot have a linksection +// :14:15: error: function type cannot have an inferred error set diff --git a/test/cases/compile_errors/passing_an_under-aligned_function_pointer.zig b/test/cases/compile_errors/passing_an_under-aligned_function_pointer.zig index c6b06f7329..e37441563b 100644 --- a/test/cases/compile_errors/passing_an_under-aligned_function_pointer.zig +++ b/test/cases/compile_errors/passing_an_under-aligned_function_pointer.zig @@ -1,7 +1,7 @@ export fn entry() void { testImplicitlyDecreaseFnAlign(alignedSmall, 1234); } -fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(8) i32, answer: i32) void { +fn testImplicitlyDecreaseFnAlign(ptr: *align(8) const fn () i32, answer: i32) void { if (ptr() != answer) unreachable; } fn alignedSmall() align(4) i32 { @@ -12,5 +12,5 @@ fn alignedSmall() align(4) i32 { // backend=stage2 // target=x86_64-linux // -// :2:35: error: expected type '*const fn () align(8) i32', found '*const fn () align(4) i32' +// :2:35: error: expected type '*align(8) const fn () i32', found '*align(4) const fn () i32' // :2:35: note: pointer alignment '4' cannot cast into pointer alignment '8' diff --git a/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig b/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig index bb2c4bbe62..4ac1312440 100644 --- a/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig +++ b/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig @@ -1,7 +1,6 @@ const Foo = @Type(.{ .Fn = .{ .calling_convention = .Unspecified, - .alignment = 0, .is_generic = true, .is_var_args = false, .return_type = u0, diff --git a/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig b/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig index 678fbe3ed7..23ea4f2095 100644 --- a/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig +++ b/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig @@ -1,7 +1,6 @@ const Foo = @Type(.{ .Fn = .{ .calling_convention = .Unspecified, - .alignment = 0, .is_generic = false, .is_var_args = true, .return_type = u0, diff --git a/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig b/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig index d348a0c908..073cf0f4cc 100644 --- a/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig +++ b/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig @@ -1,7 +1,6 @@ const Foo = @Type(.{ .Fn = .{ .calling_convention = .Unspecified, - .alignment = 0, .is_generic = false, .is_var_args = false, .return_type = null,