diff --git a/src/Sema.zig b/src/Sema.zig index 6f516229a0..dcfbf52687 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 0000000000..621b8ead25 --- /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 0000000000..002143b0b8 --- /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/test/alignCast_of_zero_sized_types.zig b/test/cases/compile_errors/stage1/alignCast_of_zero_sized_types.zig similarity index 98% rename from test/cases/compile_errors/stage1/test/alignCast_of_zero_sized_types.zig rename to test/cases/compile_errors/stage1/alignCast_of_zero_sized_types.zig index f83d22759c..277301a06d 100644 --- a/test/cases/compile_errors/stage1/test/alignCast_of_zero_sized_types.zig +++ b/test/cases/compile_errors/stage1/alignCast_of_zero_sized_types.zig @@ -20,7 +20,6 @@ export fn qux() void { // 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' 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 c77ccf1a52..0000000000 --- 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/test/ptrToInt_with_pointer_to_zero-sized_type.zig b/test/cases/compile_errors/stage1/ptrToInt_with_pointer_to_zero-sized_type.zig similarity index 94% rename from test/cases/compile_errors/stage1/test/ptrToInt_with_pointer_to_zero-sized_type.zig rename to test/cases/compile_errors/stage1/ptrToInt_with_pointer_to_zero-sized_type.zig index 7c2ba184c4..143dc9135d 100644 --- a/test/cases/compile_errors/stage1/test/ptrToInt_with_pointer_to_zero-sized_type.zig +++ b/test/cases/compile_errors/stage1/ptrToInt_with_pointer_to_zero-sized_type.zig @@ -7,6 +7,5 @@ export fn entry() void { // error // backend=stage1 // target=native -// is_test=1 // // tmp.zig:3:23: error: pointer to size 0 type has no address 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 a010414a57..0000000000 --- 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 b3ffcc6ec2..0000000000 --- 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 4898ac744c..0000000000 --- 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