| author | |
| committer | |
| log | 7a39a038dbe99b5189591378eef89ae5c023806d |
| tree | 4581e558c13c8d870577415f4e8ba9cc964ef297 |
| parent | 5f7c7191ab16c4c9320c28652a0d4c4e53af0024 |
4 files changed, 41 insertions(+), 8 deletions(-)
src-self-hosted/Module.zig+2-2| ... | ... | @@ -1345,8 +1345,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1345 | 1345 | |
| 1346 | 1346 | _ = try astgen.blockExpr(self, params_scope, .none, body_block); |
| 1347 | 1347 | |
| 1348 | if (!fn_type.fnReturnType().isNoReturn() and (gen_scope.instructions.items.len == 0 or | |
| 1349 | !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())) | |
| 1348 | if (gen_scope.instructions.items.len == 0 or | |
| 1349 | !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn()) | |
| 1350 | 1350 | { |
| 1351 | 1351 | const src = tree.token_locs[body_block.rbrace].start; |
| 1352 | 1352 | _ = try astgen.addZIRNoOp(self, &gen_scope.base, src, .returnvoid); |
src-self-hosted/zir_sema.zig+20-2| ... | ... | @@ -112,8 +112,17 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | 114 | pub fn analyzeBody(mod: *Module, scope: *Scope, body: zir.Module.Body) !void { |
| 115 | for (body.instructions) |src_inst| { | |
| 116 | src_inst.analyzed_inst = try analyzeInst(mod, scope, src_inst); | |
| 115 | for (body.instructions) |src_inst, i| { | |
| 116 | const analyzed_inst = try analyzeInst(mod, scope, src_inst); | |
| 117 | src_inst.analyzed_inst = analyzed_inst; | |
| 118 | if (analyzed_inst.ty.zigTypeTag() == .NoReturn) { | |
| 119 | for (body.instructions[i..]) |unreachable_inst| { | |
| 120 | if (unreachable_inst.castTag(.dbg_stmt)) |dbg_stmt| { | |
| 121 | return mod.fail(scope, dbg_stmt.base.src, "unreachable code", .{}); | |
| 122 | } | |
| 123 | } | |
| 124 | break; | |
| 125 | } | |
| 117 | 126 | } |
| 118 | 127 | } |
| 119 | 128 | |
| ... | ... | @@ -1216,6 +1225,15 @@ fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError! |
| 1216 | 1225 | |
| 1217 | 1226 | fn analyzeInstRetVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { |
| 1218 | 1227 | const b = try mod.requireRuntimeBlock(scope, inst.base.src); |
| 1228 | if (b.func) |func| { | |
| 1229 | // Need to emit a compile error if returning void is not allowed. | |
| 1230 | const void_inst = try mod.constVoid(scope, inst.base.src); | |
| 1231 | const fn_ty = func.owner_decl.typed_value.most_recent.typed_value.ty; | |
| 1232 | const casted_void = try mod.coerce(scope, fn_ty.fnReturnType(), void_inst); | |
| 1233 | if (casted_void.ty.zigTypeTag() != .Void) { | |
| 1234 | return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, casted_void); | |
| 1235 | } | |
| 1236 | } | |
| 1219 | 1237 | return mod.addNoOp(b, inst.base.src, Type.initTag(.noreturn), .retvoid); |
| 1220 | 1238 | } |
| 1221 | 1239 |
test/stage2/cbe.zig+14-4| ... | ... | @@ -10,13 +10,19 @@ const linux_x64 = std.zig.CrossTarget{ |
| 10 | 10 | |
| 11 | 11 | pub fn addCases(ctx: *TestContext) !void { |
| 12 | 12 | ctx.c("empty start function", linux_x64, |
| 13 | \\export fn _start() noreturn {} | |
| 13 | \\export fn _start() noreturn { | |
| 14 | \\ unreachable; | |
| 15 | \\} | |
| 14 | 16 | , |
| 15 | \\zig_noreturn void _start(void) {} | |
| 17 | \\zig_noreturn void _start(void) { | |
| 18 | \\ zig_unreachable(); | |
| 19 | \\} | |
| 16 | 20 | \\ |
| 17 | 21 | ); |
| 18 | 22 | ctx.c("less empty start function", linux_x64, |
| 19 | \\fn main() noreturn {} | |
| 23 | \\fn main() noreturn { | |
| 24 | \\ unreachable; | |
| 25 | \\} | |
| 20 | 26 | \\ |
| 21 | 27 | \\export fn _start() noreturn { |
| 22 | 28 | \\ main(); |
| ... | ... | @@ -28,7 +34,9 @@ pub fn addCases(ctx: *TestContext) !void { |
| 28 | 34 | \\ main(); |
| 29 | 35 | \\} |
| 30 | 36 | \\ |
| 31 | \\zig_noreturn void main(void) {} | |
| 37 | \\zig_noreturn void main(void) { | |
| 38 | \\ zig_unreachable(); | |
| 39 | \\} | |
| 32 | 40 | \\ |
| 33 | 41 | ); |
| 34 | 42 | // TODO: implement return values |
| ... | ... | @@ -40,6 +48,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 40 | 48 | \\ : [number] "{rax}" (231), |
| 41 | 49 | \\ [arg1] "{rdi}" (0) |
| 42 | 50 | \\ ); |
| 51 | \\ unreachable; | |
| 43 | 52 | \\} |
| 44 | 53 | \\ |
| 45 | 54 | \\export fn _start() noreturn { |
| ... | ... | @@ -62,6 +71,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 62 | 71 | \\ register size_t rax_constant __asm__("rax") = 231; |
| 63 | 72 | \\ register size_t rdi_constant __asm__("rdi") = 0; |
| 64 | 73 | \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); |
| 74 | \\ zig_unreachable(); | |
| 65 | 75 | \\} |
| 66 | 76 | \\ |
| 67 | 77 | ); |
test/stage2/compare_output.zig+5| ... | ... | @@ -26,6 +26,11 @@ pub fn addCases(ctx: *TestContext) !void { |
| 26 | 26 | |
| 27 | 27 | case.addError("", &[_][]const u8{":1:1: error: no entry point found"}); |
| 28 | 28 | |
| 29 | case.addError( | |
| 30 | \\export fn _start() noreturn { | |
| 31 | \\} | |
| 32 | , &[_][]const u8{":2:1: error: expected noreturn, found void"}); | |
| 33 | ||
| 29 | 34 | // Regular old hello world |
| 30 | 35 | case.addCompareOutput( |
| 31 | 36 | \\export fn _start() noreturn { |