This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/53025] New: [C++11] noexcept operator depends on copy-elision
- From: "daniel.kruegler at googlemail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 17 Apr 2012 22:38:30 +0000
- Subject: [Bug c++/53025] New: [C++11] noexcept operator depends on copy-elision
- Auto-submitted: auto-generated
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53025
Bug #: 53025
Summary: [C++11] noexcept operator depends on copy-elision
Classification: Unclassified
Product: gcc
Version: 4.8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
AssignedTo: unassigned@gcc.gnu.org
ReportedBy: daniel.kruegler@googlemail.com
gcc 4.8.0 20120318 (experimental) in C++11 mode rejects the following code:
//-----
struct A {
A() noexcept {}
A(const A&) noexcept(false) {}
};
void a(A) noexcept {}
static_assert(!noexcept(a(A{})), ""); // Error
//-----
According to [expr.call] p4 parameter construction happens in the caller space,
therefore the copy-initialization need to respect the noexcept(false) of the
copy constructor (The same problem for a type with a corresponding
move-constructor).
There seems to be evidence that the outcome of the test above depends on
compiler optimization (copy-elision):
a) If we change the program slightly to the following form:
//-----
template<class T>
T&& declval() noexcept;
struct A {
A() noexcept {}
A(const A&) noexcept(false) {}
};
void a(A) noexcept {}
static_assert(!noexcept(a(declval<A>())), ""); // OK
//-----
The code is accepted, presumably because 12.8 p31 b3 does no longer hold.
b) An even more convincing argument is that when adding the compiler argument
--no-elide-constructors
the original code becomes accepted as well, thus the outcome indeed depends on
copy-elision taking place or not. The semantics of the noexcept operator
(5.3.7) are described by "potentially evaluated functions calls" and 3.2 p3
says in a note that "A constructor selected to copy or move an object of class
type is odr-used even if the call is actually elided by the implementation", so
this observable behaviour seems to be non-conforming.