aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaDeclCXX.cpp27
-rw-r--r--test/CXX/special/class.copy/p11.0x.copy.cpp12
-rw-r--r--test/CXX/special/class.copy/p23-cxx11.cpp14
3 files changed, 44 insertions, 9 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a4528eda0f..2a5c0dae43 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
}
diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp
index 2274700c5b..fab3b9dd7b 100644
--- a/test/CXX/special/class.copy/p11.0x.copy.cpp
+++ b/test/CXX/special/class.copy/p11.0x.copy.cpp
@@ -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}}
+}
diff --git a/test/CXX/special/class.copy/p23-cxx11.cpp b/test/CXX/special/class.copy/p23-cxx11.cpp
index 62a0843bfa..7c04a82018 100644
--- a/test/CXX/special/class.copy/p23-cxx11.cpp
+++ b/test/CXX/special/class.copy/p23-cxx11.cpp
@@ -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}}
+ }
+}