I believe Clang is correct here. GCC should not be accepting the code.
The reason is the way overload resolution for constructors for the object copy occurring in a return
statement is specified in [class.copy] p32
(emphasis mine):
When the criteria for elision of a copy/move constructor are met,
[...], and the object to be copied is designated by an lvalue, [...],
overload resolution to select the constructor for the copy is first
performed as if the object were designated by an rvalue. If the first
overload resolution fails or was not performed, or if the type of
the first parameter of the selected constructor is not an rvalue
reference to the object's type (possibly cv-qualified), overload
resolution is performed again, considering the object as an lvalue.
In this example, the criteria for elision are met (by the first bullet in [class.copy] p31
) and the object to be copied is designated by an lvalue, so this paragraph applies.
Overload resolution is first attempted as if the object were designated by an rvalue. The explicit
constructors are not candidates (see below for an explanation of why), so the Derived(Base&&)
constructor is selected. However, this falls under "the type of the first parameter of the selected constructor is not an rvalue reference to the object's type" (instead, it's an rvalue reference to the type of the object's base class), so overload resolution should be performed again, considering the object as an lvalue.
This second overload resolution fails, because the only viable constructor (again, the explicit
constructors are not candidates) has an rvalue reference parameter, which cannot bind to the lvalue. Clang shows the resulting overload resolution failure error.
To complete the explanation, here's why explicit
constructors are not candidates for either overload resolution (all emphasis is mine).
First, [dcl.init] p15
says that:
The initialization that occurs in the = form of a
brace-or-equal-initializer or condition (6.4), as well as in argument
passing, function return, throwing an exception (15.1), handling an
exception (15.3), and aggregate member initialization (8.5.1), is
called copy-initialization."
Next, we look at [over.match.ctor] p1
:
For copy-initialization, the candidate functions are all the converting
constructors (12.3.1) of that class.
Finally, we see that explicit
constructors are not converting constructors in [class.conv.ctor] p1
:
A constructor declared without the function-specifier
explicit
specifies a conversion from the types of its parameters to the type of its class. Such a constructor is called a converting
constructor.