You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
avoid undefined behavior from UNREACHABLE on reachable code paths (scp-fs2open#7555)
* avoid undefined behavior from UNREACHABLE on reachable code paths
UNREACHABLE expands to __assume(false) / __builtin_unreachable() in
release builds, which is undefined behavior if the code is ever actually
reached. Many UNREACHABLE sites only guard against unexpected-but-
possible runtime states (values from tables, mission/save files, network
packets, scripting, or user input), so reaching them should degrade
gracefully rather than invoke UB.
Replace UNREACHABLE with Assertion(false, ...) at all such sites. It
still pops an error in debug builds, but in release it is a harmless
no-op that simply falls through to the following code. Sites that are
genuinely unreachable by local invariants (e.g. a switch over a bounded
random number) are left as UNREACHABLE.
A few converted sites had no safe fall-through -- an uninitialized read,
null dereference, or null call would have followed -- so they also get a
minimal recovery: initialize the value, guard the dereference, return
early, or skip the offending item.
Where the converted site was a simple guard of the form
if (x) { Assertion(false, ...); return; }
hoist the check onto the invariant instead:
Assertion(!x, ...);
if (x) { return; }
This states the expectation directly and shows the offending value in
the debug popup, while keeping the same graceful runtime degradation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* addendum
After consultation with Lafiel, use UNREACHABLE in situations that are effectively impossible even if not provably impossible. UNREACHABLE = "this shouldn't ever happen"; Assertion = "if this ever happens, it's a coding error". Also fix a few other sites and change a couple to Warnings.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: code/ai/aibig.cpp
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1870,7 +1870,7 @@ void ai_big_strafe()
1870
1870
1871
1871
/*
1872
1872
if ( aip->goal_objnum != aip->target_objnum ) {
1873
-
UNREACHABLE("The goal objnum does not match the target objnum in ai_big_strafe(), please report to the SCP!"); // what is going on here? - Get Alan
1873
+
Assertion(false, "The goal objnum does not match the target objnum in ai_big_strafe(), please report to the SCP!"); // what is going on here? - Get Alan
Assertion(evaded != evader, "Ship %s is trying to evade itself. Please report to the SCP!", Ships[evader->instance].ship_name); // Bogus! Who tried to get me to evade myself! Trace out and fix!
2737
2738
if (evaded == evader) {
2738
-
UNREACHABLE("Ship %s is trying to evade itself. Please report to the SCP!", Ships[evader->instance].ship_name); // Bogus! Who tried to get me to evade myself! Trace out and fix!
Assertion(guard_objp != Pl_objp, "The ship %s has been found to be guarding itself in ai_guard. Please report to the SCP!", shipp->ship_name); // This seems illegal. Why is a ship guarding itself?
11023
11024
if (guard_objp == Pl_objp) {
11024
-
UNREACHABLE("The ship %s has been found to be guarding itself in ai_guard. Please report to the SCP!", shipp->ship_name); // This seems illegal. Why is a ship guarding itself?
11025
11025
aip->guard_objnum = -1;
11026
11026
return;
11027
11027
}
@@ -13889,7 +13889,7 @@ int ai_acquire_emerge_path(object *pl_objp, int parent_objnum, int allowed_path_
13889
13889
// Cyborg: to avoid divide by zero and avoid a logic path that should not exist check for 0 allowed paths -- Coverity 1523287
13890
13890
if (num_allowed_paths == 0) {
13891
13891
bay_path = Ai_last_arrive_path % bay->num_paths;
13892
-
UNREACHABLE("Parent_shipp in ai_acquire_emerge_path somehow does not have any allowed bay paths!");
13892
+
Assertion(false, "Parent_shipp in ai_acquire_emerge_path somehow does not have any allowed bay paths!");
// short circuit a couple of cases. Ship not arrived shouldn't happen. Ship gone means
2235
2235
// we mark the goal as not achievable.
2236
+
Assertion(status != SHIP_STATUS_NOT_ARRIVED, "Ship %s cannot rearm a target %s that hasn't arrived; get Allender or a SCP member", shipp->ship_name, aigp->target_name); // get Allender. this shouldn't happen!!!
2236
2237
if ( status == SHIP_STATUS_NOT_ARRIVED ) {
2237
-
UNREACHABLE("Ship %s cannot rearm a target %s that hasn't arrived; get Allender or a SCP member", shipp->ship_name, aigp->target_name); // get Allender. this shouldn't happen!!!
2238
2238
return ai_achievability::NOT_ACHIEVABLE;
2239
2239
}
2240
2240
2241
2241
if ( status == SHIP_STATUS_GONE )
2242
2242
return ai_achievability::NOT_ACHIEVABLE;
2243
2243
2244
+
Assertion(target_ship_entry && target_ship_entry->has_shipp(), "Target name %s is not an arrived ship!", aigp->target_name);
2244
2245
if ( !target_ship_entry || !target_ship_entry->has_shipp() ) {
2245
-
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
0 commit comments