authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-14 13:08:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-14 13:08:55-07:00
log7a39a038dbe99b5189591378eef89ae5c023806d
tree4581e558c13c8d870577415f4e8ba9cc964ef297
parent5f7c7191ab16c4c9320c28652a0d4c4e53af0024

stage2: proper semantic analysis of improper returning of implicit void


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 {
13451345
13461346 _ = try astgen.blockExpr(self, params_scope, .none, body_block);
13471347
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())
13501350 {
13511351 const src = tree.token_locs[body_block.rbrace].start;
13521352 _ = 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!
112112}
113113
114114pub 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 }
117126 }
118127}
119128
......@@ -1216,6 +1225,15 @@ fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!
12161225
12171226fn analyzeInstRetVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
12181227 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 }
12191237 return mod.addNoOp(b, inst.base.src, Type.initTag(.noreturn), .retvoid);
12201238}
12211239
test/stage2/cbe.zig+14-4
......@@ -10,13 +10,19 @@ const linux_x64 = std.zig.CrossTarget{
1010
1111pub fn addCases(ctx: *TestContext) !void {
1212 ctx.c("empty start function", linux_x64,
13 \\export fn _start() noreturn {}
13 \\export fn _start() noreturn {
14 \\ unreachable;
15 \\}
1416 ,
15 \\zig_noreturn void _start(void) {}
17 \\zig_noreturn void _start(void) {
18 \\ zig_unreachable();
19 \\}
1620 \\
1721 );
1822 ctx.c("less empty start function", linux_x64,
19 \\fn main() noreturn {}
23 \\fn main() noreturn {
24 \\ unreachable;
25 \\}
2026 \\
2127 \\export fn _start() noreturn {
2228 \\ main();
......@@ -28,7 +34,9 @@ pub fn addCases(ctx: *TestContext) !void {
2834 \\ main();
2935 \\}
3036 \\
31 \\zig_noreturn void main(void) {}
37 \\zig_noreturn void main(void) {
38 \\ zig_unreachable();
39 \\}
3240 \\
3341 );
3442 // TODO: implement return values
......@@ -40,6 +48,7 @@ pub fn addCases(ctx: *TestContext) !void {
4048 \\ : [number] "{rax}" (231),
4149 \\ [arg1] "{rdi}" (0)
4250 \\ );
51 \\ unreachable;
4352 \\}
4453 \\
4554 \\export fn _start() noreturn {
......@@ -62,6 +71,7 @@ pub fn addCases(ctx: *TestContext) !void {
6271 \\ register size_t rax_constant __asm__("rax") = 231;
6372 \\ register size_t rdi_constant __asm__("rdi") = 0;
6473 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
74 \\ zig_unreachable();
6575 \\}
6676 \\
6777 );
test/stage2/compare_output.zig+5
......@@ -26,6 +26,11 @@ pub fn addCases(ctx: *TestContext) !void {
2626
2727 case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
2828
29 case.addError(
30 \\export fn _start() noreturn {
31 \\}
32 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
33
2934 // Regular old hello world
3035 case.addCompareOutput(
3136 \\export fn _start() noreturn {