Still in production, for 20 years now.
> A setjmp/longjmp call pair has undefined behavior if replacing the setjmp and longjmp by catch and throw would invoke any non-trivial destructors for any automatic objects.
Of course, the C++ language runtime is usually written in pure C, and at least one naive implementation of the C++ try/catch mechanism uses setjmp/longjmp under the hood.
Clang on Windows behaves this way! That is, when targeting the Visual C++ runtime, as opposed to MinGW.
With the Visual C++ toolchain and runtime, longjmp behaves like a C++ exception throw and goes through a whole stack unwinding routine, unlike on Unix (and MinGW) where it just sets a few registers and branches. This has the downside of being much slower, but the benefit that longjmp will run destructors of C++ local variables as it unwinds (as well as SEH `__finally` blocks), making it less of a footgun in C++ code.
Visual C++ itself doesn't support GCC extensions like `__attribute__((cleanup))`, but these days Clang is highly compatible with Visual C++ while also supporting GCC extensions.
The program point to where "longjmp" jumps is viewed by the compiler as a function return point, so the compiler assumes that all the other registers hold undefined values.
For most CPUs, the C ABI defines the SIMD registers as being not preserved across function calls, so "setjmp" does not need to save them. Had some of them been defined as preserved registers, "setjmp" would have also saved those.
"setjmp/longjmp" cannot be used in any C++ program, unless all the nested functions that occur between a "setjmp" and a "longjmp" are C functions. This may happen in C libraries which are linked into C++ programs and which may use "setjmp/longjmp" internally, without interfering with C++ objects.
As you say, "attribute(cleanup)" is not something specified in the C language standard, so you cannot expect that "longjmp" will invoke the cleanup function, unless you use a specific libc implementation, whose documentation explicitly says that its "longjmp" will invoke the cleanup functions, when the program is compiled with a certain C compiler. I am not aware of any such "longjmp" implementation.
If you want to use exceptions in a C program, you must use "setjmp/longjmp". If you do not want to use exceptions in a C program, you have no need for them.
The same happens in any other programming language. If you do not want to use exceptions in a C++ program, you have no need to use keywords like "try" and "throw".