brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · 588778c Raw
309 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base %s2 3// Tests for implicit (non-)declaration of move constructor and4// assignment: p9, p11, p20, p23.5 6// This class, used as a member, allows to distinguish move from copy because7// move operations are no-throw, copy operations aren't.8struct 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 16struct HasCopyConstructor {17  ThrowingCopy tc;18  HasCopyConstructor() noexcept;19  HasCopyConstructor(const HasCopyConstructor &) noexcept(false);20};21 22struct HasCopyAssignment {23  ThrowingCopy tc;24  HasCopyAssignment() noexcept;25  HasCopyAssignment & operator =(const HasCopyAssignment &) noexcept(false);26};27 28struct 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 34struct HasMoveAssignment { // expected-note {{implicit copy constructor}}35  ThrowingCopy tc;36  HasMoveAssignment() noexcept;37  HasMoveAssignment & operator =(HasMoveAssignment &&) noexcept;38};39 40struct HasDestructor {41  ThrowingCopy tc;42  HasDestructor() noexcept;43  ~HasDestructor() noexcept;44};45 46void 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 68struct PrivateMove {69  PrivateMove() noexcept;70  PrivateMove(const PrivateMove &) noexcept(false);71  PrivateMove & operator =(const PrivateMove &) noexcept(false);72private:73  PrivateMove(PrivateMove &&) noexcept;74  PrivateMove & operator =(PrivateMove &&) noexcept;75};76 77struct InheritsPrivateMove : PrivateMove {};78struct ContainsPrivateMove {79  PrivateMove pm;80};81 82struct PrivateDestructor {83  PrivateDestructor() noexcept;84  PrivateDestructor(const PrivateDestructor &) noexcept(false);85  PrivateDestructor(PrivateDestructor &&) noexcept;86private:87  ~PrivateDestructor() noexcept;88};89 90struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{base class 'PrivateDestructor' has an inaccessible destructor}}91struct ContainsPrivateDestructor {92  PrivateDestructor pd; // expected-note{{field 'pd' has an inaccessible destructor}}93};94 95struct NonTrivialCopyOnly {96  NonTrivialCopyOnly() noexcept;97  NonTrivialCopyOnly(const NonTrivialCopyOnly &) noexcept(false);98  NonTrivialCopyOnly & operator =(const NonTrivialCopyOnly &) noexcept(false);99};100 101struct InheritsNonTrivialCopyOnly : NonTrivialCopyOnly {};102struct ContainsNonTrivialCopyOnly {103  NonTrivialCopyOnly ntco;104};105 106struct ContainsConst {107  const int i;108  ContainsConst() noexcept;109  ContainsConst & operator =(ContainsConst &); // expected-note {{not viable}}110};111 112struct ContainsRef {113  int &i;114  ContainsRef() noexcept;115  ContainsRef & operator =(ContainsRef &); // expected-note {{not viable}}116};117 118struct Base {119  Base & operator =(Base &);120};121struct DirectVirtualBase : virtual Base {}; // expected-note {{copy assignment operator) not viable}}122struct IndirectVirtualBase : DirectVirtualBase {}; // expected-note {{copy assignment operator) not viable}}123 124void 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 157struct ContainsRValueRef {158  int&& ri;159  ContainsRValueRef() noexcept;160};161 162void test_contains_rref() {163  (ContainsRValueRef(ContainsRValueRef()));164}165 166 167namespace 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 no194  // 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 longer205  // inhibits the declaration of a move assignment (even though it might206  // 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)); // ok213    t = static_cast<T&&>(t); // ok214  }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, copies236  template void test(MoveOnly); // ok, moves237  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 mo242  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 303namespace PR12625 {304  struct X; // expected-note {{forward decl}}305  struct Y {306    X x; // expected-error {{incomplete}}307  } y = Y();308}309