forked from OSchip/llvm-project
Take cv-qualifiers on fields of class type into account when determining
whether a defaulted special member function should be deleted. llvm-svn: 195620
This commit is contained in:
parent
52b9cbf880
commit
c91d12ce80
|
@ -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:
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}
|
||||
|
|
Loading…
Reference in New Issue