Consider the following code:
class SILPassPipelinePlan final {
public:
SILPassPipelinePlan() = default;
~SILPassPipelinePlan() = default;
SILPassPipelinePlan(const SILPassPipelinePlan &) = default;
SILPassPipelinePlan(SILPassPipelinePlan &&) = delete;
SILPassPipelinePlan x() {
SILPassPipelinePlan P;
return P;
}
};
int main() {
return 0;
}
MSVC reports the following error:
1>consoleapplication2.cpp(13): error C2280: 'SILPassPipelinePlan::SILPassPipelinePlan(SILPassPipelinePlan &&)': attempting to reference a deleted function
1>consoleapplication2.cpp(8): note: see declaration of 'SILPassPipelinePlan::SILPassPipelinePlan'
Clang and GCC don't.
From a specification point of view, which compiler is correct? Is this an MSVC bug, or a Clang bug?
MSVC is from the latest Visual Studio 2015 Update 3, Clang is version 3.9.0.
C++11 introduced implicit moves in certain scenarios—yours included:
In the following copy-initialization contexts, a move operation might be used instead of a copy operation:
If the expression in a return statement ([stmt.return]) is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or
[…]
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, […]
Clang (the only accepting implementation, btw.) either misinterprets "fails" to include the selection of deleted functions, or applies [over.match.funcs]/8 too laxly. See bug 31025.
All versions of GCC on Wandbox reject this code. Are you by any chance testing this on a Mac and using its Clang-masquerading-as-GCC?
This has nothing to do with P0135. Clang is simply taking an excessively liberal reading of "fails" in what is currently [class.copy.elision]/3, which says that in this situation
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, [...], overload resolution is performed again, considering the object as an lvalue.
That overload resolution doesn't fail; it succeeds and selects the move constructor, which happens to be deleted. That should be the end of the matter.
This has been reported as bug 31025.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With