diff options
| author | Veikka Tuominen <git@vexu.eu> | 2023-04-10 18:48:23 +0300 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2023-05-16 11:33:38 +0300 |
| commit | b91d6ff9e8d3b224d8cfa4ce7f206264fe814f6f (patch) | |
| tree | e6c0ec5a4201e64c323c72c9968b4ee3817699ff /src/Sema.zig | |
| parent | 2286c19c20897727825a6fd8dd63de1ada6724ee (diff) | |
| download | zig-b91d6ff9e8d3b224d8cfa4ce7f206264fe814f6f.tar.gz zig-b91d6ff9e8d3b224d8cfa4ce7f206264fe814f6f.zip | |
add runtime safety for noreturn function returning
Closes #15221
Diffstat (limited to 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 247dea5f63..007717457f 100644 --- a/src/Sema.zig +++ b/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( |
