| author | |
| committer | |
| log | 03b356e34af37d74cf92087c0303a1b2c74d3afc |
| tree | 3c1766f4e41c96ddc64fb65d6756453768b2bff6 |
| parent | 3204d00a5e7fe119b690e921138a439fb84dff5b |
11 files changed, 115 insertions(+), 113 deletions(-)
src/Sema.zig+29-7| ... | ... | @@ -5231,6 +5231,10 @@ fn analyzeCall( |
| 5231 | 5231 | .async_kw => return sema.fail(block, call_src, "TODO implement async call", .{}), |
| 5232 | 5232 | }; |
| 5233 | 5233 | |
| 5234 | if (modifier == .never_inline and func_ty_info.cc == .Inline) { | |
| 5235 | return sema.fail(block, call_src, "no-inline call of inline function", .{}); | |
| 5236 | } | |
| 5237 | ||
| 5234 | 5238 | const gpa = sema.gpa; |
| 5235 | 5239 | |
| 5236 | 5240 | var is_generic_call = func_ty_info.is_generic; |
| ... | ... | @@ -5270,6 +5274,10 @@ fn analyzeCall( |
| 5270 | 5274 | } |
| 5271 | 5275 | } |
| 5272 | 5276 | |
| 5277 | if (is_comptime_call and modifier == .never_inline) { | |
| 5278 | return sema.fail(block, call_src, "unable to perform 'never_inline' call at compile-time", .{}); | |
| 5279 | } | |
| 5280 | ||
| 5273 | 5281 | const result: Air.Inst.Ref = if (is_inline_call) res: { |
| 5274 | 5282 | const func_val = try sema.resolveConstValue(block, func_src, func); |
| 5275 | 5283 | const module_fn = switch (func_val.tag()) { |
| ... | ... | @@ -11612,8 +11620,13 @@ fn analyzeCmpUnionTag( |
| 11612 | 11620 | ) CompileError!Air.Inst.Ref { |
| 11613 | 11621 | const union_ty = try sema.resolveTypeFields(block, un_src, sema.typeOf(un)); |
| 11614 | 11622 | const union_tag_ty = union_ty.unionTagType() orelse { |
| 11615 | // TODO note at declaration site that says "union foo is not tagged" | |
| 11616 | return sema.fail(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); | |
| 11623 | const msg = msg: { | |
| 11624 | const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); | |
| 11625 | errdefer msg.destroy(sema.gpa); | |
| 11626 | try sema.mod.errNoteNonLazy(union_ty.declSrcLoc(sema.mod), msg, "union '{}' is not a tagged union", .{union_ty.fmt(sema.mod)}); | |
| 11627 | break :msg msg; | |
| 11628 | }; | |
| 11629 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 11617 | 11630 | }; |
| 11618 | 11631 | // Coerce both the union and the tag to the union's tag type, and then execute the |
| 11619 | 11632 | // enum comparison codepath. |
| ... | ... | @@ -16878,10 +16891,15 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 16878 | 16891 | break :modifier modifier_val.toEnum(std.builtin.CallOptions.Modifier); |
| 16879 | 16892 | }; |
| 16880 | 16893 | |
| 16894 | const is_comptime = extra.flags.is_comptime or block.is_comptime; | |
| 16895 | ||
| 16881 | 16896 | const modifier: std.builtin.CallOptions.Modifier = switch (wanted_modifier) { |
| 16882 | 16897 | // These can be upgraded to comptime or nosuspend calls. |
| 16883 | 16898 | .auto, .never_tail, .no_async => m: { |
| 16884 | if (extra.flags.is_comptime) { | |
| 16899 | if (is_comptime) { | |
| 16900 | if (wanted_modifier == .never_tail) { | |
| 16901 | return sema.fail(block, options_src, "unable to perform 'never_tail' call at compile-time", .{}); | |
| 16902 | } | |
| 16885 | 16903 | break :m .compile_time; |
| 16886 | 16904 | } |
| 16887 | 16905 | if (extra.flags.is_nosuspend) { |
| ... | ... | @@ -16891,7 +16909,11 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 16891 | 16909 | }, |
| 16892 | 16910 | // These can be upgraded to comptime. nosuspend bit can be safely ignored. |
| 16893 | 16911 | .always_tail, .always_inline, .compile_time => m: { |
| 16894 | if (extra.flags.is_comptime) { | |
| 16912 | _ = (try sema.resolveDefinedValue(block, func_src, func)) orelse { | |
| 16913 | return sema.fail(block, func_src, "modifier '{s}' requires a comptime-known function", .{@tagName(wanted_modifier)}); | |
| 16914 | }; | |
| 16915 | ||
| 16916 | if (is_comptime) { | |
| 16895 | 16917 | break :m .compile_time; |
| 16896 | 16918 | } |
| 16897 | 16919 | break :m wanted_modifier; |
| ... | ... | @@ -16900,14 +16922,14 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 16900 | 16922 | if (extra.flags.is_nosuspend) { |
| 16901 | 16923 | return sema.fail(block, options_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{}); |
| 16902 | 16924 | } |
| 16903 | if (extra.flags.is_comptime) { | |
| 16925 | if (is_comptime) { | |
| 16904 | 16926 | return sema.fail(block, options_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{}); |
| 16905 | 16927 | } |
| 16906 | 16928 | break :m wanted_modifier; |
| 16907 | 16929 | }, |
| 16908 | 16930 | .never_inline => m: { |
| 16909 | if (extra.flags.is_comptime) { | |
| 16910 | return sema.fail(block, options_src, "modifier 'never_inline' cannot be used in combination with comptime function call", .{}); | |
| 16931 | if (is_comptime) { | |
| 16932 | return sema.fail(block, options_src, "unable to perform 'never_inline' call at compile-time", .{}); | |
| 16911 | 16933 | } |
| 16912 | 16934 | break :m wanted_modifier; |
| 16913 | 16935 | }, |
test/cases/comparison_of_non-tagged_union_and_enum_literal.zig created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | export fn entry() void { | |
| 2 | const U = union { A: u32, B: u64 }; | |
| 3 | var u = U{ .A = 42 }; | |
| 4 | var ok = u == .A; | |
| 5 | _ = ok; | |
| 6 | } | |
| 7 | ||
| 8 | // error | |
| 9 | // backend=stage2 | |
| 10 | // target=native | |
| 11 | // | |
| 12 | // :4:14: error: comparison of union and enum literal is only valid for tagged union types | |
| 13 | // :2:15: note: union 'tmp.entry.U' is not a tagged union |
test/cases/compile_errors/bad_usage_of_call.zig created+35| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | export fn entry1() void { | |
| 2 | @call(.{}, foo, {}); | |
| 3 | } | |
| 4 | export fn entry2() void { | |
| 5 | comptime @call(.{ .modifier = .never_inline }, foo, .{}); | |
| 6 | } | |
| 7 | export fn entry3() void { | |
| 8 | comptime @call(.{ .modifier = .never_tail }, foo, .{}); | |
| 9 | } | |
| 10 | export fn entry4() void { | |
| 11 | @call(.{ .modifier = .never_inline }, bar, .{}); | |
| 12 | } | |
| 13 | export fn entry5(c: bool) void { | |
| 14 | var baz = if (c) &baz1 else &baz2; | |
| 15 | @call(.{ .modifier = .compile_time }, baz, .{}); | |
| 16 | } | |
| 17 | pub export fn entry() void { | |
| 18 | var call_me: *const fn () void = undefined; | |
| 19 | @call(.{ .modifier = .always_inline }, call_me, .{}); | |
| 20 | } | |
| 21 | fn foo() void {} | |
| 22 | fn bar() callconv(.Inline) void {} | |
| 23 | fn baz1() void {} | |
| 24 | fn baz2() void {} | |
| 25 | ||
| 26 | // error | |
| 27 | // backend=stage2 | |
| 28 | // target=native | |
| 29 | // | |
| 30 | // :2:21: error: expected a tuple, found 'void' | |
| 31 | // :5:21: error: unable to perform 'never_inline' call at compile-time | |
| 32 | // :8:21: error: unable to perform 'never_tail' call at compile-time | |
| 33 | // :11:5: error: no-inline call of inline function | |
| 34 | // :15:43: error: modifier 'compile_time' requires a comptime-known function | |
| 35 | // :19:44: error: modifier 'always_inline' requires a comptime-known function |
test/cases/compile_errors/stage1/alignCast_of_zero_sized_types.zig created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | export fn foo() void { | |
| 2 | const a: *void = undefined; | |
| 3 | _ = @alignCast(2, a); | |
| 4 | } | |
| 5 | export fn bar() void { | |
| 6 | const a: ?*void = undefined; | |
| 7 | _ = @alignCast(2, a); | |
| 8 | } | |
| 9 | export fn baz() void { | |
| 10 | const a: []void = undefined; | |
| 11 | _ = @alignCast(2, a); | |
| 12 | } | |
| 13 | export fn qux() void { | |
| 14 | const a = struct { | |
| 15 | fn a(comptime b: u32) void { _ = b; } | |
| 16 | }.a; | |
| 17 | _ = @alignCast(2, a); | |
| 18 | } | |
| 19 | ||
| 20 | // error | |
| 21 | // backend=stage1 | |
| 22 | // target=native | |
| 23 | // | |
| 24 | // tmp.zig:3:23: error: cannot adjust alignment of zero sized type '*void' | |
| 25 | // tmp.zig:7:23: error: cannot adjust alignment of zero sized type '?*void' | |
| 26 | // tmp.zig:11:23: error: cannot adjust alignment of zero sized type '[]void' | |
| 27 | // tmp.zig:17:23: error: cannot adjust alignment of zero sized type 'fn(u32) anytype' |
test/cases/compile_errors/stage1/obj/bad_usage_of_call.zig deleted-30| ... | ... | @@ -1,30 +0,0 @@ |
| 1 | export fn entry1() void { | |
| 2 | @call(.{}, foo, {}); | |
| 3 | } | |
| 4 | export fn entry2() void { | |
| 5 | comptime @call(.{ .modifier = .never_inline }, foo, .{}); | |
| 6 | } | |
| 7 | export fn entry3() void { | |
| 8 | comptime @call(.{ .modifier = .never_tail }, foo, .{}); | |
| 9 | } | |
| 10 | export fn entry4() void { | |
| 11 | @call(.{ .modifier = .never_inline }, bar, .{}); | |
| 12 | } | |
| 13 | export fn entry5(c: bool) void { | |
| 14 | var baz = if (c) baz1 else baz2; | |
| 15 | @call(.{ .modifier = .compile_time }, baz, .{}); | |
| 16 | } | |
| 17 | fn foo() void {} | |
| 18 | fn bar() callconv(.Inline) void {} | |
| 19 | fn baz1() void {} | |
| 20 | fn baz2() void {} | |
| 21 | ||
| 22 | // error | |
| 23 | // backend=stage1 | |
| 24 | // target=native | |
| 25 | // | |
| 26 | // tmp.zig:2:21: error: expected tuple or struct, found 'void' | |
| 27 | // tmp.zig:5:14: error: unable to perform 'never_inline' call at compile-time | |
| 28 | // tmp.zig:8:14: error: unable to perform 'never_tail' call at compile-time | |
| 29 | // tmp.zig:11:5: error: no-inline call of inline function | |
| 30 | // tmp.zig:15:5: error: the specified modifier requires a comptime-known function |
test/cases/compile_errors/stage1/ptrToInt_with_pointer_to_zero-sized_type.zig created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | export fn entry() void { | |
| 2 | var pointer: ?*u0 = null; | |
| 3 | var x = @ptrToInt(pointer); | |
| 4 | _ = x; | |
| 5 | } | |
| 6 | ||
| 7 | // error | |
| 8 | // backend=stage1 | |
| 9 | // target=native | |
| 10 | // | |
| 11 | // tmp.zig:3:23: error: pointer to size 0 type has no address |
test/cases/compile_errors/stage1/test/alignCast_of_zero_sized_types.zig deleted-28| ... | ... | @@ -1,28 +0,0 @@ |
| 1 | export fn foo() void { | |
| 2 | const a: *void = undefined; | |
| 3 | _ = @alignCast(2, a); | |
| 4 | } | |
| 5 | export fn bar() void { | |
| 6 | const a: ?*void = undefined; | |
| 7 | _ = @alignCast(2, a); | |
| 8 | } | |
| 9 | export fn baz() void { | |
| 10 | const a: []void = undefined; | |
| 11 | _ = @alignCast(2, a); | |
| 12 | } | |
| 13 | export fn qux() void { | |
| 14 | const a = struct { | |
| 15 | fn a(comptime b: u32) void { _ = b; } | |
| 16 | }.a; | |
| 17 | _ = @alignCast(2, a); | |
| 18 | } | |
| 19 | ||
| 20 | // error | |
| 21 | // backend=stage1 | |
| 22 | // target=native | |
| 23 | // is_test=1 | |
| 24 | // | |
| 25 | // tmp.zig:3:23: error: cannot adjust alignment of zero sized type '*void' | |
| 26 | // tmp.zig:7:23: error: cannot adjust alignment of zero sized type '?*void' | |
| 27 | // tmp.zig:11:23: error: cannot adjust alignment of zero sized type '[]void' | |
| 28 | // tmp.zig:17:23: error: cannot adjust alignment of zero sized type 'fn(u32) anytype' |
test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-always_inline.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | pub export fn entry() void { | |
| 2 | var call_me: fn () void = undefined; | |
| 3 | @call(.{ .modifier = .always_inline }, call_me, .{}); | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage1 | |
| 8 | // target=native | |
| 9 | // is_test=1 | |
| 10 | // | |
| 11 | // tmp.zig:3:5: error: the specified modifier requires a comptime-known function |
test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-compile_time.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | pub export fn entry() void { | |
| 2 | var call_me: fn () void = undefined; | |
| 3 | @call(.{ .modifier = .compile_time }, call_me, .{}); | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage1 | |
| 8 | // target=native | |
| 9 | // is_test=1 | |
| 10 | // | |
| 11 | // tmp.zig:3:5: error: the specified modifier requires a comptime-known function |
test/cases/compile_errors/stage1/test/comparison_of_non-tagged_union_and_enum_literal.zig deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | const U = union { A: u32, B: u64 }; | |
| 3 | var u = U{ .A = 42 }; | |
| 4 | var ok = u == .A; | |
| 5 | _ = ok; | |
| 6 | } | |
| 7 | ||
| 8 | // error | |
| 9 | // backend=stage1 | |
| 10 | // target=native | |
| 11 | // is_test=1 | |
| 12 | // | |
| 13 | // tmp.zig:4:16: error: comparison of union and enum literal is only valid for tagged union types | |
| 14 | // tmp.zig:2:15: note: type U is not a tagged union |
test/cases/compile_errors/stage1/test/ptrToInt_with_pointer_to_zero-sized_type.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | var pointer: ?*u0 = null; | |
| 3 | var x = @ptrToInt(pointer); | |
| 4 | _ = x; | |
| 5 | } | |
| 6 | ||
| 7 | // error | |
| 8 | // backend=stage1 | |
| 9 | // target=native | |
| 10 | // is_test=1 | |
| 11 | // | |
| 12 | // tmp.zig:3:23: error: pointer to size 0 type has no address |