reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
// 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> dntv3a(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);
  }
}