https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70387
Bug ID: 70387 Summary: -fnon-call-exceptions has no effect Product: gcc Version: 5.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: jwjagersma at gmail dot com Target Milestone: --- I wrote some code to trap a hardware exception, and transfer control to a signal handler which throws a C++ exception. From the documentation, I believe '-fnon-call-exceptions' (and/or '-fasynchronous-unwind-tables') should allow me to do this, but it doesn't work. It appears that gcc doesn't consider that non-call instructions may throw, and silently omits the try/catch block around it. The exception is only caught when the trapped instruction appears in a (non-inlined) function, or inbetween two function calls. --- Output from 'gcc -v': Using built-in specs. COLLECT_GCC=D:\msys64\usr\local\djgpp\i586-pc-msdosdjgpp\bin\gcc.exe COLLECT_LTO_WRAPPER=D:/msys64/usr/local/djgpp/lib/gcc/../../libexec/gcc/i586-pc-msdosdjgpp/5.3.0/lto-wrapper.exe Target: i586-pc-msdosdjgpp Configured with: ../gnu/gcc-5.30/configure --host= --build=x86_64-w64-mingw32 --target=i586-pc-msdosdjgpp --program-prefix=i586-pc-msdosdjgpp- --prefix=/usr/local/djgpp --disable-nls --disable-plugin --disable-lto --enable-lto --enable-libquadmath-support --with-gmp=/home/JW/build-djgpp/build/djcross-gcc-5.3.0/tmpinst --with-mpfr=/home/JW/build-djgpp/build/djcross-gcc-5.3.0/tmpinst --with-mpc=/home/JW/build-djgpp/build/djcross-gcc-5.3.0/tmpinst --enable-version-specific-runtime-libs --enable-languages=c,c++ Thread model: single gcc version 5.3.0 (GCC) --- Example code: (implementation details omitted) void throw_exception() { throw std::runtime_error("Division by zero!"); } __attribute__((noinline)) void try_div0() { cout << 1 / 0 << endl; } void nop() { asm(""); } int main() { // this class traps a hardware exception (division by zero, in this case) and calls the supplied lambda function. exception_wrapper div0_exc { 0, [] (exception_frame* frame, bool) { // only handle exceptions that occured in our own code if (frame->address.segment != get_cs()) return false; // sub <fault esp>, 4; frame->stack.offset -= 4; // get pointer to [<fault esp>] auto* stack = reinterpret_cast<std::uintptr_t *>(frame->stack.offset); // mov [<fault esp>], <fault address>; *stack = frame->address.offset; // resume at throw_exception() frame->address.offset = reinterpret_cast<std::uintptr_t>(throw_exception); return true; } }; try { // thrown from inside a function, this exception is caught. try_div0(); } catch (std::exception& e) { cout << "oops: " << e.what() << endl; } try { // thrown inbetween two function calls, this exception is caught. nop(); cout << 1 / 0 << endl; nop(); } catch (std::exception& e) { cout << "oops: " << e.what() << endl; } try { // throws, but is NOT CAUGHT! cout << 1 / 0 << endl; } catch (std::exception& e) { cout << "oops: " << e.what() << endl; } }