diff options
Diffstat (limited to 'clang/test/CXX/special')
30 files changed, 2024 insertions, 0 deletions
| diff --git a/clang/test/CXX/special/class.copy/implicit-move-def.cpp b/clang/test/CXX/special/class.copy/implicit-move-def.cpp new file mode 100644 index 0000000..5c54aea --- /dev/null +++ b/clang/test/CXX/special/class.copy/implicit-move-def.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-ASSIGN %s +// RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-ASSIGN %s +// RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-CTOR %s + +// construct + +struct E { +  E(); +  E(E&&); +}; + +struct F { +  F(); +  F(F&&); +}; + +struct G { +  E e; +}; + +struct H : G { +  F l; +  E m; +  F ar[2]; +}; + +void f() { +  H s; +  // CHECK: call void @_ZN1HC1EOS_ +  H t(static_cast<H&&>(s)); +} + + +// assign + +struct A { +  A &operator =(A&&); +}; + +struct B { +  B &operator =(B&&); +}; + +struct C { +  A a; +}; + +struct D : C { +  A a; +  B b; +  A ar[2]; +}; + +void g() { +  D d; +  // CHECK: call {{.*}} @_ZN1DaSEOS_ +  d = D(); +} + +// PR10822 +struct I { +  unsigned var[1]; +}; + +// CHECK: define void @_Z1hv() nounwind { +void h() { +  I i; +  // CHECK: call void @llvm.memcpy. +  i = I(); +  // CHECK-NEXT: ret void +} + +// PR10860 +struct Empty { }; +struct VirtualWithEmptyBase : Empty { +  virtual void f(); +}; + +// CHECK: define void @_Z25move_VirtualWithEmptyBaseR20VirtualWithEmptyBaseS0_ +void move_VirtualWithEmptyBase(VirtualWithEmptyBase &x, VirtualWithEmptyBase &y) { +  // CHECK: call {{.*}} @_ZN20VirtualWithEmptyBaseaSEOS_ +  x = static_cast<VirtualWithEmptyBase&&>(y); +  // CHECK-NEXT: ret void +} + +// move assignment ops + +// CHECK-ASSIGN: define linkonce_odr {{.*}} @_ZN1DaSEOS_ +// CHECK-ASSIGN: call {{.*}} @_ZN1CaSEOS_ +// CHECK-ASSIGN: call {{.*}} @_ZN1AaSEOS_ +// CHECK-ASSIGN: call {{.*}} @_ZN1BaSEOS_ +// array loop +// CHECK-ASSIGN: br i1 +// CHECK-ASSIGN: call {{.*}} @_ZN1AaSEOS_ + +// VirtualWithEmptyBase move assignment operatpr +// CHECK-ASSIGN: define linkonce_odr {{.*}} @_ZN20VirtualWithEmptyBaseaSEOS_ +// CHECK-ASSIGN: store +// CHECK-ASSIGN-NEXT: store +// CHECK-ASSIGN-NOT: call +// CHECK-ASSIGN: ret + +// CHECK-ASSIGN: define linkonce_odr {{.*}} @_ZN1CaSEOS_ +// CHECK-ASSIGN: call {{.*}} @_ZN1AaSEOS_ + +// move ctors + +// CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1HC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1GC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ +// array loop +// CHECK-CTOR: br i1 +// CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ + +// CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1GC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ diff --git a/clang/test/CXX/special/class.copy/implicit-move.cpp b/clang/test/CXX/special/class.copy/implicit-move.cpp new file mode 100644 index 0000000..3e9accf --- /dev/null +++ b/clang/test/CXX/special/class.copy/implicit-move.cpp @@ -0,0 +1,236 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Tests for implicit (non-)declaration of move constructor and +// assignment: p9, p11, p20, p23. + +// This class, used as a member, allows to distinguish move from copy because +// move operations are no-throw, copy operations aren't. +struct ThrowingCopy { +  ThrowingCopy() noexcept; +  ThrowingCopy(ThrowingCopy &&) noexcept; +  ThrowingCopy(const ThrowingCopy &) noexcept(false); +  ThrowingCopy & operator =(ThrowingCopy &&) noexcept; +  ThrowingCopy & operator =(const ThrowingCopy &) noexcept(false); +}; + +struct HasCopyConstructor { +  ThrowingCopy tc; +  HasCopyConstructor() noexcept; +  HasCopyConstructor(const HasCopyConstructor &) noexcept(false); +}; + +struct HasCopyAssignment { +  ThrowingCopy tc; +  HasCopyAssignment() noexcept; +  HasCopyAssignment & operator =(const HasCopyAssignment &) noexcept(false); +}; + +struct HasMoveConstructor { +  ThrowingCopy tc; +  HasMoveConstructor() noexcept; +  HasMoveConstructor(HasMoveConstructor &&) noexcept; // expected-note {{copy assignment operator is implicitly deleted because 'HasMoveConstructor' has a user-declared move constructor}} +}; + +struct HasMoveAssignment { // expected-note {{implicit copy constructor}} +  ThrowingCopy tc; +  HasMoveAssignment() noexcept; +  HasMoveAssignment & operator =(HasMoveAssignment &&) noexcept; +}; + +struct HasDestructor { +  ThrowingCopy tc; +  HasDestructor() noexcept; +  ~HasDestructor() noexcept; +}; + +void test_basic_exclusion() { +  static_assert(!noexcept(HasCopyConstructor((HasCopyConstructor()))), ""); +  HasCopyConstructor hcc; +  static_assert(!noexcept(hcc = HasCopyConstructor()), ""); + +  static_assert(!noexcept(HasCopyAssignment((HasCopyAssignment()))), ""); +  HasCopyAssignment hca; +  static_assert(!noexcept(hca = HasCopyAssignment()), ""); + +  static_assert(noexcept(HasMoveConstructor((HasMoveConstructor()))), ""); +  HasMoveConstructor hmc; +  hmc = HasMoveConstructor(); // expected-error {{selected implicitly-deleted copy assignment}} + +  (HasMoveAssignment(HasMoveAssignment())); // expected-error {{uses deleted function}} +  HasMoveAssignment hma; +  static_assert(noexcept(hma = HasMoveAssignment()), ""); + +  static_assert(!noexcept(HasDestructor((HasDestructor()))), ""); +  HasDestructor hd; +  static_assert(!noexcept(hd = HasDestructor()), ""); +} + +struct PrivateMove { +  PrivateMove() noexcept; +  PrivateMove(const PrivateMove &) noexcept(false); +  PrivateMove & operator =(const PrivateMove &) noexcept(false); +private: +  PrivateMove(PrivateMove &&) noexcept; +  PrivateMove & operator =(PrivateMove &&) noexcept; +}; + +struct InheritsPrivateMove : PrivateMove {}; +struct ContainsPrivateMove { +  PrivateMove pm; +}; + +struct PrivateDestructor { +  PrivateDestructor() noexcept; +  PrivateDestructor(const PrivateDestructor &) noexcept(false); +  PrivateDestructor(PrivateDestructor &&) noexcept; +private: +  ~PrivateDestructor() noexcept; +}; + +struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{base class 'PrivateDestructor' has an inaccessible destructor}} +struct ContainsPrivateDestructor { +  PrivateDestructor pd; // expected-note{{field 'pd' has an inaccessible destructor}} +}; + +struct NonTrivialCopyOnly { +  NonTrivialCopyOnly() noexcept; +  NonTrivialCopyOnly(const NonTrivialCopyOnly &) noexcept(false); +  NonTrivialCopyOnly & operator =(const NonTrivialCopyOnly &) noexcept(false); +}; + +struct InheritsNonTrivialCopyOnly : NonTrivialCopyOnly {}; +struct ContainsNonTrivialCopyOnly { +  NonTrivialCopyOnly ntco; +}; + +struct ContainsConst { +  const int i; +  ContainsConst() noexcept; +  ContainsConst & operator =(ContainsConst &); // expected-note {{not viable}} +}; + +struct ContainsRef { +  int &i; +  ContainsRef() noexcept; +  ContainsRef & operator =(ContainsRef &); // expected-note {{not viable}} +}; + +struct Base { +  Base & operator =(Base &); +}; +struct DirectVirtualBase : virtual Base {}; // expected-note {{copy assignment operator) not viable}} +struct IndirectVirtualBase : DirectVirtualBase {}; // expected-note {{copy assignment operator) not viable}} + +void test_deletion_exclusion() { +  // FIXME: How to test the union thing? + +  static_assert(!noexcept(InheritsPrivateMove(InheritsPrivateMove())), ""); +  static_assert(!noexcept(ContainsPrivateMove(ContainsPrivateMove())), ""); +  InheritsPrivateMove ipm; +  static_assert(!noexcept(ipm = InheritsPrivateMove()), ""); +  ContainsPrivateMove cpm; +  static_assert(!noexcept(cpm = ContainsPrivateMove()), ""); + +  (InheritsPrivateDestructor(InheritsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}} +  (ContainsPrivateDestructor(ContainsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}} + +  static_assert(!noexcept(InheritsNonTrivialCopyOnly(InheritsNonTrivialCopyOnly())), ""); +  static_assert(!noexcept(ContainsNonTrivialCopyOnly(ContainsNonTrivialCopyOnly())), ""); +  InheritsNonTrivialCopyOnly intco; +  static_assert(!noexcept(intco = InheritsNonTrivialCopyOnly()), ""); +  ContainsNonTrivialCopyOnly cntco; +  static_assert(!noexcept(cntco = ContainsNonTrivialCopyOnly()), ""); + +  ContainsConst cc; +  cc = ContainsConst(); // expected-error {{no viable}}  + +  ContainsRef cr; +  cr = ContainsRef(); // expected-error {{no viable}}  + +  DirectVirtualBase dvb; +  dvb = DirectVirtualBase(); // expected-error {{no viable}}  + +  IndirectVirtualBase ivb; +  ivb = IndirectVirtualBase(); // expected-error {{no viable}}  +} + +struct ContainsRValueRef { +  int&& ri; +  ContainsRValueRef() noexcept; +}; + +void test_contains_rref() { +  (ContainsRValueRef(ContainsRValueRef())); +} + + +namespace DR1402 { +  struct NonTrivialCopyCtor { +    NonTrivialCopyCtor(const NonTrivialCopyCtor &); +  }; +  struct NonTrivialCopyAssign { +    NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &); +  }; + +  struct NonTrivialCopyCtorVBase : virtual NonTrivialCopyCtor { +    NonTrivialCopyCtorVBase(NonTrivialCopyCtorVBase &&); +    NonTrivialCopyCtorVBase &operator=(NonTrivialCopyCtorVBase &&) = default; +  }; +  struct NonTrivialCopyAssignVBase : virtual NonTrivialCopyAssign { +    NonTrivialCopyAssignVBase(NonTrivialCopyAssignVBase &&); +    NonTrivialCopyAssignVBase &operator=(NonTrivialCopyAssignVBase &&) = default; +  }; + +  struct NonTrivialMoveAssign { +    NonTrivialMoveAssign(NonTrivialMoveAssign&&); +    NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&); +  }; +  struct NonTrivialMoveAssignVBase : virtual NonTrivialMoveAssign { +    NonTrivialMoveAssignVBase(NonTrivialMoveAssignVBase &&); +    NonTrivialMoveAssignVBase &operator=(NonTrivialMoveAssignVBase &&) = default; +  }; + +  // A non-movable, non-trivially-copyable class type as a subobject inhibits +  // the declaration of a move operation. +  struct NoMove1 { NonTrivialCopyCtor ntcc; }; // expected-note 2{{'const DR1402::NoMove1 &'}} +  struct NoMove2 { NonTrivialCopyAssign ntcc; }; // expected-note 2{{'const DR1402::NoMove2 &'}} +  struct NoMove3 : NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove3 &'}} +  struct NoMove4 : NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove4 &'}} +  struct NoMove5 : virtual NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove5 &'}} +  struct NoMove6 : virtual NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove6 &'}} +  struct NoMove7 : NonTrivialCopyCtorVBase {}; // expected-note 2{{'const DR1402::NoMove7 &'}} +  struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note 2{{'const DR1402::NoMove8 &'}} + +  // A non-trivially-move-assignable virtual base class inhibits the declaration +  // of a move assignment (which might move-assign the base class multiple +  // times). +  struct NoMove9 : NonTrivialMoveAssign {}; +  struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note {{'const DR1402::NoMove10 &'}} +  struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'const DR1402::NoMove11 &'}} + +  struct Test { +    friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{no matching function}} +    friend NoMove2::NoMove2(NoMove2 &&); // expected-error {{no matching function}} +    friend NoMove3::NoMove3(NoMove3 &&); // expected-error {{no matching function}} +    friend NoMove4::NoMove4(NoMove4 &&); // expected-error {{no matching function}} +    friend NoMove5::NoMove5(NoMove5 &&); // expected-error {{no matching function}} +    friend NoMove6::NoMove6(NoMove6 &&); // expected-error {{no matching function}} +    friend NoMove7::NoMove7(NoMove7 &&); // expected-error {{no matching function}} +    friend NoMove8::NoMove8(NoMove8 &&); // expected-error {{no matching function}} +    friend NoMove9::NoMove9(NoMove9 &&); +    friend NoMove10::NoMove10(NoMove10 &&); +    friend NoMove11::NoMove11(NoMove11 &&); + +    friend NoMove1 &NoMove1::operator=(NoMove1 &&); // expected-error {{no matching function}} +    friend NoMove2 &NoMove2::operator=(NoMove2 &&); // expected-error {{no matching function}} +    friend NoMove3 &NoMove3::operator=(NoMove3 &&); // expected-error {{no matching function}} +    friend NoMove4 &NoMove4::operator=(NoMove4 &&); // expected-error {{no matching function}} +    friend NoMove5 &NoMove5::operator=(NoMove5 &&); // expected-error {{no matching function}} +    friend NoMove6 &NoMove6::operator=(NoMove6 &&); // expected-error {{no matching function}} +    friend NoMove7 &NoMove7::operator=(NoMove7 &&); // expected-error {{no matching function}} +    friend NoMove8 &NoMove8::operator=(NoMove8 &&); // expected-error {{no matching function}} +    friend NoMove9 &NoMove9::operator=(NoMove9 &&); +    friend NoMove10 &NoMove10::operator=(NoMove10 &&); // expected-error {{no matching function}} +    friend NoMove11 &NoMove11::operator=(NoMove11 &&); // expected-error {{no matching function}} +  }; +} diff --git a/clang/test/CXX/special/class.copy/p11.0x.copy.cpp b/clang/test/CXX/special/class.copy/p11.0x.copy.cpp new file mode 100644 index 0000000..b2b4f6a --- /dev/null +++ b/clang/test/CXX/special/class.copy/p11.0x.copy.cpp @@ -0,0 +1,121 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct NonTrivial { +  NonTrivial(const NonTrivial&); +}; + +// A defaulted copy 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{{copy constructor of union 'DeletedNTVariant' is implicitly deleted because field 'NT' has a non-trivial copy constructor}} +  DeletedNTVariant(); +}; +DeletedNTVariant DVa; +DeletedNTVariant DVb(DVa); // expected-error{{call to implicitly-deleted copy constructor}} + +struct DeletedNTVariant2 { +  union { +    NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant2' is implicitly deleted because field 'NT' has a non-trivial copy constructor}} +  }; +  DeletedNTVariant2(); +}; +DeletedNTVariant2 DV2a; +DeletedNTVariant2 DV2b(DV2a); // expected-error{{call to implicitly-deleted copy constructor}} + +// -- 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(const NoAccess&); + +  friend struct HasAccess; +}; + +struct HasNoAccess { +  NoAccess NA; // expected-note{{copy constructor of 'HasNoAccess' is implicitly deleted because field 'NA' has an inaccessible copy constructor}} +}; +HasNoAccess HNAa; +HasNoAccess HNAb(HNAa); // expected-error{{call to implicitly-deleted copy constructor}} + +struct HasAccess { +  NoAccess NA; +}; + +HasAccess HAa; +HasAccess HAb(HAa); + +struct NonConst { +  NonConst(NonConst&); +}; +struct Ambiguity { +  Ambiguity(const Ambiguity&); +  Ambiguity(volatile Ambiguity&); +}; + +struct IsAmbiguous { +  NonConst NC; +  Ambiguity A; // expected-note 2{{copy constructor of 'IsAmbiguous' is implicitly deleted because field 'A' has multiple copy constructors}} +  IsAmbiguous(); +}; +IsAmbiguous IAa; +IsAmbiguous IAb(IAa); // expected-error{{call to implicitly-deleted copy constructor}} + +struct Deleted { +  IsAmbiguous IA; // expected-note{{copy constructor of 'Deleted' is implicitly deleted because field 'IA' has a deleted copy constructor}} +}; +Deleted Da; +Deleted Db(Da); // expected-error{{call to implicitly-deleted copy constructor}} + +// -- 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 +struct AmbiguousCopyBase : Ambiguity { // expected-note 2{{copy constructor of 'AmbiguousCopyBase' is implicitly deleted because base class 'Ambiguity' has multiple copy constructors}} +  NonConst NC; +}; +extern AmbiguousCopyBase ACBa; +AmbiguousCopyBase ACBb(ACBa); // expected-error {{deleted copy constructor}} + +struct DeletedCopyBase : AmbiguousCopyBase {}; // expected-note {{copy constructor of 'DeletedCopyBase' is implicitly deleted because base class 'AmbiguousCopyBase' has a deleted copy constructor}} +extern DeletedCopyBase DCBa; +DeletedCopyBase DCBb(DCBa); // expected-error {{deleted copy constructor}} + +struct InaccessibleCopyBase : NoAccess {}; // expected-note {{copy constructor of 'InaccessibleCopyBase' is implicitly deleted because base class 'NoAccess' has an inaccessible copy constructor}} +extern InaccessibleCopyBase ICBa; +InaccessibleCopyBase ICBb(ICBa); // expected-error {{deleted copy constructor}} + +// -- any direct or virtual base class or non-static data member of a type with +//    a destructor that is deleted or inaccessible +struct NoAccessDtor { +private: +  ~NoAccessDtor(); +  friend struct HasAccessDtor; +}; + +struct HasNoAccessDtor { +  NoAccessDtor NAD; // expected-note{{copy constructor of 'HasNoAccessDtor' is implicitly deleted because field 'NAD' has an inaccessible destructor}} +  HasNoAccessDtor(); +  ~HasNoAccessDtor(); +}; +HasNoAccessDtor HNADa; +HasNoAccessDtor HNADb(HNADa); // expected-error{{call to implicitly-deleted copy constructor}} + +struct HasAccessDtor { +  NoAccessDtor NAD; +}; +HasAccessDtor HADa; +HasAccessDtor HADb(HADa); + +struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has an inaccessible destructor}} +}; +extern HasNoAccessDtorBase HNADBa; +HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}} + +// -- a non-static data member of rvalue reference type +struct RValue { +  int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}} +}; +RValue RVa; +RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}} diff --git a/clang/test/CXX/special/class.copy/p11.0x.move.cpp b/clang/test/CXX/special/class.copy/p11.0x.move.cpp new file mode 100644 index 0000000..ff9478b --- /dev/null +++ b/clang/test/CXX/special/class.copy/p11.0x.move.cpp @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct NonTrivial { +  NonTrivial(NonTrivial&&); +}; + +// 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; +  DeletedNTVariant(DeletedNTVariant&&); +}; +DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}} + +struct DeletedNTVariant2 { +  union { +    NonTrivial NT; +  }; +  DeletedNTVariant2(DeletedNTVariant2&&); +}; +DeletedNTVariant2::DeletedNTVariant2(DeletedNTVariant2&&) = default; // expected-error{{would delete}} + +// -- 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; +  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; +  IsAmbiguous(IsAmbiguous&&); +}; +IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}} + +struct Deleted { +  IsAmbiguous IA; +  Deleted(Deleted&&); +}; +Deleted::Deleted(Deleted&&) = 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 { +  AmbiguousMoveBase(AmbiguousMoveBase&&); +}; +AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}} + +struct DeletedMoveBase : AmbiguousMoveBase { +  DeletedMoveBase(DeletedMoveBase&&); +}; +DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}} + +struct InaccessibleMoveBase : NoAccess { +  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; +  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); +  } +} diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp new file mode 100644 index 0000000..0a9aa62 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p13-0x.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If the implicitly-defined constructor would satisfy the requirements of a +// constexpr constructor, the implicitly-defined constructor is constexpr. +struct Constexpr1 { +  constexpr Constexpr1() : n(0) {} +  int n; +}; +constexpr Constexpr1 c1a = Constexpr1(Constexpr1()); // ok +constexpr Constexpr1 c1b = Constexpr1(Constexpr1(c1a)); // ok + +struct Constexpr2 { +  Constexpr1 ce1; +  constexpr Constexpr2() = default; +  constexpr Constexpr2(const Constexpr2 &o) : ce1(o.ce1) {} +  // no move constructor +}; + +constexpr Constexpr2 c2a = Constexpr2(Constexpr2()); // ok +constexpr Constexpr2 c2b = Constexpr2(Constexpr2(c2a)); // ok + +struct Constexpr3 { +  Constexpr2 ce2; +  // all special constructors are constexpr, move ctor calls ce2's copy ctor +}; + +constexpr Constexpr3 c3a = Constexpr3(Constexpr3()); // ok +constexpr Constexpr3 c3b = Constexpr3(Constexpr3(c3a)); // ok + +struct NonConstexprCopy { +  constexpr NonConstexprCopy() = default; +  NonConstexprCopy(const NonConstexprCopy &); +  constexpr NonConstexprCopy(NonConstexprCopy &&) = default; + +  int n = 42; +}; + +NonConstexprCopy::NonConstexprCopy(const NonConstexprCopy &) = default; // expected-note {{here}} + +constexpr NonConstexprCopy ncc1 = NonConstexprCopy(NonConstexprCopy()); // ok +constexpr NonConstexprCopy ncc2 = ncc1; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct NonConstexprDefault { +  NonConstexprDefault() = default; +  constexpr NonConstexprDefault(int n) : n(n) {} +  int n; +}; +struct Constexpr4 { +  NonConstexprDefault ncd; +}; + +constexpr NonConstexprDefault ncd = NonConstexprDefault(NonConstexprDefault(1)); +constexpr Constexpr4 c4a = { ncd }; +constexpr Constexpr4 c4b = Constexpr4(c4a); +constexpr Constexpr4 c4c = Constexpr4(static_cast<Constexpr4&&>(const_cast<Constexpr4&>(c4b))); + +struct Constexpr5Base {}; +struct Constexpr5 : Constexpr5Base { constexpr Constexpr5() {} }; +constexpr Constexpr5 ce5move = Constexpr5(); +constexpr Constexpr5 ce5copy = ce5move; diff --git a/clang/test/CXX/special/class.copy/p15-0x.cpp b/clang/test/CXX/special/class.copy/p15-0x.cpp new file mode 100644 index 0000000..fff8844 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p15-0x.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +namespace PR10622 { +  struct foo { +    const int first; +    foo(const foo&) = default; +  }; +  void find_or_insert(const foo& __obj) { +    foo x(__obj); +  } + +  struct bar : foo { +    bar(const bar&) = default; +  }; +  void test_bar(const bar &obj) { +    bar obj2(obj); +  } +} + +namespace PR11418 { +  template<typename T> +  T may_throw() { +    return T(); +  } + +  template<typename T> T &&declval() noexcept; + +  struct NonPOD { +    NonPOD(); +    NonPOD(const NonPOD &) noexcept; +    NonPOD(NonPOD &&) noexcept; +  }; + +  struct X { +    NonPOD np = may_throw<NonPOD>(); +  }; + +  static_assert(noexcept(declval<X>()), "noexcept isn't working at all"); +  static_assert(noexcept(X(declval<X&>())), "copy constructor can't throw"); +  static_assert(noexcept(X(declval<X>())), "move constructor can't throw"); +} diff --git a/clang/test/CXX/special/class.copy/p15-inclass.cpp b/clang/test/CXX/special/class.copy/p15-inclass.cpp new file mode 100644 index 0000000..c4f8eaf --- /dev/null +++ b/clang/test/CXX/special/class.copy/p15-inclass.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s + +namespace PR11418 { +  struct NonPOD { +    NonPOD(); +    NonPOD(const NonPOD &); +    NonPOD(NonPOD &&); +  }; + +  struct X { +    NonPOD np; +    int a = 17; +  }; + +  void check_copy(X x) { +    X x2(x); +  } + +  void check_move(X x) { +    X x3(static_cast<X&&>(x)); +  } + +  // CHECK: define linkonce_odr void @_ZN7PR114181XC2EOS0_ +  // CHECK-NOT: 17 +  // CHECK: call void @_ZN7PR114186NonPODC1EOS0_ +  // CHECK-NOT: 17 +  // CHECK: load i32*  +  // CHECK-NOT: 17 +  // CHECK: store i32 +  // CHECK-NOT: 17 +  // CHECK: ret + +  // CHECK: define linkonce_odr void @_ZN7PR114181XC2ERKS0_ +  // CHECK-NOT: 17 +  // CHECK: call void @_ZN7PR114186NonPODC1ERKS0_ +  // CHECK-NOT: 17 +  // CHECK: load i32*  +  // CHECK-NOT: 17 +  // CHECK: store i32 +  // CHECK-NOT: 17 +  // CHECK: ret +} diff --git a/clang/test/CXX/special/class.copy/p20.cpp b/clang/test/CXX/special/class.copy/p20.cpp new file mode 100644 index 0000000..8dfb7ca --- /dev/null +++ b/clang/test/CXX/special/class.copy/p20.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct ConstCopy { +  ConstCopy(); +  ConstCopy &operator=(const ConstCopy&); +}; + +struct NonConstCopy { +  NonConstCopy(); +  NonConstCopy &operator=(NonConstCopy&); +}; + +struct VirtualInheritsNonConstCopy : virtual NonConstCopy {  +  VirtualInheritsNonConstCopy(); +  VirtualInheritsNonConstCopy &operator=(const VirtualInheritsNonConstCopy&); +}; + +struct ImplicitNonConstCopy1 : NonConstCopy {  // expected-note{{the implicit copy assignment operator}} +  ImplicitNonConstCopy1(); +}; + +struct ImplicitNonConstCopy2 { // expected-note{{the implicit copy assignment operator}} +  ImplicitNonConstCopy2(); +  NonConstCopy ncc; +}; + +struct ImplicitNonConstCopy3 { // expected-note{{the implicit copy assignment operator}} +  ImplicitNonConstCopy3(); +  NonConstCopy ncc_array[2][3]; +}; + +struct ImplicitNonConstCopy4 : VirtualInheritsNonConstCopy {  +  ImplicitNonConstCopy4(); +}; + +void test_non_const_copy(const ImplicitNonConstCopy1 &cincc1, +                         const ImplicitNonConstCopy2 &cincc2, +                         const ImplicitNonConstCopy3 &cincc3, +                         const ImplicitNonConstCopy4 &cincc4, +                         const VirtualInheritsNonConstCopy &vincc) { +  (void)sizeof(ImplicitNonConstCopy1() = cincc1); // expected-error{{no viable overloaded '='}} +  (void)sizeof(ImplicitNonConstCopy2() = cincc2); // expected-error{{no viable overloaded '='}} +  (void)sizeof(ImplicitNonConstCopy3() = cincc3); // expected-error{{no viable overloaded '='}} +  (void)sizeof(ImplicitNonConstCopy4() = cincc4); // okay +  (void)sizeof(VirtualInheritsNonConstCopy() = vincc); +} diff --git a/clang/test/CXX/special/class.copy/p3.cpp b/clang/test/CXX/special/class.copy/p3.cpp new file mode 100644 index 0000000..3d87266 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p3.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +// PR6141 +template<typename T> +struct X { +  X(); +  template<typename U> X(X<U>); +  X(const X<T>&); +}; + +void f(X<int>) { } + +struct Y : X<int> { }; +struct Z : X<float> { }; + +// CHECK: define i32 @main() +int main() { +  // CHECK: call void @_ZN1YC1Ev +  // CHECK: call void @_ZN1XIiEC1ERKS0_ +  // CHECK: call void @_Z1f1XIiE +  f(Y()); +  // CHECK: call void @_ZN1ZC1Ev +  // CHECK: call void @_ZN1XIfEC1ERKS0_ +  // CHECK: call void @_ZN1XIiEC1IfEES_IT_E +  // CHECK: call void @_Z1f1XIiE +  f(Z()); +} diff --git a/clang/test/CXX/special/class.copy/p33-0x.cpp b/clang/test/CXX/special/class.copy/p33-0x.cpp new file mode 100644 index 0000000..b66e19a --- /dev/null +++ b/clang/test/CXX/special/class.copy/p33-0x.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -fsyntax-only -verify %s +class X { +  X(const X&); + +public: +  X(); +  X(X&&); +}; + +X return_by_move(int i, X x) { +  X x2; +  if (i == 0) +    return x; +  else if (i == 1) +    return x2; +  else +    return x; +} + +void throw_move_only(X x) { +  X x2; +  throw x; +  throw x2; +} +   +namespace PR10142 { +  struct X { +    X(); +    X(X&&); +    X(const X&) = delete; // expected-note 2{{function has been explicitly marked deleted here}} +  }; + +  void f(int i) { +    X x; +    try { +      X x2; +      if (i) +        throw x2; // okay +      throw x; // expected-error{{call to deleted constructor of 'PR10142::X'}} +    } catch (...) { +    } +  } + +  template<typename T> +  void f2(int i) { +    T x; +    try { +      T x2; +      if (i) +        throw x2; // okay +      throw x; // expected-error{{call to deleted constructor of 'PR10142::X'}} +    } catch (...) { +    } +  } + +  template void f2<X>(int); // expected-note{{in instantiation of function template specialization 'PR10142::f2<PR10142::X>' requested here}} +} diff --git a/clang/test/CXX/special/class.copy/p8-cxx11.cpp b/clang/test/CXX/special/class.copy/p8-cxx11.cpp new file mode 100644 index 0000000..02e6cd1 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p8-cxx11.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +// C++98 [class.copy]p5 / C++11 [class.copy]p8. + +// The implicitly-declared copy constructor for a class X will have the form +//   X::X(const X&) +// if [every direct subobject] has a copy constructor whose first parameter is +// of type 'const volatile[opt] T &'. Otherwise, it will have the form +//   X::X(X&) + +struct ConstCopy { +  ConstCopy(const ConstCopy &); +}; + +struct NonConstCopy { +  NonConstCopy(NonConstCopy &); +}; + +struct DeletedConstCopy { +  DeletedConstCopy(const DeletedConstCopy &) = delete; +}; + +struct DeletedNonConstCopy { +  DeletedNonConstCopy(DeletedNonConstCopy &) = delete; +}; + +struct ImplicitlyDeletedConstCopy { +  ImplicitlyDeletedConstCopy(ImplicitlyDeletedConstCopy &&); +}; + + +struct A : ConstCopy {}; +struct B : NonConstCopy { ConstCopy a; }; +struct C : ConstCopy { NonConstCopy a; }; +struct D : DeletedConstCopy {}; +struct E : DeletedNonConstCopy {}; +struct F { ImplicitlyDeletedConstCopy a; }; +struct G : virtual B {}; + +struct Test { +  friend A::A(const A &); +  friend B::B(B &); +  friend C::C(C &); +  friend D::D(const D &); +  friend E::E(E &); +  friend F::F(const F &); +  friend G::G(G &); +}; diff --git a/clang/test/CXX/special/class.copy/p9.cpp b/clang/test/CXX/special/class.copy/p9.cpp new file mode 100644 index 0000000..77ab19e --- /dev/null +++ b/clang/test/CXX/special/class.copy/p9.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct ConstCopy { +  ConstCopy(); +  ConstCopy(const ConstCopy&); +}; + +struct NonConstCopy { +  NonConstCopy(); +  NonConstCopy(NonConstCopy&); +}; + +struct VirtualInheritsNonConstCopy : virtual NonConstCopy {  +  VirtualInheritsNonConstCopy(); +  VirtualInheritsNonConstCopy(const VirtualInheritsNonConstCopy&); +}; + +struct ImplicitNonConstCopy1 : NonConstCopy { // expected-note {{candidate constructor}} +  ImplicitNonConstCopy1(); // expected-note {{candidate constructor}} +}; + +struct ImplicitNonConstCopy2 { // expected-note {{candidate constructor}} +  ImplicitNonConstCopy2(); // expected-note {{candidate constructor}} +  NonConstCopy ncc; +}; + +struct ImplicitNonConstCopy3 { // expected-note {{candidate constructor}} +  ImplicitNonConstCopy3(); // expected-note {{candidate constructor}} +  NonConstCopy ncc_array[2][3]; +}; + +struct ImplicitNonConstCopy4 : VirtualInheritsNonConstCopy { // expected-note {{candidate constructor}} +  ImplicitNonConstCopy4(); // expected-note {{candidate constructor}} +}; + +void test_non_const_copy(const ImplicitNonConstCopy1 &cincc1, +                         const ImplicitNonConstCopy2 &cincc2, +                         const ImplicitNonConstCopy3 &cincc3, +                         const ImplicitNonConstCopy4 &cincc4) { +  (void)sizeof(ImplicitNonConstCopy1(cincc1)); // expected-error{{no matching conversion for functional-style cast from 'const ImplicitNonConstCopy1' to 'ImplicitNonConstCopy1'}} +  (void)sizeof(ImplicitNonConstCopy2(cincc2)); // expected-error{{no matching conversion for functional-style cast from 'const ImplicitNonConstCopy2' to 'ImplicitNonConstCopy2'}} +  (void)sizeof(ImplicitNonConstCopy3(cincc3)); // expected-error{{no matching conversion for functional-style cast from 'const ImplicitNonConstCopy3' to 'ImplicitNonConstCopy3'}} +  (void)sizeof(ImplicitNonConstCopy4(cincc4)); // expected-error{{no matching conversion for functional-style cast from 'const ImplicitNonConstCopy4' to 'ImplicitNonConstCopy4'}} +} diff --git a/clang/test/CXX/special/class.ctor/p1.cpp b/clang/test/CXX/special/class.ctor/p1.cpp new file mode 100644 index 0000000..9500a7d --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p1.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct X0 { +  struct type { }; + +  X0(); +  X0(int); +  (X0)(float); +  X0 (f0)(int); +  X0 (f0)(type); +   +  X0 f1(); +  X0 f1(double); +}; + +X0::X0() { } +(X0::X0)(int) { } + +X0 (X0::f0)(int) { return X0(); } + +template<typename T> +struct X1 { +  struct type { }; + +  X1<T>(); +  X1<T>(int); +  (X1<T>)(float); +  X1(float, float); +  (X1)(double); +  X1<T> (f0)(int); +  X1<T> (f0)(type); +  X1 (f1)(int); +  X1 (f1)(type); + +  template<typename U> X1(U); +  X1 f2(); +  X1 f2(int); +}; + +template<typename T> X1<T>::X1() { } +template<typename T> (X1<T>::X1)(double) { } +template<typename T> X1<T> X1<T>::f1(int) { return 0; } +template<typename T> X1<T> (X1<T>::f1)(type) { return 0; } diff --git a/clang/test/CXX/special/class.ctor/p4-0x.cpp b/clang/test/CXX/special/class.ctor/p4-0x.cpp new file mode 100644 index 0000000..509beb4 --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p4-0x.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// A constructor shall not be declared with a ref-qualifier. +struct X { +  X() &; // expected-error{{ref-qualifier '&' is not allowed on a constructor}} +  X(int) &&; // expected-error{{ref-qualifier '&&' is not allowed on a constructor}} +}; diff --git a/clang/test/CXX/special/class.ctor/p5-0x.cpp b/clang/test/CXX/special/class.ctor/p5-0x.cpp new file mode 100644 index 0000000..694ab5b --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p5-0x.cpp @@ -0,0 +1,182 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct DefaultedDefCtor1 {}; +struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; }; +struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); }; // expected-note {{explicitly marked deleted here}} +class PrivateDefCtor { PrivateDefCtor() = default; public: PrivateDefCtor(int); }; +struct DeletedDtor { ~DeletedDtor() = delete; }; // expected-note 4{{explicitly marked deleted here}} +class PrivateDtor { ~PrivateDtor() = default; }; +class Friend { +  Friend() = default; ~Friend() = default; +  friend struct NotDeleted6c; +  friend struct NotDeleted7i; +  friend struct NotDeleted7j; +  friend struct NotDeleted7k; +}; +struct UserProvidedDefCtor { UserProvidedDefCtor() {} }; +int n; + + +// A defaulted default constructor for a class X is defined as deleted if: + +// - X is a union-like class that has a variant member with a non-trivial +// default constructor, +union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{default constructor of union 'Deleted1a' is implicitly deleted because field 'u' has a non-trivial default constructor}} +Deleted1a d1a; // expected-error {{implicitly-deleted default constructor}} +union NotDeleted1a { DefaultedDefCtor1 nu; }; +NotDeleted1a nd1a; +union NotDeleted1b { DefaultedDefCtor2 nu; }; +NotDeleted1b nd1b; + +// - any non-static data member with no brace-or-equal-initializer is of +// reference type, +class Deleted2a { +  Deleted2a() = default;  // expected-note 4{{implicitly deleted here}} +  int &a; // expected-note 4{{because field 'a' of reference type 'int &' would not be initialized}} +}; +Deleted2a d2a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted2b { +  int &&b; // expected-note {{default constructor of 'Deleted2b' is implicitly deleted because field 'b' of reference type 'int &&' would not be initialized}} +}; +Deleted2b d2b; // expected-error {{deleted default constructor}} +class NotDeleted2a { int &a = n; }; +NotDeleted2a nd2a; +class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}} +NotDeleted2b nd2b; +class NotDeleted2c { int &&a = 0; }; +NotDeleted2c nd2c; + +// - any non-variant non-static data member of const qualified type (or array +// thereof) with no brace-or-equal-initializer does not have a user-provided +// default constructor, +class Deleted3a { const int a; }; // expected-note {{because field 'a' of const-qualified type 'const int' would not be initialized}} \ +                                     expected-warning {{does not declare any constructor}} \ +                                     expected-note {{will never be initialized}} +Deleted3a d3a; // expected-error {{implicitly-deleted default constructor}} +class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor1' would not be initialized}} +Deleted3b d3b; // expected-error {{implicitly-deleted default constructor}} +class Deleted3c { const DefaultedDefCtor2 a; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor2' would not be initialized}} +Deleted3c d3c; // expected-error {{implicitly-deleted default constructor}} +class NotDeleted3a { const int a = 0; }; +NotDeleted3a nd3a; +class NotDeleted3b { const DefaultedDefCtor1 a[42] = {}; }; +NotDeleted3b nd3b; +class NotDeleted3c { const DefaultedDefCtor2 a = DefaultedDefCtor2(); }; +NotDeleted3c nd3c; +union NotDeleted3d { const int a; int b; }; +NotDeleted3d nd3d; +union NotDeleted3e { const DefaultedDefCtor1 a[42]; int b; }; +NotDeleted3e nd3e; +union NotDeleted3f { const DefaultedDefCtor2 a; int b; }; +NotDeleted3f nd3f; +struct NotDeleted3g { union { const int a; int b; }; }; +NotDeleted3g nd3g; + +// - X is a union and all of its variant members are of const-qualified type (or +// array thereof), +union Deleted4a { +  const int a; +  const int b; +  const UserProvidedDefCtor c; // expected-note {{because field 'c' has a non-trivial default constructor}} +}; +Deleted4a d4a; // expected-error {{implicitly-deleted default constructor}} +union NotDeleted4a { const int a; int b; }; +NotDeleted4a nd4a; + +// - X is a non-union class and all members of any anonymous union member are of +// const-qualified type (or array thereof), +struct Deleted5a { +  union { const int a; }; // expected-note {{because all data members of an anonymous union member are const-qualified}} +  union { int b; }; +}; +Deleted5a d5a; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted5a { union { const int a; int b; }; union { const int c; int d; }; }; +NotDeleted5a nd5a; + +// - any direct or virtual base class, or non-static data member with no +// brace-or-equal-initializer, has class type M (or array thereof) and either +// M has no default constructor or overload resolution as applied to M's default +// constructor results in an ambiguity or in a function that is deleted or +// inaccessible from the defaulted default constructor, or +struct Deleted6a : Deleted2a {}; // expected-note {{because base class 'Deleted2a' has a deleted default constructor}} +Deleted6a d6a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6b : virtual Deleted2a {}; // expected-note {{because base class 'Deleted2a' has a deleted default constructor}} +Deleted6b d6b; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6c { Deleted2a a; }; // expected-note {{because field 'a' has a deleted default constructor}} +Deleted6c d6c; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6d { DeletedDefCtor a; }; // expected-note {{because field 'a' has a deleted default constructor}} +Deleted6d d6d; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted6a { DeletedDefCtor a = 0; }; +NotDeleted6a nd6a; +struct Deleted6e { PrivateDefCtor a; }; // expected-note {{because field 'a' has an inaccessible default constructor}} +Deleted6e d6e; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted6b { PrivateDefCtor a = 0; }; +NotDeleted6b nd6b; +struct NotDeleted6c { Friend a; }; +NotDeleted6c nd6c; + +// - any direct or virtual base class or non-static data member has a type with +// a destructor that is deleted or inaccessible from the defaulted default +// constructor. +struct Deleted7a : DeletedDtor {}; // expected-note {{because base class 'DeletedDtor' has a deleted destructor}} +Deleted7a d7a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7b : virtual DeletedDtor {}; // expected-note {{because base class 'DeletedDtor' has a deleted destructor}} +Deleted7b d7b; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7c { DeletedDtor a; }; // expected-note {{because field 'a' has a deleted destructor}} +Deleted7c d7c; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7d { DeletedDtor a = {}; }; // expected-note {{because field 'a' has a deleted destructor}} +Deleted7d d7d; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7e : PrivateDtor {}; // expected-note {{base class 'PrivateDtor' has an inaccessible destructor}} +Deleted7e d7e; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7f : virtual PrivateDtor {}; // expected-note {{base class 'PrivateDtor' has an inaccessible destructor}} +Deleted7f d7f; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7g { PrivateDtor a; }; // expected-note {{field 'a' has an inaccessible destructor}} +Deleted7g d7g; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7h { PrivateDtor a = {}; }; // expected-note {{field 'a' has an inaccessible destructor}} +Deleted7h d7h; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted7i : Friend {}; +NotDeleted7i d7i; +struct NotDeleted7j : virtual Friend {}; +NotDeleted7j d7j; +struct NotDeleted7k { Friend a; }; +NotDeleted7k d7k; + + +class Trivial { static const int n = 42; }; +static_assert(__has_trivial_constructor(Trivial), "Trivial is nontrivial"); + +// A default constructor is trivial if it is not user-provided and if: +class NonTrivialDefCtor1 { NonTrivialDefCtor1(); }; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor1), "NonTrivialDefCtor1 is trivial"); + +// - its class has no virtual functions (10.3) and no virtual base classes (10.1), and +class NonTrivialDefCtor2 { virtual void f(); }; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor2), "NonTrivialDefCtor2 is trivial"); +class NonTrivialDefCtor3 : virtual Trivial {}; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor3), "NonTrivialDefCtor3 is trivial"); + +// - no non-static data member of its class has a brace-or-equal-initializer, and +class NonTrivialDefCtor4 { int m = 52; }; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor4), "NonTrivialDefCtor4 is trivial"); + +// - all the direct base classes of its class have trivial default constructors, and +class NonTrivialDefCtor5 : NonTrivialDefCtor1 {}; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor5), "NonTrivialDefCtor5 is trivial"); + +// - for all the non-static data members of its class that are of class type (or array thereof), each such class +// has a trivial default constructor. +class NonTrivialDefCtor6 { NonTrivialDefCtor1 t; }; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor6), "NonTrivialDefCtor5 is trivial"); + +// Otherwise, the default constructor is non-trivial. +class Trivial2 { Trivial2() = delete; }; +static_assert(__has_trivial_constructor(Trivial2), "Trivial2 is trivial"); + +class Trivial3 { Trivial3() = default; }; +static_assert(__has_trivial_constructor(Trivial3), "Trivial3 is trivial"); + +template<typename T> class Trivial4 { Trivial4() = default; }; +static_assert(__has_trivial_constructor(Trivial4<int>), "Trivial4 is trivial"); + +template<typename T> class Trivial5 { Trivial5() = delete; }; +static_assert(__has_trivial_constructor(Trivial5<int>), "Trivial5 is trivial"); diff --git a/clang/test/CXX/special/class.ctor/p6-0x.cpp b/clang/test/CXX/special/class.ctor/p6-0x.cpp new file mode 100644 index 0000000..8c8800f --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p6-0x.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +// Implicitly-defined default constructors are constexpr if the implicit +// definition would be. +struct NonConstexpr1 { // expected-note {{here}} +  int a; +}; +struct NonConstexpr2 { // expected-note {{here}} +  NonConstexpr1 nl; +}; +struct NonConstexpr2a : NonConstexpr1 { }; +constexpr NonConstexpr1 nc1 = NonConstexpr1(); // ok, does not call constructor +constexpr NonConstexpr2 nc2 = NonConstexpr2(); // ok, does not call constructor +constexpr NonConstexpr2a nc2a = NonConstexpr2a(); // ok, does not call constructor +constexpr int nc2_a = NonConstexpr2().nl.a; // ok +constexpr int nc2a_a = NonConstexpr2a().a; // ok +struct Helper { +  friend constexpr NonConstexpr1::NonConstexpr1(); // expected-error {{follows non-constexpr declaration}} +  friend constexpr NonConstexpr2::NonConstexpr2(); // expected-error {{follows non-constexpr declaration}} +}; + +struct Constexpr1 {}; +constexpr Constexpr1 c1 = Constexpr1(); // ok +struct NonConstexpr3 : virtual Constexpr1 {}; // expected-note {{struct with virtual base}} expected-note {{declared here}} +constexpr NonConstexpr3 nc3 = NonConstexpr3(); // expected-error {{non-literal type 'const NonConstexpr3'}} + +struct Constexpr2 { +  int a = 0; +}; +constexpr Constexpr2 c2 = Constexpr2(); // ok + +int n; +struct Member { +  Member() : a(n) {} +  constexpr Member(int&a) : a(a) {} +  int &a; +}; +struct NonConstexpr4 { // expected-note {{here}} +  Member m; +}; +constexpr NonConstexpr4 nc4 = NonConstexpr4(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4'}} +struct Constexpr3 { +  constexpr Constexpr3() : m(n) {} +  Member m; +}; +constexpr Constexpr3 c3 = Constexpr3(); // ok +struct Constexpr4 { +  Constexpr3 m; +}; +constexpr Constexpr4 c4 = Constexpr4(); // ok + + +// This rule breaks some legal C++98 programs! +struct A {}; // expected-note {{here}} +struct B { +  friend A::A(); // expected-error {{non-constexpr declaration of 'A' follows constexpr declaration}} +}; diff --git a/clang/test/CXX/special/class.dtor/p10-0x.cpp b/clang/test/CXX/special/class.dtor/p10-0x.cpp new file mode 100644 index 0000000..e10afb5 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p10-0x.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// PR10127/N3031 +struct A { ~A(); }; +struct B {}; +template<typename T> +void b(const T *x, const A *y) { +  x->~decltype(T())(); +  x->~decltype(*x)(); // expected-error{{the type of object expression ('const int') does not match the type being destroyed ('decltype(*x)' (aka 'const int &')) in pseudo-destructor expression}} \ +                         expected-error{{no member named '~const struct A &' in 'A'}} +  x->~decltype(int())(); // expected-error{{no member named '~int' in 'A'}} + +  y->~decltype(*y)(); // expected-error{{destructor type 'decltype(*y)' (aka 'const A &') in object destruction expression does not match the type 'const A' of the object being destroyed}} +  y->~decltype(T())(); // expected-error{{destructor type 'decltype(T())' in object destruction expression does not match the type 'const A' of the object being destroyed}} +  y->~decltype(A())(); +} +template void b(const int*, const A*); // expected-note{{in instantiation of function template specialization 'b<int>' requested here}} +template void b(const A*,const A*); // expected-note{{in instantiation of function template specialization 'b<A>' requested here}} +void a(const A *x, int i, int *pi) { +  x->~decltype(A())(); +  x->~decltype(*x)(); // expected-error{{destructor type 'decltype(*x)' (aka 'const A &') in object destruction expression does not match the type 'const A' of the object being destroyed}} +  x->~decltype()(); // expected-error{{expected expression}} +  x->~decltype(B())(); // expected-error{{destructor type 'decltype(B())' (aka 'B') in object destruction expression does not match the type 'const A' of the object being destroyed}} +  x->~decltype(x)(); // expected-error{{destructor type 'decltype(x)' (aka 'const A *') in object destruction expression does not match the type 'const A' of the object being destroyed}} +  // this last one could be better, mentioning that the nested-name-specifier could be removed or a type name after the ~ +  x->::A::~decltype(*x)(); // expected-error{{expected a class name after '~' to name a destructor}} +  y->~decltype(A())(); // expected-error{{use of undeclared identifier 'y'}} + +  typedef int *intp; +  i->~decltype(int())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} +  i.~decltype(int())(); +  i->~decltype(intp())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} \ +                             expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} +  i.~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} +  pi->~decltype(int())(); +  pi.~decltype(int())(); // expected-error{{the type of object expression ('int *') does not match the type being destroyed ('decltype(int())' (aka 'int')) in pseudo-destructor expression}} +  pi.~decltype(intp())(); +  pi->~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} +} diff --git a/clang/test/CXX/special/class.dtor/p2-0x.cpp b/clang/test/CXX/special/class.dtor/p2-0x.cpp new file mode 100644 index 0000000..c7b1b58 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p2-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// A destructor shall not be declared with a ref-qualifier. +struct X { +  ~X() &; // expected-error{{ref-qualifier '&' is not allowed on a destructor}} +}; + +struct Y { +  ~Y() &&; // expected-error{{ref-qualifier '&&' is not allowed on a destructor}} +}; diff --git a/clang/test/CXX/special/class.dtor/p2.cpp b/clang/test/CXX/special/class.dtor/p2.cpp new file mode 100644 index 0000000..b05c992 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p2.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5548 +struct A {~A();}; +void a(const A* x) { +  x->~A(); +} diff --git a/clang/test/CXX/special/class.dtor/p3-0x.cpp b/clang/test/CXX/special/class.dtor/p3-0x.cpp new file mode 100644 index 0000000..44bf5aa --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p3-0x.cpp @@ -0,0 +1,177 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s + +struct A { +  ~A(); +}; + +struct B { +  ~B() throw(int); +}; + +struct C { +  B b; +  ~C() {} +}; + +struct D { +  ~D() noexcept(false); +}; + +struct E { +  D d; +  ~E() {} +}; + +void foo() { +  A a; +  C c; +  E e; +  // CHECK: invoke {{.*}} @_ZN1ED1Ev +  // CHECK: invoke {{.*}} @_ZN1CD1Ev +  // CHECK: call {{.*}} @_ZN1AD1Ev +} + +struct F { +  D d; +  ~F(); +}; +F::~F() noexcept(false) {} + +struct G { +  D d; +  ~G(); +}; +G::~G() {} + +struct H { +  B b; +  ~H(); +}; +H::~H() throw(int) {} + +struct I { +  B b; +  ~I(); +}; +I::~I() {} + +// Template variants. + +template <typename T> +struct TA { +  ~TA(); +}; + +template <typename T> +struct TB { +  ~TB() throw(int); +}; + +template <typename T> +struct TC { +  TB<T> b; +  ~TC() {} +}; + +template <typename T> +struct TD { +  ~TD() noexcept(false); +}; + +template <typename T> +struct TE { +  TD<T> d; +  ~TE() {} +}; + +void tfoo() { +  TA<int> a; +  TC<int> c; +  TE<int> e; +  // CHECK: invoke {{.*}} @_ZN2TEIiED1Ev +  // CHECK: invoke {{.*}} @_ZN2TCIiED1Ev +  // CHECK: call {{.*}} @_ZN2TAIiED1Ev +} + +template <typename T> +struct TF { +  TD<T> d; +  ~TF(); +}; +template <typename T> +TF<T>::~TF() noexcept(false) {} + +template <typename T> +struct TG { +  TD<T> d; +  ~TG(); +}; +template <typename T> +TG<T>::~TG() {} + +template <typename T> +struct TH { +  TB<T> b; +  ~TH(); +}; +template <typename T> +TH<T>::~TH() {} + +void tinst() { +  TF<int> f; +  TG<int> g; +  TH<int> h; +} +// CHECK: define linkonce_odr {{.*}} @_ZN2THIiED1Ev +// CHECK: _ZTIi +// CHECK: __cxa_call_unexpected + +struct VX +{ virtual ~VX() {} }; + +struct VY : VX +{ virtual ~VY() {} }; + +template<typename T> +struct TVY : VX +{ virtual ~TVY() {} }; + + +struct VA { +  B b; +  virtual ~VA() {} +}; + +struct VB : VA +{ virtual ~VB() {} }; + +template<typename T> +struct TVB : VA +{ virtual ~TVB() {} }; + +void tinst2() { +  TVY<int> tvy; +  TVB<int> tvb; +} + +template <typename T> +struct Sw { +  T t; +  ~Sw() {} +}; + +void tsw() { +  Sw<int> swi; +  Sw<B> swb; +} +// CHECK-NOT: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}} nounwind +// CHECK: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}} +// CHECK: _ZTIi +// CHECK: __cxa_call_unexpected +// CHECK: define linkonce_odr {{.*}} @_ZN2SwIiED1Ev({{.*}} nounwind + +template <typename T> +struct TVC : VX +{ virtual ~TVC(); }; +template <typename T> +TVC<T>::~TVC() {} diff --git a/clang/test/CXX/special/class.dtor/p5-0x.cpp b/clang/test/CXX/special/class.dtor/p5-0x.cpp new file mode 100644 index 0000000..dbfa004 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p5-0x.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +struct NonTrivDtor { +  ~NonTrivDtor(); +}; +struct DeletedDtor { +  ~DeletedDtor() = delete; // expected-note 5 {{deleted here}} +}; +class InaccessibleDtor { +  ~InaccessibleDtor() = default; +}; + +// A defaulted destructor for a class X is defined as deleted if: + +// -- X is a union-like class that has a variant member with a non-trivial +// destructor. +union A1 { +  A1(); +  NonTrivDtor n; // expected-note {{destructor of union 'A1' is implicitly deleted because field 'n' has a non-trivial destructor}} +}; +A1 a1; // expected-error {{deleted function}} +struct A2 { +  A2(); +  union { +    NonTrivDtor n; // expected-note {{because field 'n' has a non-trivial destructor}} +  }; +}; +A2 a2; // expected-error {{deleted function}} +union A3 { +  A3(); +  NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}} +}; +A3 a3; // expected-error {{deleted function}} +struct A4 { +  A4(); +  union { +    NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}} +  }; +}; +A4 a4; // expected-error {{deleted function}} + +// -- any of the non-static data members has class type M (or array thereof) and +// M has a deleted or inaccessible destructor. +struct B1 { +  B1(); +  DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} +}; +B1 b1; // expected-error {{deleted function}} +struct B2 { +  B2(); +  InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}} +}; +B2 b2; // expected-error {{deleted function}} +struct B3 { +  B3(); +  DeletedDtor a[4]; // expected-note {{because field 'a' has a deleted destructor}} +}; +B3 b3; // expected-error {{deleted function}} +struct B4 { +  B4(); +  InaccessibleDtor a[4]; // expected-note {{because field 'a' has an inaccessible destructor}} +}; +B4 b4; // expected-error {{deleted function}} +union B5 { +  B5(); +  // FIXME: Describe the anonymous union member better than ''. +  union { // expected-note {{because field '' has a deleted destructor}} +    DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} +  }; +}; +B5 b5; // expected-error {{deleted function}} +union B6 { +  B6(); +  union { // expected-note {{because field '' has a deleted destructor}} +    InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}} +  }; +}; +B6 b6; // expected-error {{deleted function}} + +// -- any direct or virtual base class has a deleted or inaccessible destructor. +struct C1 : DeletedDtor { C1(); } c1; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}} +struct C2 : InaccessibleDtor { C2(); } c2; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}} +struct C3 : virtual DeletedDtor { C3(); } c3; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}} +struct C4 : virtual InaccessibleDtor { C4(); } c4; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}} + +// -- for a virtual destructor, lookup of the non-array deallocation function +// results in an ambiguity or a function that is deleted or inaccessible. +class D1 { +  void operator delete(void*); +public: +  virtual ~D1() = default; +} d1; // ok +struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} +  // implicitly-virtual destructor +} d2; // expected-error {{deleted function}} +struct D3 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} +  virtual ~D3() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} +  void operator delete(void*, double = 0.0); +  void operator delete(void*, char = 0); +} d3; // expected-error {{deleted function}} +struct D4 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} +  virtual ~D4() = default; // expected-note {{implicitly deleted here}} +  void operator delete(void*) = delete; +} d4; // expected-error {{deleted function}} diff --git a/clang/test/CXX/special/class.dtor/p9.cpp b/clang/test/CXX/special/class.dtor/p9.cpp new file mode 100644 index 0000000..8b76a15 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p9.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef typeof(sizeof(int)) size_t; + +// PR7803 +namespace test0 { +  class A { +  public: +    static void operator delete(void *p) {}; +    virtual ~A(); +  }; + +  class B : protected A { +  public: +    ~B(); +  }; + +  class C : protected B { +  public: +    using B::operator delete; +    ~C(); +  }; + +  // Shouldn't have an error. +  C::~C() {} +} + +namespace test1 { +  class A { +  public: +    static void operator delete(void *p) {}; // expected-note {{member 'operator delete' declared here}} +    virtual ~A(); +  }; + +  class B : protected A { +  public: +    static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}} +    ~B(); +  }; + +  class C : protected B { +  public: +    using A::operator delete; +    using B::operator delete; + +    ~C(); +  }; + +  C::~C() {} // expected-error {{multiple suitable 'operator delete' functions in 'C'}} +} + +// ...at the point of definition of a virtual destructor... +namespace test2 { +  struct A { +    virtual ~A(); +    static void operator delete(void*, const int &); +  }; + +  struct B { +    virtual ~B(); +    static void operator delete(void*, const int &); // expected-note {{declared here}} +  }; +  B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}} + +  struct CBase { virtual ~CBase(); }; +  struct C : CBase { // expected-error {{no suitable member 'operator delete' in 'C'}} +    static void operator delete(void*, const int &); // expected-note {{declared here}} +  }; +  void test() { +    C c; // expected-note {{first required here}} +  } +} + +// PR7346 +namespace test3 { +  struct A { +    virtual ~A(); +    static void operator delete(void*, const int &); +  }; + +  struct B : A { +    virtual ~B() {} +    static void operator delete(void*); +  }; +} diff --git a/clang/test/CXX/special/class.free/p1.cpp b/clang/test/CXX/special/class.free/p1.cpp new file mode 100644 index 0000000..5c0240b --- /dev/null +++ b/clang/test/CXX/special/class.free/p1.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +#include <stddef.h> + +struct A { +  void *operator new(size_t) { +    return this; // expected-error {{invalid use of 'this' outside of a non-static member function}} +  } +  void *operator new[](size_t) { +    return this; // expected-error {{invalid use of 'this' outside of a non-static member function}} +  } +}; diff --git a/clang/test/CXX/special/class.free/p6.cpp b/clang/test/CXX/special/class.free/p6.cpp new file mode 100644 index 0000000..fc4b2ae --- /dev/null +++ b/clang/test/CXX/special/class.free/p6.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +#include <stddef.h> + +struct A { +  void operator delete(void*) { +    (void)this; // expected-error {{invalid use of 'this' outside of a non-static member function}} +  } +  void operator delete[](void*) { +    (void)this; // expected-error {{invalid use of 'this' outside of a non-static member function}} +  } +}; diff --git a/clang/test/CXX/special/class.inhctor/elsewhere.cpp b/clang/test/CXX/special/class.inhctor/elsewhere.cpp new file mode 100644 index 0000000..09fd3d5 --- /dev/null +++ b/clang/test/CXX/special/class.inhctor/elsewhere.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Tests related to constructor inheriting, but not specified in [class.inhctor] + +// [namespace.udecl]p8: +//   A using-declaration for a class member shall be a member-declaration. + +struct B1 { +  B1(int); +}; + +using B1::B1; // expected-error {{using declaration can not refer to class member}} expected-error {{not supported}} + +// C++0x [namespace.udecl]p10: +//   A using-declaration is a declaration and can therefore be used repeatedly +//   where (and only where) multiple declarations are allowed. + +struct I1 : B1 { +  using B1::B1; // expected-note {{previous using declaration}} expected-error {{not supported}} +  using B1::B1; // expected-error {{redeclaration of using decl}} expected-error {{not supported}} +}; + +// C++0x [namespace.udecl]p3: +//   In a using declaration used as a member-declaration, the nested-name- +//   specifier shall name a base class of the class being defined. +//   If such a using-declaration names a constructor, the nested-name-specifier +//   shall name a direct base class of the class being defined. + +struct D1 : I1 { +  using B1::B1; // expected-error {{'B1' is not a direct base of 'D1', can not inherit constructors}} expected-error {{not supported}} +}; + +template<typename T> struct A {}; + +template<typename T> struct B : A<bool>, A<char> { +  using A<T>::A; // expected-error {{'A<double>::', which is not a base class of 'B<double>'}} expected-error {{not supported}} +}; +B<bool> bb; +B<char> bc; +B<double> bd; // expected-note {{here}} + +template<typename T> struct C : A<T> { +  using A<bool>::A; // expected-error {{'A<bool>::', which is not a base class of 'C<char>'}} expected-error {{not supported}} +}; +C<bool> cb; +C<char> cc; // expected-note {{here}} + +template<typename T> struct D : A<T> {}; +template<typename T> struct E : D<T> { +  using A<bool>::A; // expected-error {{'A<bool>' is not a direct base of 'E<bool>', can not inherit}} expected-error {{not supported}} +}; +E<bool> eb; // expected-note {{here}} + +template<typename T> struct F : D<bool> { +  using A<T>::A; // expected-error {{'A<bool>' is not a direct base of 'F<bool>'}} expected-error {{not supported}} +}; +F<bool> fb; // expected-note {{here}} diff --git a/clang/test/CXX/special/class.inhctor/p3.cpp b/clang/test/CXX/special/class.inhctor/p3.cpp new file mode 100644 index 0000000..d7093fb --- /dev/null +++ b/clang/test/CXX/special/class.inhctor/p3.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct B1 { +  B1(int); +  B1(int, int); +}; +struct D1 : B1 { +  using B1::B1; // expected-error {{not supported}} +}; +D1 d1a(1), d1b(1, 1); + +D1 fd1() { return 1; } + +struct B2 { +  explicit B2(int, int = 0, int = 0); +}; +struct D2 : B2 { // expected-note 2 {{candidate constructor}} +  using B2::B2; // expected-error {{not supported}} +}; +D2 d2a(1), d2b(1, 1), d2c(1, 1, 1); + +D2 fd2() { return 1; } // expected-error {{no viable conversion}} + +struct B3 { +  B3(void*); // expected-note {{inherited from here}} +}; +struct D3 : B3 { // expected-note 2 {{candidate constructor}} +  using B3::B3; // expected-note {{candidate constructor (inherited)}} expected-error {{not supported}} +}; +D3 fd3() { return 1; } // expected-error {{no viable conversion}} + +template<typename T> struct T1 : B1 { +  using B1::B1; // expected-error {{not supported}} +}; +template<typename T> struct T2 : T1<T> { +  using T1<int>::T1; // expected-error {{not supported}} +}; +template<typename T> struct T3 : T1<int> { +  using T1<T>::T1; // expected-error {{not supported}} +}; +struct U { +  friend T1<int>::T1(int); +  friend T1<int>::T1(int, int); +  friend T2<int>::T2(int); +  friend T2<int>::T2(int, int); +  friend T3<int>::T3(int); +  friend T3<int>::T3(int, int); +}; diff --git a/clang/test/CXX/special/class.inhctor/p7.cpp b/clang/test/CXX/special/class.inhctor/p7.cpp new file mode 100644 index 0000000..bfaa3ac --- /dev/null +++ b/clang/test/CXX/special/class.inhctor/p7.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Straight from the standard +struct B1 { +  B1(int); // expected-note {{previous constructor}} expected-note {{conflicting constructor}} +}; +struct B2 { +  B2(int); // expected-note {{conflicting constructor}} +}; +struct D1 : B1, B2 { +  using B1::B1; // expected-note {{inherited here}} expected-error {{not supported}} +  using B2::B2; // expected-error {{already inherited constructor with the same signature}} expected-error {{not supported}} +}; +struct D2 : B1, B2 { +  using B1::B1; // expected-error {{not supported}} +  using B2::B2; // expected-error {{not supported}} +  D2(int); +}; + +template<typename T> struct B3 { +  B3(T); // expected-note {{previous constructor}} +}; +template<typename T> struct B4 : B3<T>, B1 { +  B4(); +  using B3<T>::B3; // expected-note {{inherited here}} expected-error {{not supported}} +  using B1::B1; // expected-error {{already inherited}} expected-error {{not supported}} +}; +B4<char> b4c; +B4<int> b4i; // expected-note {{here}} diff --git a/clang/test/CXX/special/class.init/class.base.init/p8-0x.cpp b/clang/test/CXX/special/class.init/class.base.init/p8-0x.cpp new file mode 100644 index 0000000..a108533 --- /dev/null +++ b/clang/test/CXX/special/class.init/class.base.init/p8-0x.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +int n; +struct S { +  int &a; // expected-note 2{{here}} +  int &b = n; + +  union { +    const int k = 42; +  }; + +  S() {} // expected-error {{constructor for 'S' must explicitly initialize the reference member 'a'}} +  S(int) : a(n) {} // ok +  S(char) : b(n) {} // expected-error {{constructor for 'S' must explicitly initialize the reference member 'a'}} +  S(double) : a(n), b(n) {} // ok +} s(0); + +union U { +  int a = 0; // desired-note 5 {{previous initialization is here}} +  char b = 'x'; + +  // FIXME: these should all be rejected +  U() {} // desired-error {{initializing multiple members of union}} +  U(int) : a(1) {} // desired-error {{initializing multiple members of union}} +  U(char) : b('y') {} // desired-error {{initializing multiple members of union}} +  // this expected note should be removed & the note should appear on the  +  // declaration of 'a' when this set of cases is handled correctly. +  U(double) : a(1), // expected-note{{previous initialization is here}} desired-error {{initializing multiple members of union}} +              b('y') {} // expected-error{{initializing multiple members of union}} +}; + +// PR10954: variant members do not acquire an implicit initializer. +namespace VariantMembers { +  struct NoDefaultCtor { +    NoDefaultCtor(int); +  }; +  union V { +    NoDefaultCtor ndc; +    int n; + +    V() {} +    V(int n) : n(n) {} +    V(int n, bool) : ndc(n) {} +  }; +  struct K { +    union { +      NoDefaultCtor ndc; +      int n; +    }; +    K() {} +    K(int n) : n(n) {} +    K(int n, bool) : ndc(n) {} +  }; +  struct Nested { +    Nested() {} +    union { +      struct { +        NoDefaultCtor ndc; +      }; +    }; +  }; +} diff --git a/clang/test/CXX/special/class.init/class.base.init/p9-0x.cpp b/clang/test/CXX/special/class.init/class.base.init/p9-0x.cpp new file mode 100644 index 0000000..ca5e807 --- /dev/null +++ b/clang/test/CXX/special/class.init/class.base.init/p9-0x.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++11 %s -O1 -emit-llvm -o - | FileCheck %s + +struct S { +  int n = 10; +  int m = 2 * n; + +  S() {} +  S(int a) : n(a) {} +  S(int a, int b) : n(a), m(b) {} + +  struct T { +    T *that = this; +  }; +}; + +template<typename T> +struct U { +  T *r = &q; +  T q = 42; +  U *p = this; +}; + +S a; +// CHECK: @a = {{.*}} { i32 10, i32 20 } + +S b(5); +// CHECK: @b = {{.*}} { i32 5, i32 10 } + +S c(3, 9); +// CHECK: @c = {{.*}} { i32 3, i32 9 } + +S::T d; +// CHECK: @d = {{.*}} { {{.*}} @d } + +U<S> e; +// CHECK: @e = {{.*}} { {{.*}} { i32 42, i32 84 }, {{.*}} @e } diff --git a/clang/test/CXX/special/class.temporary/p1.cpp b/clang/test/CXX/special/class.temporary/p1.cpp new file mode 100644 index 0000000..4f6ac0a --- /dev/null +++ b/clang/test/CXX/special/class.temporary/p1.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +namespace test0 { +  struct A { +    A() = default; +    int x; +    int y; + +    A(const A&) = delete; // expected-note {{function has been explicitly marked deleted here}} +  }; + +  void foo(...); + +  void test() { +    A a; +    foo(a); // expected-error {{call to deleted constructor of 'test0::A'}} +  } +} + +namespace test1 { +  struct A { +    A() = default; +    int x; +    int y; + +  private: +    A(const A&) = default; // expected-note {{declared private here}} +  }; + +  void foo(...); + +  void test() { +    A a; +    foo(a); // expected-error {{calling a private constructor of class 'test1::A'}} +  } +} + +// Don't enforce this in an unevaluated context. +namespace test2 { +  struct A { +    A(const A&) = delete; // expected-note {{marked deleted here}} +  }; + +  typedef char one[1]; +  typedef char two[2]; + +  one &meta(bool); +  two &meta(...); + +  void a(A &a) { +    char check[sizeof(meta(a)) == 2 ? 1 : -1]; +  } + +  void b(A &a) { +    meta(a); // expected-error {{call to deleted constructor}} +  } +} | 
