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

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 'Deleted1a' is implicitly deleted because variant 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 = static_cast<int&&>(n); };
NotDeleted2c nd2c;
// Note: this one does not have a deleted default constructor even though the
// implicit default constructor is ill-formed!
class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' binds to a temporary object}} expected-note {{default member init}}
NotDeleted2d nd2d; // expected-note {{first required here}}

// - 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 [42]' 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 variant 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");

#define ASSERT_NONTRIVIAL_IMPL(Class, Bases, Body) \
  class Class Bases { Body }; \
  static_assert(!__has_trivial_constructor(Class), "");
#define ASSERT_NONTRIVIAL(Class, Bases, Body) \
  ASSERT_NONTRIVIAL_IMPL(Class, Bases, Body) \
  ASSERT_NONTRIVIAL_IMPL(Def ## Class, Bases, Def ## Class() = default; Body) \
  ASSERT_NONTRIVIAL_IMPL(Del ## Class, Bases, Del ## Class() = delete; Body)

// - its class has no virtual functions (10.3) and no virtual base classes (10.1), and
ASSERT_NONTRIVIAL(NonTrivialDefCtor2, , virtual void f();)
ASSERT_NONTRIVIAL(NonTrivialDefCtor3, : virtual Trivial, )

// - no non-static data member of its class has a brace-or-equal-initializer, and
ASSERT_NONTRIVIAL(NonTrivialDefCtor4, , int m = 52;)

// - all the direct base classes of its class have trivial default constructors, and
ASSERT_NONTRIVIAL(NonTrivialDefCtor5, : NonTrivialDefCtor1, )

// - 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.
ASSERT_NONTRIVIAL(NonTrivialDefCtor6, , NonTrivialDefCtor1 t;)

// FIXME: No core issue number yet.
// - its parameter-declaration-clause is equivalent to that of an implicit declaration.
struct NonTrivialDefCtor7 {
  NonTrivialDefCtor7(...) = delete;
};
static_assert(!__has_trivial_constructor(NonTrivialDefCtor7), "");
struct NonTrivialDefCtor8 {
  NonTrivialDefCtor8(int = 0) = delete;
};
static_assert(!__has_trivial_constructor(NonTrivialDefCtor8), "");

// 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");

namespace PR14558 {
  // Ensure we determine whether an explicitly-defaulted or deleted special
  // member is trivial before we return to parsing the containing class.
  struct A {
    struct B { B() = default; } b;
    struct C { C() = delete; } c;
  };

  static_assert(__has_trivial_constructor(A), "");
  static_assert(__has_trivial_constructor(A::B), "");
}