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