mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
parent
2286c19c20
commit
b91d6ff9e8
4 changed files with 55 additions and 4 deletions
|
|
@ -1006,6 +1006,7 @@ pub const panic_messages = struct {
|
|||
pub const for_len_mismatch = "for loop over objects with non-equal lengths";
|
||||
pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
|
||||
pub const memcpy_alias = "@memcpy arguments alias";
|
||||
pub const noreturn_returned = "'noreturn' function returned";
|
||||
};
|
||||
|
||||
pub noinline fn returnError(st: *StackTrace) void {
|
||||
|
|
|
|||
34
src/Sema.zig
34
src/Sema.zig
|
|
@ -7055,15 +7055,38 @@ fn analyzeCall(
|
|||
} },
|
||||
});
|
||||
sema.appendRefsAssumeCapacity(args);
|
||||
|
||||
if (call_tag == .call_always_tail) {
|
||||
if (ensure_result_used) {
|
||||
try sema.ensureResultUsed(block, sema.typeOf(func_inst), call_src);
|
||||
}
|
||||
return sema.handleTailCall(block, call_src, func_ty, func_inst);
|
||||
} else if (block.wantSafety() and func_ty_info.return_type.isNoReturn()) {
|
||||
// Function pointers and extern functions aren't guaranteed to
|
||||
// actually be noreturn so we add a safety check for them.
|
||||
check: {
|
||||
var func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;
|
||||
switch (func_val.tag()) {
|
||||
.function, .decl_ref => {
|
||||
_ = try block.addNoOp(.unreach);
|
||||
return Air.Inst.Ref.unreachable_value;
|
||||
},
|
||||
else => break :check,
|
||||
}
|
||||
}
|
||||
|
||||
try sema.safetyPanic(block, .noreturn_returned);
|
||||
return Air.Inst.Ref.unreachable_value;
|
||||
} else if (func_ty_info.return_type.isNoReturn()) {
|
||||
_ = try block.addNoOp(.unreach);
|
||||
return Air.Inst.Ref.unreachable_value;
|
||||
}
|
||||
break :res func_inst;
|
||||
};
|
||||
|
||||
if (ensure_result_used) {
|
||||
try sema.ensureResultUsed(block, sema.typeOf(result), call_src);
|
||||
}
|
||||
if (call_tag == .call_always_tail) {
|
||||
return sema.handleTailCall(block, call_src, func_ty, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -7556,6 +7579,10 @@ fn instantiateGenericCall(
|
|||
if (call_tag == .call_always_tail) {
|
||||
return sema.handleTailCall(block, call_src, func_ty, result);
|
||||
}
|
||||
if (new_fn_info.return_type.isNoReturn()) {
|
||||
_ = try block.addNoOp(.unreach);
|
||||
return Air.Inst.Ref.unreachable_value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -23441,6 +23468,7 @@ pub const PanicId = enum {
|
|||
for_len_mismatch,
|
||||
memcpy_len_mismatch,
|
||||
memcpy_alias,
|
||||
noreturn_returned,
|
||||
};
|
||||
|
||||
fn addSafetyCheck(
|
||||
|
|
|
|||
|
|
@ -5030,7 +5030,6 @@ pub const FuncGen = struct {
|
|||
}
|
||||
|
||||
if (return_type.isNoReturn() and attr != .AlwaysTail) {
|
||||
_ = self.builder.buildUnreachable();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
23
test/cases/safety/noreturn returned.zig
Normal file
23
test/cases/safety/noreturn returned.zig
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = stack_trace;
|
||||
if (std.mem.eql(u8, message, "'noreturn' function returned")) {
|
||||
std.process.exit(0);
|
||||
}
|
||||
std.process.exit(1);
|
||||
}
|
||||
const T = struct {
|
||||
export fn bar() void {
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
extern fn bar() noreturn;
|
||||
pub fn main() void {
|
||||
_ = T.bar;
|
||||
bar();
|
||||
}
|
||||
// run
|
||||
// backend=llvm
|
||||
// target=native
|
||||
Loading…
Add table
Reference in a new issue