Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleted constructor - MSVC reports an error, Clang doesn't

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.

like image 851
H Bellamy Avatar asked Dec 22 '16 12:12

H Bellamy


2 Answers

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.

like image 83
Columbo Avatar answered Oct 09 '22 23:10

Columbo


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.

like image 37
T.C. Avatar answered Oct 10 '22 01:10

T.C.