Рассмотрим следующий фрагмент кода:
void f();
void a() { f(); }
void b() noexcept { f(); }
В приведенном выше сценарии тело f
не отображается компилятору в текущей единице перевода. Поэтому, поскольку b
помечено noexcept
, для стороны, выполняющей вызов, должен быть сгенерирован дополнительный код, чтобы убедиться, что исключение перехвачено и std::terminate
вызвано.
Это то, что clang++ -Ofast -std=c++2a
делает (версия транка) :
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()
Однако g++ -Ofast -std=c++2a
не (версия с транком) :
a():
jmp f()
b():
jmp f()
живой пример на godbolt.org
Как g++
это сходит с рук? Разве не должен генерироваться код на стороне вызывающей стороны, поскольку тело f
не видно?
... или это просто странная причуда Compiler Explorer?