Vittorio Romeo
Vittorio Romeo

Reputation: 93364

`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?

Upvotes: 10

Views: 1320

Answers (1)

Michael Doubez
Michael Doubez

Reputation: 6903

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 ?

Upvotes: 1

Related Questions