Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 356
Vittorio Romeo Avatar asked Apr 26 '18 16:04

Vittorio Romeo


1 Answers

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 ?

like image 186
Michael Doubez Avatar answered Oct 30 '22 10:10

Michael Doubez