mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
stage2: proper semantic analysis of improper returning of implicit void
This commit is contained in:
parent
5f7c7191ab
commit
7a39a038db
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user