* C-specific compiler-independent cleanup. This is completely unnecessary if your language supports proper destructors. Unfortunately many still-used and newly-invented languages are completely insufficient here. GNU C has `__attribute__((cleanup))` but it's kind of clunky.
* `continue` or `break` for an outer loop. One of the few things Java did correctly was supporting this directly, with names. A few languages support break/continue by number which is error-prone (fortunately they don't make the same mistake C did in adding `break`-skew for `switch, though unfortunately that usually means they also give up on efficient multi-way dispatch)
* nontrivial variants of `fallthrough` for a `switch`. This is generally an indicator that you should refactor out an `inline` function, but sometimes that makes the code significantly uglier since most languages don't support local-promoted-dynamic variables.
* computed `goto` in interpreter loops, state machines, etc. There is no viable replacement for this, though if your compiler is capable of inlining through an array of function pointers that helps (last I checked, GCC and Clang both failed very badly).
* coroutine implementations. Efficient coroutines have to be built-in to the language anyway (so they can optimize the existence of locals), but languages that support coroutines tend to abandon sanity all ye that enter here.
static int __init init_nfs_fs(void)
line 2046 without goto. See which version you prefer? I don't see goto use as mandatory.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
Destructors throwing isn't broken, it just requires explicit care from the programmer to figure out which option to use in case of conflicting exceptions:
* If the existing unwind is a non-exception-unwind, there is no conflict. Exceptions thrown from a destructor just work™ and change it to an exception-unwind. Since C++11 you have to explicitly mark the dtor as `noexcept(false)` to indicate that you think you know what you are doing.
* If you're already winding due to an exception and want to preserve it, you can check for it at the start of the dtor, and wrap the dtor body in a try-catch which conditionally rethrows if there wasn't already one.
* If you're already unwinding due to an exception and want to ignore it in favor of the new exception ... doing this in C++ is pretty ugly but it's certainly possible. In order to use bare `throw` for the no-additional-exception case, you have to replace all stack variables with `option`-like wrappers so you can manually dispose them during `catch`. Other solutions exist if you don't care about correctly using bare `throw`.
* Or, you can do the safe thing and say "simultaneously unhandled exceptions means the programmer likely never considered how to handle this; give up"
Note that most languages that use `try-finally` have even bigger problems to deal with, since they have to worry about `return` as well as `throw`. Bugs and inconsistencies are frequent here.
[1] or trivially replacing with so many nested if statements.
Pretty much every language created in the past 50-some-odd years, encompassing effectively every language you will actually use, enforce bridled gotos, so for all practical purposes there is no bad use of goto.
But there's a reason even in languages that have it, you use it rarely. Structured programming is really good.