Richard Smith | 7a614d8 | 2011-06-11 17:19:42 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x |
| 2 | |
| 3 | struct DefaultedDefCtor1 {}; |
| 4 | struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; }; |
| 5 | struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); }; |
| 6 | class PrivateDefCtor { PrivateDefCtor() = default; public: PrivateDefCtor(int); }; |
| 7 | struct DeletedDtor { ~DeletedDtor() = delete; }; |
| 8 | class PrivateDtor { ~PrivateDtor() = default; }; |
| 9 | class Friend { |
| 10 | Friend() = default; ~Friend() = default; |
| 11 | friend struct NotDeleted6c; |
| 12 | friend struct NotDeleted7i; |
| 13 | friend struct NotDeleted7j; |
| 14 | friend struct NotDeleted7k; |
| 15 | }; |
| 16 | struct UserProvidedDefCtor { UserProvidedDefCtor() {} }; |
| 17 | int n; |
| 18 | |
| 19 | |
| 20 | // A defaulted default constructor for a class X is defined as deleted if: |
| 21 | |
| 22 | // - X is a union-like class that has a variant member with a non-trivial |
| 23 | // default constructor, |
| 24 | union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{deleted here}} |
| 25 | Deleted1a d1a; // expected-error {{deleted constructor}} |
| 26 | // FIXME: treating this as having a deleted default constructor is probably a |
| 27 | // bug in the standard. |
| 28 | union Deleted1b { UserProvidedDefCtor u = UserProvidedDefCtor(); }; // expected-note {{deleted here}} |
| 29 | Deleted1b d1b; // expected-error {{deleted constructor}} |
| 30 | union NotDeleted1a { DefaultedDefCtor1 nu; }; |
| 31 | NotDeleted1a nd1a; |
| 32 | // FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2's |
| 33 | // default constructor is non-trivial. |
| 34 | union NotDeleted1b { DefaultedDefCtor2 nu; }; // unexpected-note {{deleted here}} |
| 35 | NotDeleted1b nd1b; // unexpected-error {{deleted constructor}} |
| 36 | |
| 37 | // - any non-static data member with no brace-or-equal-initializer is of |
| 38 | // reference type, |
| 39 | class Deleted2a { Deleted2a() = default; int &a; }; // expected-note {{deleted here}} |
| 40 | Deleted2a d2a; // expected-error {{deleted constructor}} |
| 41 | class NotDeleted2a { int &a = n; }; |
| 42 | NotDeleted2a nd2a; |
| 43 | class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}} |
| 44 | NotDeleted2b nd2b; |
| 45 | |
| 46 | // - any non-variant non-static data member of const qualified type (or array |
| 47 | // thereof) with no brace-or-equal-initializer does not have a user-provided |
| 48 | // default constructor, |
| 49 | class Deleted3a { const int a; }; // expected-note {{here}} \ |
| 50 | expected-warning {{does not declare any constructor}} \ |
| 51 | expected-note {{will never be initialized}} |
| 52 | Deleted3a d3a; // expected-error {{deleted constructor}} |
| 53 | class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{here}} |
| 54 | Deleted3b d3b; // expected-error {{deleted constructor}} |
| 55 | // FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2's |
| 56 | // default constructor is user-provided. |
| 57 | class Deleted3c { const DefaultedDefCtor2 a; }; // desired-note {{here}} |
| 58 | Deleted3c d3c; // desired-error {{deleted constructor}} |
| 59 | class NotDeleted3a { const int a = 0; }; |
| 60 | NotDeleted3a nd3a; |
| 61 | class NotDeleted3b { const DefaultedDefCtor1 a[42] = {}; }; |
| 62 | NotDeleted3b nd3b; |
| 63 | class NotDeleted3c { const DefaultedDefCtor2 a = DefaultedDefCtor2(); }; |
| 64 | NotDeleted3c nd3c; |
| 65 | union NotDeleted3d { const int a; int b; }; |
| 66 | NotDeleted3d nd3d; |
| 67 | // FIXME: this class should not have a deleted default constructor. |
| 68 | union NotDeleted3e { const DefaultedDefCtor1 a[42]; int b; }; // unexpected-note {{here}} |
| 69 | NotDeleted3e nd3e; // unexpected-error {{deleted constructor}} |
| 70 | // FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2 is |
| 71 | // non-trivial. |
| 72 | union NotDeleted3f { const DefaultedDefCtor2 a; int b; }; // unexpected-note {{here}} |
| 73 | NotDeleted3f nd3f; // unexpected-error {{deleted constructor}} |
| 74 | |
| 75 | // - X is a union and all of its variant members are of const-qualified type (or |
| 76 | // array thereof), |
| 77 | union Deleted4a { const int a; const int b; const UserProvidedDefCtor c; }; // expected-note {{here}} |
| 78 | Deleted4a d4a; // expected-error {{deleted constructor}} |
| 79 | union Deleted4b { const int a; int b; }; |
| 80 | Deleted4b d4b; |
| 81 | |
| 82 | // - X is a non-union class and all members of any anonymous union member are of |
| 83 | // const-qualified type (or array thereof), |
| 84 | struct Deleted5a { union { const int a; }; union { int b; }; }; // expected-note {{here}} |
| 85 | Deleted5a d5a; // expected-error {{deleted constructor}} |
| 86 | struct Deleted5b { union { const int a; int b; }; union { const int c; int d; }; }; |
| 87 | Deleted5b d5b; |
| 88 | |
| 89 | // - any direct or virtual base class, or non-static data member with no |
| 90 | // brace-or-equal-initializer, has class type M (or array thereof) and either |
| 91 | // M has no default constructor or overload resolution as applied to M's default |
| 92 | // constructor results in an ambiguity or in a function that is deleted or |
| 93 | // inaccessible from the defaulted default constructor, or |
| 94 | struct Deleted6a : Deleted2a {}; // expected-note {{here}} |
| 95 | Deleted6a d6a; // expected-error {{deleted constructor}} |
| 96 | struct Deleted6b : virtual Deleted2a {}; // expected-note {{here}} |
| 97 | Deleted6b d6b; // expected-error {{deleted constructor}} |
| 98 | struct Deleted6c { Deleted2a a; }; // expected-note {{here}} |
| 99 | Deleted6c d6c; // expected-error {{deleted constructor}} |
| 100 | struct Deleted6d { DeletedDefCtor a; }; // expected-note {{here}} |
| 101 | Deleted6d d6d; // expected-error {{deleted constructor}} |
| 102 | struct NotDeleted6a { DeletedDefCtor a = 0; }; |
| 103 | NotDeleted6a nd6a; |
| 104 | struct Deleted6e { PrivateDefCtor a; }; // expected-note {{here}} |
| 105 | Deleted6e d6e; // expected-error {{deleted constructor}} |
| 106 | struct NotDeleted6b { PrivateDefCtor a = 0; }; |
| 107 | NotDeleted6b nd6b; |
| 108 | struct NotDeleted6c { Friend a; }; |
| 109 | NotDeleted6c nd6c; |
| 110 | |
| 111 | // - any direct or virtual base class or non-static data member has a type with |
| 112 | // a destructor that is deleted or inaccessible from the defaulted default |
| 113 | // constructor. |
| 114 | struct Deleted7a : DeletedDtor {}; // expected-note {{here}} |
| 115 | Deleted7a d7a; // expected-error {{deleted constructor}} |
| 116 | struct Deleted7b : virtual DeletedDtor {}; // expected-note {{here}} |
| 117 | Deleted7b d7b; // expected-error {{deleted constructor}} |
| 118 | struct Deleted7c { DeletedDtor a; }; // expected-note {{here}} |
| 119 | Deleted7c d7c; // expected-error {{deleted constructor}} |
| 120 | struct Deleted7d { DeletedDtor a = {}; }; // expected-note {{here}} |
| 121 | Deleted7d d7d; // expected-error {{deleted constructor}} |
| 122 | struct Deleted7e : PrivateDtor {}; // expected-note {{here}} |
| 123 | Deleted7e d7e; // expected-error {{deleted constructor}} |
| 124 | struct Deleted7f : virtual PrivateDtor {}; // expected-note {{here}} |
| 125 | Deleted7f d7f; // expected-error {{deleted constructor}} |
| 126 | struct Deleted7g { PrivateDtor a; }; // expected-note {{here}} |
| 127 | Deleted7g d7g; // expected-error {{deleted constructor}} |
| 128 | struct Deleted7h { PrivateDtor a = {}; }; // expected-note {{here}} |
| 129 | Deleted7h d7h; // expected-error {{deleted constructor}} |
| 130 | struct NotDeleted7i : Friend {}; |
| 131 | NotDeleted7i d7i; |
| 132 | struct NotDeleted7j : virtual Friend {}; |
| 133 | NotDeleted7j d7j; |
| 134 | struct NotDeleted7k { Friend a; }; |
| 135 | NotDeleted7k d7k; |
| 136 | |
| 137 | |
| 138 | class Trivial { static const int n = 42; }; |
| 139 | static_assert(__has_trivial_constructor(Trivial), "Trivial is nontrivial"); |
| 140 | |
| 141 | // A default constructor is trivial if it is not user-provided and if: |
| 142 | class NonTrivialDefCtor1 { NonTrivialDefCtor1(); }; |
| 143 | static_assert(!__has_trivial_constructor(NonTrivialDefCtor1), "NonTrivialDefCtor1 is trivial"); |
| 144 | |
| 145 | // - its class has no virtual functions (10.3) and no virtual base classes (10.1), and |
| 146 | class NonTrivialDefCtor2 { virtual void f(); }; |
| 147 | static_assert(!__has_trivial_constructor(NonTrivialDefCtor2), "NonTrivialDefCtor2 is trivial"); |
| 148 | class NonTrivialDefCtor3 : virtual Trivial {}; |
| 149 | static_assert(!__has_trivial_constructor(NonTrivialDefCtor3), "NonTrivialDefCtor3 is trivial"); |
| 150 | |
| 151 | // - no non-static data member of its class has a brace-or-equal-initializer, and |
| 152 | class NonTrivialDefCtor4 { int m = 52; }; |
| 153 | static_assert(!__has_trivial_constructor(NonTrivialDefCtor4), "NonTrivialDefCtor4 is trivial"); |
| 154 | |
| 155 | // - all the direct base classes of its class have trivial default constructors, and |
| 156 | class NonTrivialDefCtor5 : NonTrivialDefCtor1 {}; |
| 157 | static_assert(!__has_trivial_constructor(NonTrivialDefCtor5), "NonTrivialDefCtor5 is trivial"); |
| 158 | |
| 159 | // - for all the non-static data members of its class that are of class type (or array thereof), each such class |
| 160 | // has a trivial default constructor. |
| 161 | class NonTrivialDefCtor6 { NonTrivialDefCtor1 t; }; |
| 162 | static_assert(!__has_trivial_constructor(NonTrivialDefCtor6), "NonTrivialDefCtor5 is trivial"); |
| 163 | |
| 164 | // Otherwise, the default constructor is non-trivial. |
| 165 | class Trivial2 { Trivial2() = delete; }; |
| 166 | //static_assert(__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial"); |
| 167 | // FIXME: clang implements the pre-FDIS rule, under which this class is non-trivial. |
| 168 | static_assert(!__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial"); |
| 169 | |
| 170 | class Trivial3 { Trivial3() = default; }; |
| 171 | //static_assert(__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial"); |
| 172 | // FIXME: clang implements the pre-FDIS rule, under which this class is non-trivial. |
| 173 | static_assert(!__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial"); |