Search code examples
c++c++11exceptioncode-generationnoexcept

`std::terminate` invocation in a `noexcept` function with limited visibility - gcc vs clang codegen


Consider the following code snippet:

void f();

void a()          { f(); }
void b() noexcept { f(); }

In the scenario above, the body of f is not visible to the compiler in the current translation unit. Therefore, since b is marked noexcept, additional code must be generated on the caller side to make sure that the exception is caught and std::terminate is invoked.

That's what clang++ -Ofast -std=c++2a does (trunk version):

a(): # @a()
  jmp f() # TAILCALL
b(): # @b()
  push rax
  call f()
  pop rax
  ret
  mov rdi, rax
  call __clang_call_terminate
__clang_call_terminate: # @__clang_call_terminate
  push rax
  call __cxa_begin_catch
  call std::terminate()

However, g++ -Ofast -std=c++2a does not (trunk version):

a():
  jmp f()
b():
  jmp f()

live example on godbolt.org


How does g++ get away with this? Shouldn't code be generated on the caller side as the body of f is not visible?

...or is this just a weird Compiler Explorer quirk?


Solution

  • As @ach answered, there is a bug opened on gcc bug tracker. But if I may say so, it is not a major issue.

    The impact is that an exception will leak instead of terminating the program but:

    • if you want to call terminate on uncaught exception, that's already the case
    • if you want no-throw exception safety guarantee, that doesn't provide it.

    The only case I can think of is during development. Or in environments were it is mandatory to fail if a contract is broken (when life is at stake) ; in this case, compilers and the feature to use are tightly controlled.

    Andrzej is making a good case in his article - noexcept — what for ?