]> granicus.if.org Git - clang/commitdiff
Take cv-qualifiers on fields of class type into account when determining
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 25 Nov 2013 07:07:05 +0000 (07:07 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 25 Nov 2013 07:07:05 +0000 (07:07 +0000)
whether a defaulted special member function should be deleted.

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

lib/AST/DeclCXX.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/except/except.spec/p14.cpp
test/CXX/special/class.copy/p11.0x.copy.cpp
test/CXX/special/class.copy/p11.0x.move.cpp
test/CXX/special/class.copy/p23-cxx11.cpp

index c880e2812c387dc53811bb6f84ff6f4dae18a043..49cf721579ec475fbc4b9e6d5c57367e799f5976 100644 (file)
@@ -722,6 +722,13 @@ void CXXRecordDecl::addedMember(Decl *D) {
       if (FieldRec->getDefinition()) {
         addedClassSubobject(FieldRec);
 
+        // We may need to perform overload resolution to determine whether a
+        // field can be moved if it's const or volatile qualified.
+        if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) {
+          data().NeedOverloadResolutionForMoveConstructor = true;
+          data().NeedOverloadResolutionForMoveAssignment = true;
+        }
+
         // C++11 [class.ctor]p5, C++11 [class.copy]p11:
         //   A defaulted [special member] for a class X is defined as
         //   deleted if:
index 54eef40043b60820c5e9374ee4611d06bcc6d1dc..28c5af50f144ad62ba29ecc3567af0b2dbce4432 100644 (file)
@@ -4913,6 +4913,10 @@ struct SpecialMemberDeletionInfo {
     // cv-qualifiers on class members don't affect default ctor / dtor calls.
     if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
       Quals = 0;
+    // cv-qualifiers on class members affect the type of both '*this' and the
+    // argument for an assignment.
+    if (IsAssignment)
+      TQ |= Quals;
     return S.LookupSpecialMember(Class, CSM,
                                  ConstArg || (Quals & Qualifiers::Const),
                                  VolatileArg || (Quals & Qualifiers::Volatile),
index dda69e9aad60dc48582e4489404d1609fa3f28ed..945a767584fec9cc9ac5176b5852cad0dfd0c11d 100644 (file)
@@ -44,8 +44,8 @@ namespace PR13381 {
   struct NoThrowMove {
     NoThrowMove(const NoThrowMove &);
     NoThrowMove(NoThrowMove &&) noexcept;
-    NoThrowMove &operator=(const NoThrowMove &);
-    NoThrowMove &operator=(NoThrowMove &&) noexcept;
+    NoThrowMove &operator=(const NoThrowMove &) const;
+    NoThrowMove &operator=(NoThrowMove &&) const noexcept;
   };
   struct NoThrowMoveOnly {
     NoThrowMoveOnly(NoThrowMoveOnly &&) noexcept;
index 011c1e9a87606130df747cb4d4a0aa1c6dfd6028..a334c50e9fdae5990983ecbf6dcdfff4071c5b4a 100644 (file)
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
 
+struct Trivial {};
 struct NonTrivial {
   NonTrivial(const NonTrivial&);
 };
@@ -69,6 +70,12 @@ struct Deleted {
 Deleted Da;
 Deleted Db(Da); // expected-error{{call to implicitly-deleted copy constructor}}
 
+// It's implied (but not stated) that this also applies in the case where
+// overload resolution would fail.
+struct VolatileMember {
+  volatile Trivial vm; // expected-note {{has no copy}}
+} vm1, vm2(vm1); // expected-error {{deleted}}
+
 // -- a direct or virtual base class B that cannot be copied because overload
 //    resolution results in an ambiguity or a function that is deleted or
 //    inaccessible
index ebcce491c404959ca308a1a00d646229639073de..1dce27a8329019646c61a4513c04dac0d427ff10 100644 (file)
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
 
+struct Trivial {};
 struct NonTrivial {
   NonTrivial(NonTrivial&&);
 };
@@ -61,6 +62,24 @@ struct Deleted {
 };
 Deleted::Deleted(Deleted&&) = default; // expected-error{{would delete}}
 
+// It's implied (but not stated) that this should also happen if overload
+// resolution fails.
+struct ConstMember {
+  const Trivial ct;
+  ConstMember(ConstMember&&);
+};
+ConstMember::ConstMember(ConstMember&&) = default; // ok, calls copy ctor
+struct ConstMoveOnlyMember {
+  const NonTrivial cnt;
+  ConstMoveOnlyMember(ConstMoveOnlyMember&&);
+};
+ConstMoveOnlyMember::ConstMoveOnlyMember(ConstMoveOnlyMember&&) = default; // expected-error{{would delete}}
+struct VolatileMember {
+  volatile Trivial vt;
+  VolatileMember(VolatileMember&&);
+};
+VolatileMember::VolatileMember(VolatileMember&&) = default; // expected-error{{would delete}}
+
 // -- a direct or virtual base class B that cannot be moved because overload
 //    resolution results in an ambiguity or a function that is deleted or
 //    inaccessible
index c55d6c268ad8d644e64b08a28e00679a3e134638..de071f050f016f9ecbdca4a303d4c677828aac44 100644 (file)
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -verify %s -std=c++11
 
+struct Trivial {};
+
 template<typename T> struct CopyAssign {
   static T t;
   void test() {
@@ -47,6 +49,9 @@ class InaccessibleCopyAssign {
 class InaccessibleMoveAssign {
   InaccessibleMoveAssign &operator=(InaccessibleMoveAssign &&);
 };
+class NonConstCopyAssign {
+  NonConstCopyAssign &operator=(NonConstCopyAssign &);
+};
 
 // A defaulted copy/move assignment operator for class X is defined as deleted
 // if X has:
@@ -114,6 +119,12 @@ struct D6 {
   D6 &operator=(D6 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}}
   InaccessibleMoveAssign a; // expected-note {{field 'a' has an inaccessible move}}
 };
+struct D7 {
+  const Trivial a; // expected-note 3{{field 'a' has no }}
+};
+struct D8 {
+  volatile Trivial a; // expected-note 3{{field 'a' has no }}
+};
 template struct CopyAssign<D1>; // expected-note {{here}}
 template struct MoveAssign<D2>; // expected-note {{here}}
 template struct MoveOrCopyAssign<D2>; // expected-note {{here}}
@@ -123,6 +134,12 @@ template struct MoveOrCopyAssign<D4>; // expected-note {{here}}
 template struct CopyAssign<D5>; // expected-note {{here}}
 template struct MoveAssign<D6>; // expected-note {{here}}
 template struct MoveOrCopyAssign<D6>; // expected-note {{here}}
+template struct CopyAssign<D7>; // expected-note {{here}}
+template struct MoveAssign<D7>; // expected-note {{here}}
+template struct MoveOrCopyAssign<D7>; // expected-note {{here}}
+template struct CopyAssign<D8>; // expected-note {{here}}
+template struct MoveAssign<D8>; // expected-note {{here}}
+template struct MoveOrCopyAssign<D8>; // expected-note {{here}}
 
 //   -- a direct or virtual base that cannot be copied/moved
 struct E1 : AmbiguousCopyAssign {}; // expected-note {{base class 'AmbiguousCopyAssign' has multiple copy}}
@@ -147,7 +164,7 @@ template struct MoveAssign<E6>; // expected-note {{here}}
 namespace PR13381 {
   struct S {
     S &operator=(const S&);
-    S &operator=(const volatile S&) = delete; // expected-note{{deleted here}}
+    S &operator=(const volatile S&) volatile = delete; // expected-note{{deleted here}}
   };
   struct T {
     volatile S s; // expected-note{{field 's' has a deleted copy assignment}}