202 lines
7.0 KiB
C++
202 lines
7.0 KiB
C++
|
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
|
||
|
|
||
|
struct Trivial {};
|
||
|
struct NonTrivial {
|
||
|
NonTrivial(NonTrivial&&); // expected-note{{copy constructor is implicitly deleted}}
|
||
|
};
|
||
|
struct DeletedCopy {
|
||
|
DeletedCopy(const DeletedCopy&) = delete;
|
||
|
};
|
||
|
|
||
|
// A defaulted move constructor for a class X is defined as deleted if X has:
|
||
|
|
||
|
// -- a variant member with a non-trivial corresponding constructor
|
||
|
union DeletedNTVariant {
|
||
|
NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}}
|
||
|
DeletedNTVariant(DeletedNTVariant&&);
|
||
|
};
|
||
|
DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}}
|
||
|
|
||
|
struct DeletedNTVariant2 {
|
||
|
union {
|
||
|
NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}}
|
||
|
};
|
||
|
DeletedNTVariant2(DeletedNTVariant2&&);
|
||
|
};
|
||
|
DeletedNTVariant2::DeletedNTVariant2(DeletedNTVariant2&&) = default; // expected-error{{would delete}}
|
||
|
|
||
|
// Note, move constructor is not a candidate because it is deleted.
|
||
|
template<typename T> struct DeletedNTVariant3 { // expected-note 2{{default}} expected-note 2{{copy}}
|
||
|
union {
|
||
|
T NT;
|
||
|
};
|
||
|
};
|
||
|
extern DeletedNTVariant3<NonTrivial> dntv3a(0); // expected-error {{no matching}}
|
||
|
extern DeletedNTVariant3<DeletedCopy> dntv3b(0); // expected-error {{no matching}}
|
||
|
|
||
|
// -- a non-static data member of class type M (or array thereof) that cannot be
|
||
|
// copied because overload resolution results in an ambiguity or a function
|
||
|
// that is deleted or inaccessible
|
||
|
struct NoAccess {
|
||
|
NoAccess() = default;
|
||
|
private:
|
||
|
NoAccess(NoAccess&&);
|
||
|
|
||
|
friend struct HasAccess;
|
||
|
};
|
||
|
|
||
|
struct HasNoAccess {
|
||
|
NoAccess NA; // expected-note{{deleted because field 'NA' has an inaccessible move constructor}}
|
||
|
HasNoAccess(HasNoAccess&&);
|
||
|
};
|
||
|
HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}}
|
||
|
|
||
|
struct HasAccess {
|
||
|
NoAccess NA;
|
||
|
HasAccess(HasAccess&&);
|
||
|
};
|
||
|
HasAccess::HasAccess(HasAccess&&) = default;
|
||
|
|
||
|
struct Ambiguity {
|
||
|
Ambiguity(const Ambiguity&&);
|
||
|
Ambiguity(volatile Ambiguity&&);
|
||
|
};
|
||
|
|
||
|
struct IsAmbiguous {
|
||
|
Ambiguity A; // expected-note{{deleted because field 'A' has multiple move constructors}}
|
||
|
IsAmbiguous(IsAmbiguous&&); // expected-note{{copy constructor is implicitly deleted because 'IsAmbiguous' has a user-declared move constructor}}
|
||
|
};
|
||
|
IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}}
|
||
|
|
||
|
struct Deleted {
|
||
|
// FIXME: This diagnostic is slightly wrong: the constructor we select to move
|
||
|
// 'IA' is deleted, but we select the copy constructor (we ignore the move
|
||
|
// constructor, because it was defaulted and deleted).
|
||
|
IsAmbiguous IA; // expected-note{{deleted because field 'IA' has a deleted move constructor}}
|
||
|
Deleted(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 {
|
||
|
// FIXME: This diagnostic is slightly wrong: the constructor we select to move
|
||
|
// 'cnt' is deleted, but we select the copy constructor, because the object is
|
||
|
// const.
|
||
|
const NonTrivial cnt; // expected-note{{deleted because field 'cnt' has a deleted move constructor}}
|
||
|
ConstMoveOnlyMember(ConstMoveOnlyMember&&);
|
||
|
};
|
||
|
ConstMoveOnlyMember::ConstMoveOnlyMember(ConstMoveOnlyMember&&) = default; // expected-error{{would delete}}
|
||
|
struct VolatileMember {
|
||
|
volatile Trivial vt; // expected-note{{deleted because field 'vt' has no move constructor}}
|
||
|
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
|
||
|
struct AmbiguousMoveBase : Ambiguity { // expected-note{{deleted because base class 'Ambiguity' has multiple move constructors}}
|
||
|
AmbiguousMoveBase(AmbiguousMoveBase&&); // expected-note{{copy constructor is implicitly deleted}}
|
||
|
};
|
||
|
AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}}
|
||
|
|
||
|
struct DeletedMoveBase : AmbiguousMoveBase { // expected-note{{deleted because base class 'AmbiguousMoveBase' has a deleted move constructor}}
|
||
|
DeletedMoveBase(DeletedMoveBase&&);
|
||
|
};
|
||
|
DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}}
|
||
|
|
||
|
struct InaccessibleMoveBase : NoAccess { // expected-note{{deleted because base class 'NoAccess' has an inaccessible move constructor}}
|
||
|
InaccessibleMoveBase(InaccessibleMoveBase&&);
|
||
|
};
|
||
|
InaccessibleMoveBase::InaccessibleMoveBase(InaccessibleMoveBase&&) = default; // expected-error{{would delete}}
|
||
|
|
||
|
// -- any direct or virtual base class or non-static data member of a type with
|
||
|
// a destructor that is deleted or inaccessible
|
||
|
struct NoAccessDtor {
|
||
|
NoAccessDtor(NoAccessDtor&&); // expected-note{{copy constructor is implicitly deleted because 'NoAccessDtor' has a user-declared move constructor}}
|
||
|
private:
|
||
|
~NoAccessDtor();
|
||
|
friend struct HasAccessDtor;
|
||
|
};
|
||
|
|
||
|
struct HasNoAccessDtor {
|
||
|
NoAccessDtor NAD; // expected-note {{deleted because field 'NAD' has an inaccessible destructor}}
|
||
|
HasNoAccessDtor(HasNoAccessDtor&&);
|
||
|
};
|
||
|
HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}}
|
||
|
|
||
|
struct HasAccessDtor {
|
||
|
NoAccessDtor NAD;
|
||
|
HasAccessDtor(HasAccessDtor&&);
|
||
|
};
|
||
|
HasAccessDtor::HasAccessDtor(HasAccessDtor&&) = default;
|
||
|
|
||
|
struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has a deleted copy constructor}}
|
||
|
};
|
||
|
extern HasNoAccessDtorBase HNADBa;
|
||
|
HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}
|
||
|
|
||
|
// The restriction on rvalue reference members applies to only the copy
|
||
|
// constructor.
|
||
|
struct RValue {
|
||
|
int &&ri = 1;
|
||
|
RValue(RValue&&);
|
||
|
};
|
||
|
RValue::RValue(RValue&&) = default;
|
||
|
|
||
|
// -- a non-static data member or direct or virtual base class with a type that
|
||
|
// does not have a move constructor and is not trivially copyable
|
||
|
struct CopyOnly {
|
||
|
CopyOnly(const CopyOnly&);
|
||
|
};
|
||
|
|
||
|
struct NonMove {
|
||
|
CopyOnly CO;
|
||
|
NonMove(NonMove&&);
|
||
|
};
|
||
|
NonMove::NonMove(NonMove&&) = default; // ok under DR1402
|
||
|
|
||
|
struct Moveable {
|
||
|
Moveable();
|
||
|
Moveable(Moveable&&);
|
||
|
};
|
||
|
|
||
|
struct HasMove {
|
||
|
Moveable M;
|
||
|
HasMove(HasMove&&);
|
||
|
};
|
||
|
HasMove::HasMove(HasMove&&) = default;
|
||
|
|
||
|
namespace DR1402 {
|
||
|
struct member {
|
||
|
member();
|
||
|
member(const member&);
|
||
|
member& operator=(const member&);
|
||
|
~member();
|
||
|
};
|
||
|
|
||
|
struct A {
|
||
|
member m_;
|
||
|
|
||
|
A() = default;
|
||
|
A(const A&) = default;
|
||
|
A& operator=(const A&) = default;
|
||
|
A(A&&) = default;
|
||
|
A& operator=(A&&) = default;
|
||
|
~A() = default;
|
||
|
};
|
||
|
|
||
|
// ok, A's explicitly-defaulted move operations copy m_.
|
||
|
void f() {
|
||
|
A a, b(a), c(static_cast<A&&>(a));
|
||
|
a = b;
|
||
|
b = static_cast<A&&>(c);
|
||
|
}
|
||
|
}
|