]> granicus.if.org Git - clang/commitdiff
In ms mode, a move assignment operator shouldn't mark a copy ctor as deleted.
authorNico Weber <nicolasweber@gmx.de>
Mon, 23 Jan 2012 03:19:29 +0000 (03:19 +0000)
committerNico Weber <nicolasweber@gmx.de>
Mon, 23 Jan 2012 03:19:29 +0000 (03:19 +0000)
MSVC2010's pair class has a move assignment operator but no explicit copy
constructor, which makes it unusable without this change.

For symmetry, let move copy constructors not mark the default assignment
operator as deleted either. Both changes match cl.exe's behavior.  Fixes
pr11826.

Also update the standard excerpt to point to the right paragraph.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148675 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/microsoft-cxx0x.cpp

index 6a24d9e43007b5b439dae759126bd3685cfdc9fc..1371b35ed493f0a8b670c6b3b078d4d95e83f8dd 100644 (file)
@@ -7846,12 +7846,14 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
     PushOnScopeChains(CopyAssignment, S, false);
   ClassDecl->addDecl(CopyAssignment);
   
-  // C++0x [class.copy]p18:
-  //   ... If the class definition declares a move constructor or move
-  //   assignment operator, the implicitly declared copy assignment operator is
-  //   defined as deleted; ...
-  if (ClassDecl->hasUserDeclaredMoveConstructor() ||
-      ClassDecl->hasUserDeclaredMoveAssignment() ||
+  // C++0x [class.copy]p19:
+  //   ....  If the class definition does not explicitly declare a copy
+  //   assignment operator, there is no user-declared move constructor, and
+  //   there is no user-declared move assignment operator, a copy assignment
+  //   operator is implicitly declared as defaulted.
+  if ((ClassDecl->hasUserDeclaredMoveConstructor() &&
+          !getLangOptions().MicrosoftExt) ||
+      ClassDecl->hasUserDeclaredMoveAssignment() &&
       ShouldDeleteCopyAssignmentOperator(CopyAssignment))
     CopyAssignment->setDeletedAsWritten();
   
@@ -8749,12 +8751,14 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
     PushOnScopeChains(CopyConstructor, S, false);
   ClassDecl->addDecl(CopyConstructor);
 
-  // C++0x [class.copy]p7:
-  //   ... If the class definition declares a move constructor or move
-  //   assignment operator, the implicitly declared constructor is defined as
-  //   deleted; ...
+  // C++11 [class.copy]p8:
+  //   ... If the class definition does not explicitly declare a copy
+  //   constructor, there is no user-declared move constructor, and there is no
+  //   user-declared move assignment operator, a copy constructor is implicitly
+  //   declared as defaulted.
   if (ClassDecl->hasUserDeclaredMoveConstructor() ||
-      ClassDecl->hasUserDeclaredMoveAssignment() ||
+      (ClassDecl->hasUserDeclaredMoveAssignment() &&
+          !getLangOptions().MicrosoftExt) ||
       ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
     CopyConstructor->setDeletedAsWritten();
   
index 82966d8a447889077c3a3b6574ceea2294b9579a..a0dbb75e079f0b09476d9c1acc3099e5de0f5699 100644 (file)
@@ -7,4 +7,25 @@ struct A {
 int b = 3;
 A var = {  b }; // expected-warning {{ cannot be narrowed }} expected-note {{override}}
 
+namespace PR11826 {
+  struct pair {
+    pair(int v) { }
+    void operator=(pair&& rhs) { }
+  };
+  void f() {
+    pair p0(3);
+    pair p = p0;
+  }
+}
 
+namespace PR11826_for_symmetry {
+  struct pair {
+    pair(int v) { }
+    pair(pair&& rhs) { }
+  };
+  void f() {
+    pair p0(3);
+    pair p(4);
+    p = p0;
+  }
+}