[Bug c++/86286] New: Could __attribute__ ((nothrow)) on a noexcept function turn off EH codegen?
redi at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Jun 22 20:17:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86286
Bug ID: 86286
Summary: Could __attribute__ ((nothrow)) on a noexcept function
turn off EH codegen?
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: enhancement
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: redi at gcc dot gnu.org
Target Milestone: ---
We generate ideal code for a noexcept function calling a noexcept function:
int f (int i) noexcept;
int foo (int i) noexcept { return f (i); }
_Z3fooi:
.LFB1:
.cfi_startproc
jmp _Z1fi
.cfi_endproc
.LFE0:
But when a noexcept function calls a non-noexcept function there is additional
code needed to call std::terminate if an exception occurs:
_Z3gooi:
.LFB1:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
.cfi_lsda 0x3,.LLSDA1
jmp _Z1gi
.cfi_endproc
.LFE1:
.globl __gxx_personality_v0
.section .gcc_except_table,"a",@progbits
.LLSDA1:
.byte 0xff
.byte 0xff
.byte 0x1
.uleb128 .LLSDACSE1-.LLSDACSB1
.LLSDACSB1:
.LLSDACSE1:
.text
If we know that the non-noexcept function definitely won't throw (e.g. because
we've explicitly checked its preconditions, or we just have additional
knowledge about the state of the program) we can eliminate that extra code with
a nothrow wrapper:
inline int g2 (int i) __attribute__((always_inline,nothrow));
inline int g2 (int i) { return g(i); }
int good (int i) noexcept { return g2 (i); }
_Z4goodi:
.LFB3:
.cfi_startproc
jmp _Z1gi
.cfi_endproc
.LFE3:
But this is awkward and doesn't scale. It's possible wrap the call in a lambda
using the attribute, but that's still awkward, and less readable:
int good (int i) noexcept {
return [&]() __attribute__((nothrow)) { return g (i); }();
}
Would it be possible for the nothrow attribute to do that automatically when
placed on a noexcept function? i.e. instead of the g2 wrapper we'd just do:
int good (int i) noexcept __attribute__((nothrow));
int good (int i) noexcept { return g (i); }
I'd like this to declare a function that never throws (which 'noexcept'
guarantees), but also never needs to deal with exceptions coming from below it.
There could be code today which uses both noexcept and __attribute__
((nothrow)), maybe for pre-C++11 compatibility:
#ifdef __GNUC__
# define NOTHROW __attribute__((nothrow))
#endif
#if __cplusplus >= 201103L
# define NOEXCEPT noexcept
#else
# define NOEXCEPT
#endif
void f() NOEXCEPT NOTHROW;
If we're concerned about changing the behaviour of this code (from guaranteed
termination in C++11 and later if the function exits via an exception, to UB)
then maybe a new attribute would be better.
More information about the Gcc-bugs
mailing list