Commit 7a39a038db
Changed files (4)
src-self-hosted
test
src-self-hosted/Module.zig
@@ -1345,8 +1345,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
_ = try astgen.blockExpr(self, params_scope, .none, body_block);
- if (!fn_type.fnReturnType().isNoReturn() and (gen_scope.instructions.items.len == 0 or
- !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn()))
+ if (gen_scope.instructions.items.len == 0 or
+ !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())
{
const src = tree.token_locs[body_block.rbrace].start;
_ = try astgen.addZIRNoOp(self, &gen_scope.base, src, .returnvoid);
src-self-hosted/zir_sema.zig
@@ -112,8 +112,17 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
}
pub fn analyzeBody(mod: *Module, scope: *Scope, body: zir.Module.Body) !void {
- for (body.instructions) |src_inst| {
- src_inst.analyzed_inst = try analyzeInst(mod, scope, src_inst);
+ for (body.instructions) |src_inst, i| {
+ const analyzed_inst = try analyzeInst(mod, scope, src_inst);
+ src_inst.analyzed_inst = analyzed_inst;
+ if (analyzed_inst.ty.zigTypeTag() == .NoReturn) {
+ for (body.instructions[i..]) |unreachable_inst| {
+ if (unreachable_inst.castTag(.dbg_stmt)) |dbg_stmt| {
+ return mod.fail(scope, dbg_stmt.base.src, "unreachable code", .{});
+ }
+ }
+ break;
+ }
}
}
@@ -1216,6 +1225,15 @@ fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!
fn analyzeInstRetVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
const b = try mod.requireRuntimeBlock(scope, inst.base.src);
+ if (b.func) |func| {
+ // Need to emit a compile error if returning void is not allowed.
+ const void_inst = try mod.constVoid(scope, inst.base.src);
+ const fn_ty = func.owner_decl.typed_value.most_recent.typed_value.ty;
+ const casted_void = try mod.coerce(scope, fn_ty.fnReturnType(), void_inst);
+ if (casted_void.ty.zigTypeTag() != .Void) {
+ return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, casted_void);
+ }
+ }
return mod.addNoOp(b, inst.base.src, Type.initTag(.noreturn), .retvoid);
}
test/stage2/cbe.zig
@@ -10,13 +10,19 @@ const linux_x64 = std.zig.CrossTarget{
pub fn addCases(ctx: *TestContext) !void {
ctx.c("empty start function", linux_x64,
- \\export fn _start() noreturn {}
+ \\export fn _start() noreturn {
+ \\ unreachable;
+ \\}
,
- \\zig_noreturn void _start(void) {}
+ \\zig_noreturn void _start(void) {
+ \\ zig_unreachable();
+ \\}
\\
);
ctx.c("less empty start function", linux_x64,
- \\fn main() noreturn {}
+ \\fn main() noreturn {
+ \\ unreachable;
+ \\}
\\
\\export fn _start() noreturn {
\\ main();
@@ -28,7 +34,9 @@ pub fn addCases(ctx: *TestContext) !void {
\\ main();
\\}
\\
- \\zig_noreturn void main(void) {}
+ \\zig_noreturn void main(void) {
+ \\ zig_unreachable();
+ \\}
\\
);
// TODO: implement return values
@@ -40,6 +48,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\ : [number] "{rax}" (231),
\\ [arg1] "{rdi}" (0)
\\ );
+ \\ unreachable;
\\}
\\
\\export fn _start() noreturn {
@@ -62,6 +71,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\ register size_t rax_constant __asm__("rax") = 231;
\\ register size_t rdi_constant __asm__("rdi") = 0;
\\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
+ \\ zig_unreachable();
\\}
\\
);
test/stage2/compare_output.zig
@@ -26,6 +26,11 @@ pub fn addCases(ctx: *TestContext) !void {
case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
+ case.addError(
+ \\export fn _start() noreturn {
+ \\}
+ , &[_][]const u8{":2:1: error: expected noreturn, found void"});
+
// Regular old hello world
case.addCompareOutput(
\\export fn _start() noreturn {