diff --git a/src/Sema.zig b/src/Sema.zig index 6f516229a03c520de68b7335faff53c127707c91..dcfbf52687d926cd76affe8c517ec60774ae2da2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5231,6 +5231,10 @@ fn analyzeCall( .async_kw => return sema.fail(block, call_src, "TODO implement async call", .{}), }; + if (modifier == .never_inline and func_ty_info.cc == .Inline) { + return sema.fail(block, call_src, "no-inline call of inline function", .{}); + } + const gpa = sema.gpa; var is_generic_call = func_ty_info.is_generic; @@ -5270,6 +5274,10 @@ fn analyzeCall( } } + if (is_comptime_call and modifier == .never_inline) { + return sema.fail(block, call_src, "unable to perform 'never_inline' call at compile-time", .{}); + } + const result: Air.Inst.Ref = if (is_inline_call) res: { const func_val = try sema.resolveConstValue(block, func_src, func); const module_fn = switch (func_val.tag()) { @@ -11612,8 +11620,13 @@ fn analyzeCmpUnionTag( ) CompileError!Air.Inst.Ref { const union_ty = try sema.resolveTypeFields(block, un_src, sema.typeOf(un)); const union_tag_ty = union_ty.unionTagType() orelse { - // TODO note at declaration site that says "union foo is not tagged" - return sema.fail(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); + const msg = msg: { + const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); + errdefer msg.destroy(sema.gpa); + try sema.mod.errNoteNonLazy(union_ty.declSrcLoc(sema.mod), msg, "union '{}' is not a tagged union", .{union_ty.fmt(sema.mod)}); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); }; // Coerce both the union and the tag to the union's tag type, and then execute the // enum comparison codepath. @@ -16878,10 +16891,15 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError break :modifier modifier_val.toEnum(std.builtin.CallOptions.Modifier); }; + const is_comptime = extra.flags.is_comptime or block.is_comptime; + const modifier: std.builtin.CallOptions.Modifier = switch (wanted_modifier) { // These can be upgraded to comptime or nosuspend calls. .auto, .never_tail, .no_async => m: { - if (extra.flags.is_comptime) { + if (is_comptime) { + if (wanted_modifier == .never_tail) { + return sema.fail(block, options_src, "unable to perform 'never_tail' call at compile-time", .{}); + } break :m .compile_time; } if (extra.flags.is_nosuspend) { @@ -16891,7 +16909,11 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError }, // These can be upgraded to comptime. nosuspend bit can be safely ignored. .always_tail, .always_inline, .compile_time => m: { - if (extra.flags.is_comptime) { + _ = (try sema.resolveDefinedValue(block, func_src, func)) orelse { + return sema.fail(block, func_src, "modifier '{s}' requires a comptime-known function", .{@tagName(wanted_modifier)}); + }; + + if (is_comptime) { break :m .compile_time; } break :m wanted_modifier; @@ -16900,14 +16922,14 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError if (extra.flags.is_nosuspend) { return sema.fail(block, options_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{}); } - if (extra.flags.is_comptime) { + if (is_comptime) { return sema.fail(block, options_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{}); } break :m wanted_modifier; }, .never_inline => m: { - if (extra.flags.is_comptime) { - return sema.fail(block, options_src, "modifier 'never_inline' cannot be used in combination with comptime function call", .{}); + if (is_comptime) { + return sema.fail(block, options_src, "unable to perform 'never_inline' call at compile-time", .{}); } break :m wanted_modifier; }, diff --git a/test/cases/comparison_of_non-tagged_union_and_enum_literal.zig b/test/cases/comparison_of_non-tagged_union_and_enum_literal.zig new file mode 100644 index 0000000000000000000000000000000000000000..621b8ead259868e26f9532a831e2b014d685ce35 --- /dev/null +++ b/test/cases/comparison_of_non-tagged_union_and_enum_literal.zig @@ -0,0 +1,13 @@ +export fn entry() void { + const U = union { A: u32, B: u64 }; + var u = U{ .A = 42 }; + var ok = u == .A; + _ = ok; +} + +// error +// backend=stage2 +// target=native +// +// :4:14: error: comparison of union and enum literal is only valid for tagged union types +// :2:15: note: union 'tmp.entry.U' is not a tagged union diff --git a/test/cases/compile_errors/bad_usage_of_call.zig b/test/cases/compile_errors/bad_usage_of_call.zig new file mode 100644 index 0000000000000000000000000000000000000000..002143b0b894e2315055d6a755350ba1cb4195b8 --- /dev/null +++ b/test/cases/compile_errors/bad_usage_of_call.zig @@ -0,0 +1,35 @@ +export fn entry1() void { + @call(.{}, foo, {}); +} +export fn entry2() void { + comptime @call(.{ .modifier = .never_inline }, foo, .{}); +} +export fn entry3() void { + comptime @call(.{ .modifier = .never_tail }, foo, .{}); +} +export fn entry4() void { + @call(.{ .modifier = .never_inline }, bar, .{}); +} +export fn entry5(c: bool) void { + var baz = if (c) &baz1 else &baz2; + @call(.{ .modifier = .compile_time }, baz, .{}); +} +pub export fn entry() void { + var call_me: *const fn () void = undefined; + @call(.{ .modifier = .always_inline }, call_me, .{}); +} +fn foo() void {} +fn bar() callconv(.Inline) void {} +fn baz1() void {} +fn baz2() void {} + +// error +// backend=stage2 +// target=native +// +// :2:21: error: expected a tuple, found 'void' +// :5:21: error: unable to perform 'never_inline' call at compile-time +// :8:21: error: unable to perform 'never_tail' call at compile-time +// :11:5: error: no-inline call of inline function +// :15:43: error: modifier 'compile_time' requires a comptime-known function +// :19:44: error: modifier 'always_inline' requires a comptime-known function diff --git a/test/cases/compile_errors/stage1/alignCast_of_zero_sized_types.zig b/test/cases/compile_errors/stage1/alignCast_of_zero_sized_types.zig new file mode 100644 index 0000000000000000000000000000000000000000..277301a06d0ea19626cd66377685e7f13840e2cc --- /dev/null +++ b/test/cases/compile_errors/stage1/alignCast_of_zero_sized_types.zig @@ -0,0 +1,27 @@ +export fn foo() void { + const a: *void = undefined; + _ = @alignCast(2, a); +} +export fn bar() void { + const a: ?*void = undefined; + _ = @alignCast(2, a); +} +export fn baz() void { + const a: []void = undefined; + _ = @alignCast(2, a); +} +export fn qux() void { + const a = struct { + fn a(comptime b: u32) void { _ = b; } + }.a; + _ = @alignCast(2, a); +} + +// error +// backend=stage1 +// target=native +// +// tmp.zig:3:23: error: cannot adjust alignment of zero sized type '*void' +// tmp.zig:7:23: error: cannot adjust alignment of zero sized type '?*void' +// tmp.zig:11:23: error: cannot adjust alignment of zero sized type '[]void' +// tmp.zig:17:23: error: cannot adjust alignment of zero sized type 'fn(u32) anytype' diff --git a/test/cases/compile_errors/stage1/obj/bad_usage_of_call.zig b/test/cases/compile_errors/stage1/obj/bad_usage_of_call.zig deleted file mode 100644 index c77ccf1a525ca5144581da98903e60aa74f19b7b..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/bad_usage_of_call.zig +++ /dev/null @@ -1,30 +0,0 @@ -export fn entry1() void { - @call(.{}, foo, {}); -} -export fn entry2() void { - comptime @call(.{ .modifier = .never_inline }, foo, .{}); -} -export fn entry3() void { - comptime @call(.{ .modifier = .never_tail }, foo, .{}); -} -export fn entry4() void { - @call(.{ .modifier = .never_inline }, bar, .{}); -} -export fn entry5(c: bool) void { - var baz = if (c) baz1 else baz2; - @call(.{ .modifier = .compile_time }, baz, .{}); -} -fn foo() void {} -fn bar() callconv(.Inline) void {} -fn baz1() void {} -fn baz2() void {} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:21: error: expected tuple or struct, found 'void' -// tmp.zig:5:14: error: unable to perform 'never_inline' call at compile-time -// tmp.zig:8:14: error: unable to perform 'never_tail' call at compile-time -// tmp.zig:11:5: error: no-inline call of inline function -// tmp.zig:15:5: error: the specified modifier requires a comptime-known function diff --git a/test/cases/compile_errors/stage1/ptrToInt_with_pointer_to_zero-sized_type.zig b/test/cases/compile_errors/stage1/ptrToInt_with_pointer_to_zero-sized_type.zig new file mode 100644 index 0000000000000000000000000000000000000000..143dc9135d435bbb32aed09820d56961366accd3 --- /dev/null +++ b/test/cases/compile_errors/stage1/ptrToInt_with_pointer_to_zero-sized_type.zig @@ -0,0 +1,11 @@ +export fn entry() void { + var pointer: ?*u0 = null; + var x = @ptrToInt(pointer); + _ = x; +} + +// error +// backend=stage1 +// target=native +// +// tmp.zig:3:23: error: pointer to size 0 type has no address diff --git a/test/cases/compile_errors/stage1/test/alignCast_of_zero_sized_types.zig b/test/cases/compile_errors/stage1/test/alignCast_of_zero_sized_types.zig deleted file mode 100644 index f83d22759cac095e9052141c74b10b7c11b49cef..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/test/alignCast_of_zero_sized_types.zig +++ /dev/null @@ -1,28 +0,0 @@ -export fn foo() void { - const a: *void = undefined; - _ = @alignCast(2, a); -} -export fn bar() void { - const a: ?*void = undefined; - _ = @alignCast(2, a); -} -export fn baz() void { - const a: []void = undefined; - _ = @alignCast(2, a); -} -export fn qux() void { - const a = struct { - fn a(comptime b: u32) void { _ = b; } - }.a; - _ = @alignCast(2, a); -} - -// error -// backend=stage1 -// target=native -// is_test=1 -// -// tmp.zig:3:23: error: cannot adjust alignment of zero sized type '*void' -// tmp.zig:7:23: error: cannot adjust alignment of zero sized type '?*void' -// tmp.zig:11:23: error: cannot adjust alignment of zero sized type '[]void' -// tmp.zig:17:23: error: cannot adjust alignment of zero sized type 'fn(u32) anytype' diff --git a/test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-always_inline.zig b/test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-always_inline.zig deleted file mode 100644 index a010414a57ad349bf2b9065ddc4f08d29c6491fe..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-always_inline.zig +++ /dev/null @@ -1,11 +0,0 @@ -pub export fn entry() void { - var call_me: fn () void = undefined; - @call(.{ .modifier = .always_inline }, call_me, .{}); -} - -// error -// backend=stage1 -// target=native -// is_test=1 -// -// tmp.zig:3:5: error: the specified modifier requires a comptime-known function diff --git a/test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-compile_time.zig b/test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-compile_time.zig deleted file mode 100644 index b3ffcc6ec2bb77169efd68539817c9f80e7b6e11..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-compile_time.zig +++ /dev/null @@ -1,11 +0,0 @@ -pub export fn entry() void { - var call_me: fn () void = undefined; - @call(.{ .modifier = .compile_time }, call_me, .{}); -} - -// error -// backend=stage1 -// target=native -// is_test=1 -// -// tmp.zig:3:5: error: the specified modifier requires a comptime-known function diff --git a/test/cases/compile_errors/stage1/test/comparison_of_non-tagged_union_and_enum_literal.zig b/test/cases/compile_errors/stage1/test/comparison_of_non-tagged_union_and_enum_literal.zig deleted file mode 100644 index 4898ac744ca97c646e04cb59ea1c9fce85ada31b..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/test/comparison_of_non-tagged_union_and_enum_literal.zig +++ /dev/null @@ -1,14 +0,0 @@ -export fn entry() void { - const U = union { A: u32, B: u64 }; - var u = U{ .A = 42 }; - var ok = u == .A; - _ = ok; -} - -// error -// backend=stage1 -// target=native -// is_test=1 -// -// tmp.zig:4:16: error: comparison of union and enum literal is only valid for tagged union types -// tmp.zig:2:15: note: type U is not a tagged union diff --git a/test/cases/compile_errors/stage1/test/ptrToInt_with_pointer_to_zero-sized_type.zig b/test/cases/compile_errors/stage1/test/ptrToInt_with_pointer_to_zero-sized_type.zig deleted file mode 100644 index 7c2ba184c4246887e970e69e17f2b7d92b9b5190..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/test/ptrToInt_with_pointer_to_zero-sized_type.zig +++ /dev/null @@ -1,12 +0,0 @@ -export fn entry() void { - var pointer: ?*u0 = null; - var x = @ptrToInt(pointer); - _ = x; -} - -// error -// backend=stage1 -// target=native -// is_test=1 -// -// tmp.zig:3:23: error: pointer to size 0 type has no address