aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2023-04-10 18:48:23 +0300
committerVeikka Tuominen <git@vexu.eu>2023-05-16 11:33:38 +0300
commitb91d6ff9e8d3b224d8cfa4ce7f206264fe814f6f (patch)
treee6c0ec5a4201e64c323c72c9968b4ee3817699ff /src/Sema.zig
parent2286c19c20897727825a6fd8dd63de1ada6724ee (diff)
downloadzig-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.zig34
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(