This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/65869] New: Incorrect overload resolution in function return statement
- From: "botond at mozilla dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Thu, 23 Apr 2015 21:55:52 +0000
- Subject: [Bug c++/65869] New: Incorrect overload resolution in function return statement
- Auto-submitted: auto-generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65869
Bug ID: 65869
Summary: Incorrect overload resolution in function return
statement
Product: gcc
Version: 4.9.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: botond at mozilla dot com
GCC accepts the following code:
struct Base {};
struct Derived : Base {
Derived();
explicit Derived(const Derived&);
explicit Derived(Derived&&);
explicit Derived(const Base&);
Derived(Base&&);
};
Derived foo() {
Derived result;
return result;
}
int main() {
Derived result = foo();
}
I believe this code is invalid. Here's why:
- [class.copy] p32 specifies that overload resolution
to select the constructor for the copy in the return
statement is to be performed in two stages.
- First, it's performed treating the object to be copied
('result' here) as an rvalue.
- Here, the 'Derived(Base&&)' constructor is selected.
(The explicit constructors are not candidates in this
context.)
- However, p32 says that "if the type of the first
parameter of the selected constructor is not an rvalue
reference to the object's type", then overload
resolution is performed again, treating the object as
an rvalue.
- Here, the type of the first parameter of the
selected constructor is 'Base&&'. This is an rvalue
reference, but it's not "to the object's type"
("the object's type" being 'Derived'). Therefore,
this provision is activated.
- The second overload resolution fails, because the only
candidate (again, the explicit constructors are not
candidates) has an rvalue reference parameter, which
cannot bind to the lvalue that we're not treating the
object as being.
A more detailed and better-formatted explanation can be found here [1].
Clang rejects this code, showing the error from the failure
of the second overload resolution:
test.cpp:13:10: error: no matching constructor for initialization of 'Derived'
return result;
^~~~~~
test.cpp:8:5: note: candidate constructor not viable: no known conversion from
'Derived' to 'Base &&' for 1st argument
Derived(Base&&);
^
test.cpp:4:5: note: candidate constructor not viable: requires 0 arguments, but
1 was provided
Derived();
^
[1] http://stackoverflow.com/a/29834426/141719