]> granicus.if.org Git - clang/commitdiff
PR13381, part 2: when determining if a defaulted special member function should
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 18 Jul 2012 03:51:16 +0000 (03:51 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 18 Jul 2012 03:51:16 +0000 (03:51 +0000)
be defined as deleted, take cv-qualifiers on class members into account when
looking up the copy or move constructor or assignment operator which will be
used for them.

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

lib/Sema/SemaDeclCXX.cpp
test/CXX/special/class.copy/p11.0x.copy.cpp
test/CXX/special/class.copy/p23-cxx11.cpp

index a4528eda0fad6d3f92a5d2201dbb8716c787decf..2a5c0dae4362ecd1522f1baabdc8407419f4c9f9 100644 (file)
@@ -4235,9 +4235,15 @@ struct SpecialMemberDeletionInfo {
   bool inUnion() const { return MD->getParent()->isUnion(); }
 
   /// Look up the corresponding special member in the given class.
-  Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class) {
+  Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class,
+                                              unsigned Quals) {
     unsigned TQ = MD->getTypeQualifiers();
-    return S.LookupSpecialMember(Class, CSM, ConstArg, VolatileArg,
+    // cv-qualifiers on class members don't affect default ctor / dtor calls.
+    if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
+      Quals = 0;
+    return S.LookupSpecialMember(Class, CSM,
+                                 ConstArg || (Quals & Qualifiers::Const),
+                                 VolatileArg || (Quals & Qualifiers::Volatile),
                                  MD->getRefQualifier() == RQ_RValue,
                                  TQ & Qualifiers::Const,
                                  TQ & Qualifiers::Volatile);
@@ -4249,7 +4255,8 @@ struct SpecialMemberDeletionInfo {
   bool shouldDeleteForField(FieldDecl *FD);
   bool shouldDeleteForAllConstMembers();
 
-  bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj);
+  bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj,
+                                     unsigned Quals);
   bool shouldDeleteForSubobjectCall(Subobject Subobj,
                                     Sema::SpecialMemberOverloadResult *SMOR,
                                     bool IsDtorCallInCtor);
@@ -4330,9 +4337,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 }
 
 /// Check whether we should delete a special member function due to having a
-/// direct or virtual base class or static data member of class type M.
+/// direct or virtual base class or non-static data member of class type M.
 bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
-    CXXRecordDecl *Class, Subobject Subobj) {
+    CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) {
   FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
 
   // C++11 [class.ctor]p5:
@@ -4351,7 +4358,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
   //    that is deleted or inaccessible
   if (!(CSM == Sema::CXXDefaultConstructor &&
         Field && Field->hasInClassInitializer()) &&
-      shouldDeleteForSubobjectCall(Subobj, lookupIn(Class), false))
+      shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals), false))
     return true;
 
   // C++11 [class.ctor]p5, C++11 [class.copy]p11:
@@ -4372,7 +4379,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
 /// having a particular direct or virtual base class.
 bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) {
   CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl();
-  return shouldDeleteForClassSubobject(BaseClass, Base);
+  return shouldDeleteForClassSubobject(BaseClass, Base, 0);
 }
 
 /// Check whether we should delete a special member function due to the class
@@ -4449,7 +4456,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
 
         CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl();
         if (UnionFieldRecord &&
-            shouldDeleteForClassSubobject(UnionFieldRecord, *UI))
+            shouldDeleteForClassSubobject(UnionFieldRecord, *UI,
+                                          UnionFieldType.getCVRQualifiers()))
           return true;
       }
 
@@ -4468,7 +4476,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
       return false;
     }
 
-    if (shouldDeleteForClassSubobject(FieldRecord, FD))
+    if (shouldDeleteForClassSubobject(FieldRecord, FD,
+                                      FieldType.getCVRQualifiers()))
       return true;
   }
 
index 2274700c5bfe391b86d7b7181c0b16dd5d19a669..fab3b9dd7bf1191542f47c565f750a9593835c03 100644 (file)
@@ -119,3 +119,15 @@ struct RValue {
 };
 RValue RVa;
 RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}}
+
+namespace PR13381 {
+  struct S {
+    S(const S&);
+    S(const volatile S&) = delete; // expected-note{{deleted here}}
+  };
+  struct T {
+    volatile S s; // expected-note{{field 's' has a deleted copy constructor}}
+  };
+  T &f();
+  T t = f(); // expected-error{{call to implicitly-deleted copy constructor}}
+}
index 62a0843bfa712c8dddae3a65c339aed63fd18e21..7c04a8201804cd809755b8c45b957e217f5330f6 100644 (file)
@@ -132,3 +132,17 @@ template struct CopyAssign<E3>; // expected-note {{here}}
 template struct MoveAssign<E4>; // expected-note {{here}}
 template struct CopyAssign<E5>; // expected-note {{here}}
 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}}
+  };
+  struct T {
+    volatile S s; // expected-note{{field 's' has a deleted copy assignment}}
+  };
+  void g() {
+    T t;
+    t = T(); // expected-error{{implicitly-deleted copy assignment}}
+  }
+}