* 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) <[email protected]>
* 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) <[email protected]>
* long project will be long
* add shared foundation files
* unify some shared types across both editors
* sexptreemodel framework
* move opf functions to the model
* move shared functions into the model
* move variable/container stuff to the model
* sexptreeactions and ui interface
* wire the model into the ui
* move some shared logic to the model
* move more methods to the model
* move clipboard to model
* create new right click menu model
* begin connecting the new right click menu
* wire up the new right click menu in fred
* wire up the new right click menu in qtfred
* move help text and visuals to model
* move menu option enable disable to model
* wire up sexp_tree to the model
* rename sexp_tree files to sexp_tree_ui
* fix build errors
* fix warning
* remove all opf forwarders
* remove some forwarder methods
* connect qtfred events editor directly to model
* wite plan for unifying tree types
* replace legacy m_mode with treeflags
* fix qtfred campaign dialog
* fix qtfred ship/wing dialog trees
* build error
* documentation
* more documentation
* even more documentation
* move more opf functions to opf file
* clean up context menu function
* move default argument to opf file
* build errors
* fix qtfred dialogs and annoations
* new shared annotations model
* sexp_tree_ui to sexp_tree_view
* documentation pass
* document annotations model
* delete the plan
* move event annotations to the new model
* generic cleanup
* remove some old defines
* cleanup includes
* more cleanup
* parenthesis
* more parenthesis
* variable collisions
* too many parenthesis this time
* clang modernization
* variable names again
* more clang and assertions
* static cast
* clang again
* fix some bugs and issues
* Refactor sexp tree action duplication into SexpTreeActions
* fix a few more minor issues
* avoid clang false positive
* rebase tweaks
* fix annotations issue
* fix typo and two small bugs claude found
* fix event editor tree widget loading
* fix ship and wing sexp tree editors in qtfred
* fix qtfred briefing and debriefing trees
* fix a regression Claude found
* address feedback
* fix annotations for root items in qtfred by copying fred's method
* address feedback
* rescope variables
* clang
Turns out PR #4243 actually introduced a bug that appeared to implement the feature. The previous implementation had the effect of intercepting all keypresses and routing them to the main window. This fixes that bug by using `CDialog` instead of `CWnd`. It also turns out that the `hWnd` window handle for some reason does not match the expected window, but fortunately, this implementation is only called in the correct window so the restriction is not needed.
Override some MFC signal paths to prevent Enter and Escape from doing their default behavior. Also add a "save changes" prompt to the Cancel and Close buttons.
Fixes#4240.