Home | History | Annotate | Download | only in class.copy
      1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
      2 
      3 // Tests for implicit (non-)declaration of move constructor and
      4 // assignment: p9, p11, p20, p23.
      5 
      6 // This class, used as a member, allows to distinguish move from copy because
      7 // move operations are no-throw, copy operations aren't.
      8 struct ThrowingCopy {
      9   ThrowingCopy() noexcept;
     10   ThrowingCopy(ThrowingCopy &&) noexcept;
     11   ThrowingCopy(const ThrowingCopy &) noexcept(false);
     12   ThrowingCopy & operator =(ThrowingCopy &&) noexcept;
     13   ThrowingCopy & operator =(const ThrowingCopy &) noexcept(false);
     14 };
     15 
     16 struct HasCopyConstructor {
     17   ThrowingCopy tc;
     18   HasCopyConstructor() noexcept;
     19   HasCopyConstructor(const HasCopyConstructor &) noexcept(false);
     20 };
     21 
     22 struct HasCopyAssignment {
     23   ThrowingCopy tc;
     24   HasCopyAssignment() noexcept;
     25   HasCopyAssignment & operator =(const HasCopyAssignment &) noexcept(false);
     26 };
     27 
     28 struct HasMoveConstructor {
     29   ThrowingCopy tc;
     30   HasMoveConstructor() noexcept;
     31   HasMoveConstructor(HasMoveConstructor &&) noexcept; // expected-note {{copy assignment operator is implicitly deleted because 'HasMoveConstructor' has a user-declared move constructor}}
     32 };
     33 
     34 struct HasMoveAssignment { // expected-note {{implicit copy constructor}}
     35   ThrowingCopy tc;
     36   HasMoveAssignment() noexcept;
     37   HasMoveAssignment & operator =(HasMoveAssignment &&) noexcept;
     38 };
     39 
     40 struct HasDestructor {
     41   ThrowingCopy tc;
     42   HasDestructor() noexcept;
     43   ~HasDestructor() noexcept;
     44 };
     45 
     46 void test_basic_exclusion() {
     47   static_assert(!noexcept(HasCopyConstructor((HasCopyConstructor()))), "");
     48   HasCopyConstructor hcc;
     49   static_assert(!noexcept(hcc = HasCopyConstructor()), "");
     50 
     51   static_assert(!noexcept(HasCopyAssignment((HasCopyAssignment()))), "");
     52   HasCopyAssignment hca;
     53   static_assert(!noexcept(hca = HasCopyAssignment()), "");
     54 
     55   static_assert(noexcept(HasMoveConstructor((HasMoveConstructor()))), "");
     56   HasMoveConstructor hmc;
     57   hmc = HasMoveConstructor(); // expected-error {{object of type 'HasMoveConstructor' cannot be assigned because its copy assignment operator is implicitly deleted}}
     58 
     59   (HasMoveAssignment(HasMoveAssignment())); // expected-error {{uses deleted function}}
     60   HasMoveAssignment hma;
     61   static_assert(noexcept(hma = HasMoveAssignment()), "");
     62 
     63   static_assert(!noexcept(HasDestructor((HasDestructor()))), "");
     64   HasDestructor hd;
     65   static_assert(!noexcept(hd = HasDestructor()), "");
     66 }
     67 
     68 struct PrivateMove {
     69   PrivateMove() noexcept;
     70   PrivateMove(const PrivateMove &) noexcept(false);
     71   PrivateMove & operator =(const PrivateMove &) noexcept(false);
     72 private:
     73   PrivateMove(PrivateMove &&) noexcept;
     74   PrivateMove & operator =(PrivateMove &&) noexcept;
     75 };
     76 
     77 struct InheritsPrivateMove : PrivateMove {};
     78 struct ContainsPrivateMove {
     79   PrivateMove pm;
     80 };
     81 
     82 struct PrivateDestructor {
     83   PrivateDestructor() noexcept;
     84   PrivateDestructor(const PrivateDestructor &) noexcept(false);
     85   PrivateDestructor(PrivateDestructor &&) noexcept;
     86 private:
     87   ~PrivateDestructor() noexcept;
     88 };
     89 
     90 struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{base class 'PrivateDestructor' has an inaccessible destructor}}
     91 struct ContainsPrivateDestructor {
     92   PrivateDestructor pd; // expected-note{{field 'pd' has an inaccessible destructor}}
     93 };
     94 
     95 struct NonTrivialCopyOnly {
     96   NonTrivialCopyOnly() noexcept;
     97   NonTrivialCopyOnly(const NonTrivialCopyOnly &) noexcept(false);
     98   NonTrivialCopyOnly & operator =(const NonTrivialCopyOnly &) noexcept(false);
     99 };
    100 
    101 struct InheritsNonTrivialCopyOnly : NonTrivialCopyOnly {};
    102 struct ContainsNonTrivialCopyOnly {
    103   NonTrivialCopyOnly ntco;
    104 };
    105 
    106 struct ContainsConst {
    107   const int i;
    108   ContainsConst() noexcept;
    109   ContainsConst & operator =(ContainsConst &); // expected-note {{not viable}}
    110 };
    111 
    112 struct ContainsRef {
    113   int &i;
    114   ContainsRef() noexcept;
    115   ContainsRef & operator =(ContainsRef &); // expected-note {{not viable}}
    116 };
    117 
    118 struct Base {
    119   Base & operator =(Base &);
    120 };
    121 struct DirectVirtualBase : virtual Base {}; // expected-note {{copy assignment operator) not viable}}
    122 struct IndirectVirtualBase : DirectVirtualBase {}; // expected-note {{copy assignment operator) not viable}}
    123 
    124 void test_deletion_exclusion() {
    125   // FIXME: How to test the union thing?
    126 
    127   static_assert(!noexcept(InheritsPrivateMove(InheritsPrivateMove())), "");
    128   static_assert(!noexcept(ContainsPrivateMove(ContainsPrivateMove())), "");
    129   InheritsPrivateMove ipm;
    130   static_assert(!noexcept(ipm = InheritsPrivateMove()), "");
    131   ContainsPrivateMove cpm;
    132   static_assert(!noexcept(cpm = ContainsPrivateMove()), "");
    133 
    134   (InheritsPrivateDestructor(InheritsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}}
    135   (ContainsPrivateDestructor(ContainsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}}
    136 
    137   static_assert(!noexcept(InheritsNonTrivialCopyOnly(InheritsNonTrivialCopyOnly())), "");
    138   static_assert(!noexcept(ContainsNonTrivialCopyOnly(ContainsNonTrivialCopyOnly())), "");
    139   InheritsNonTrivialCopyOnly intco;
    140   static_assert(!noexcept(intco = InheritsNonTrivialCopyOnly()), "");
    141   ContainsNonTrivialCopyOnly cntco;
    142   static_assert(!noexcept(cntco = ContainsNonTrivialCopyOnly()), "");
    143 
    144   ContainsConst cc;
    145   cc = ContainsConst(); // expected-error {{no viable}}
    146 
    147   ContainsRef cr;
    148   cr = ContainsRef(); // expected-error {{no viable}}
    149 
    150   DirectVirtualBase dvb;
    151   dvb = DirectVirtualBase(); // expected-error {{no viable}}
    152 
    153   IndirectVirtualBase ivb;
    154   ivb = IndirectVirtualBase(); // expected-error {{no viable}}
    155 }
    156 
    157 struct ContainsRValueRef {
    158   int&& ri;
    159   ContainsRValueRef() noexcept;
    160 };
    161 
    162 void test_contains_rref() {
    163   (ContainsRValueRef(ContainsRValueRef()));
    164 }
    165 
    166 
    167 namespace DR1402 {
    168   struct NonTrivialCopyCtor {
    169     NonTrivialCopyCtor(const NonTrivialCopyCtor &);
    170   };
    171   struct NonTrivialCopyAssign {
    172     NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &);
    173   };
    174 
    175   struct NonTrivialCopyCtorVBase : virtual NonTrivialCopyCtor {
    176     NonTrivialCopyCtorVBase(NonTrivialCopyCtorVBase &&);
    177     NonTrivialCopyCtorVBase &operator=(NonTrivialCopyCtorVBase &&) = default;
    178   };
    179   struct NonTrivialCopyAssignVBase : virtual NonTrivialCopyAssign {
    180     NonTrivialCopyAssignVBase(NonTrivialCopyAssignVBase &&);
    181     NonTrivialCopyAssignVBase &operator=(NonTrivialCopyAssignVBase &&) = default;
    182   };
    183 
    184   struct NonTrivialMoveAssign {
    185     NonTrivialMoveAssign(NonTrivialMoveAssign&&);
    186     NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&);
    187   };
    188   struct NonTrivialMoveAssignVBase : virtual NonTrivialMoveAssign {
    189     NonTrivialMoveAssignVBase(NonTrivialMoveAssignVBase &&);
    190     NonTrivialMoveAssignVBase &operator=(NonTrivialMoveAssignVBase &&) = default;
    191   };
    192 
    193   // DR1402: A non-movable, non-trivially-copyable class type as a subobject no
    194   // longer inhibits the declaration of a move operation.
    195   struct NoMove1 { NonTrivialCopyCtor ntcc; };
    196   struct NoMove2 { NonTrivialCopyAssign ntcc; };
    197   struct NoMove3 : NonTrivialCopyCtor {};
    198   struct NoMove4 : NonTrivialCopyAssign {};
    199   struct NoMove5 : virtual NonTrivialCopyCtor {};
    200   struct NoMove6 : virtual NonTrivialCopyAssign {};
    201   struct NoMove7 : NonTrivialCopyCtorVBase {};
    202   struct NoMove8 : NonTrivialCopyAssignVBase {};
    203 
    204   // DR1402: A non-trivially-move-assignable virtual base class no longer
    205   // inhibits the declaration of a move assignment (even though it might
    206   // move-assign the base class multiple times).
    207   struct NoMove9 : NonTrivialMoveAssign {};
    208   struct NoMove10 : virtual NonTrivialMoveAssign {};
    209   struct NoMove11 : NonTrivialMoveAssignVBase {};
    210 
    211   template<typename T> void test(T t) {
    212     (void)T(static_cast<T&&>(t)); // ok
    213     t = static_cast<T&&>(t); // ok
    214   }
    215   template void test(NoMove1);
    216   template void test(NoMove2);
    217   template void test(NoMove3);
    218   template void test(NoMove4);
    219   template void test(NoMove5);
    220   template void test(NoMove6);
    221   template void test(NoMove7);
    222   template void test(NoMove8);
    223   template void test(NoMove9);
    224   template void test(NoMove10);
    225   template void test(NoMove11);
    226 
    227   struct CopyOnly {
    228     CopyOnly(const CopyOnly&);
    229     CopyOnly &operator=(const CopyOnly&);
    230   };
    231   struct MoveOnly {
    232     MoveOnly(MoveOnly&&); // expected-note {{user-declared move}}
    233     MoveOnly &operator=(MoveOnly&&);
    234   };
    235   template void test(CopyOnly); // ok, copies
    236   template void test(MoveOnly); // ok, moves
    237   struct CopyAndMove { // expected-note {{implicitly deleted}}
    238     CopyOnly co;
    239     MoveOnly mo; // expected-note {{deleted copy}}
    240   };
    241   template void test(CopyAndMove); // ok, copies co, moves mo
    242   void test2(CopyAndMove cm) {
    243     (void)CopyAndMove(cm); // expected-error {{deleted}}
    244     cm = cm; // expected-error {{deleted}}
    245   }
    246 
    247   namespace VbaseMove {
    248     struct A {};
    249     struct B { B &operator=(B&&); };
    250     struct C { C &operator=(const C&); };
    251     struct D { B b; };
    252 
    253     template<typename T, unsigned I, bool NonTrivialMove = false>
    254     struct E : virtual T {};
    255 
    256     template<typename T, unsigned I>
    257     struct E<T, I, true> : virtual T { E &operator=(E&&); };
    258 
    259     template<typename T>
    260     struct F :
    261       E<T, 0>, // expected-note-re 2{{'{{[BD]}}' is a virtual base class of base class 'E<}}
    262       E<T, 1> {}; // expected-note-re 2{{'{{[BD]}}' is a virtual base class of base class 'E<}}
    263 
    264     template<typename T>
    265     struct G : E<T, 0, true>, E<T, 0> {};
    266 
    267     template<typename T>
    268     struct H : E<T, 0, true>, E<T, 1, true> {};
    269 
    270     template<typename T>
    271     struct I : E<T, 0>, T {};
    272 
    273     template<typename T>
    274     struct J :
    275       E<T, 0>, // expected-note-re 2{{'{{[BD]}}' is a virtual base class of base class 'E<}}
    276       virtual T {}; // expected-note-re 2{{virtual base class '{{[BD]}}' declared here}}
    277 
    278     template<typename T> void move(T t) { t = static_cast<T&&>(t); }
    279     // expected-warning-re@-1 4{{defaulted move assignment operator of {{.*}} will move assign virtual base class '{{[BD]}}' multiple times}}
    280     template void move(F<A>);
    281     template void move(F<B>); // expected-note {{in instantiation of}}
    282     template void move(F<C>);
    283     template void move(F<D>); // expected-note {{in instantiation of}}
    284     template void move(G<A>);
    285     template void move(G<B>);
    286     template void move(G<C>);
    287     template void move(G<D>);
    288     template void move(H<A>);
    289     template void move(H<B>);
    290     template void move(H<C>);
    291     template void move(H<D>);
    292     template void move(I<A>);
    293     template void move(I<B>);
    294     template void move(I<C>);
    295     template void move(I<D>);
    296     template void move(J<A>);
    297     template void move(J<B>); // expected-note {{in instantiation of}}
    298     template void move(J<C>);
    299     template void move(J<D>); // expected-note {{in instantiation of}}
    300   }
    301 }
    302 
    303 namespace PR12625 {
    304   struct X; // expected-note {{forward decl}}
    305   struct Y {
    306     X x; // expected-error {{incomplete}}
    307   } y = Y();
    308 }
    309