summaryrefslogtreecommitdiffstats
path: root/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
blob: 2b7886d383db85ec47b106c14590f5fe812db888 (plain)
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
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions %s

// An explicitly-defaulted function may be declared constexpr only if it would
// have been implicitly declared as constexpr.
struct S1 {
  constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
  constexpr S1(const S1&) = default;
  constexpr S1(S1&&) = default;
  constexpr S1 &operator=(const S1&) const = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}}
  constexpr S1 &operator=(S1&&) const = default; // expected-error {{explicitly-defaulted move assignment operator may not have}}
  constexpr ~S1() = default; // expected-error {{destructor cannot be marked constexpr}}
  int n;
};
struct NoCopyMove {
  constexpr NoCopyMove() {}
  NoCopyMove(const NoCopyMove&);
  NoCopyMove(NoCopyMove&&);
};
struct S2 {
  constexpr S2() = default;
  constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}}
  constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}}
  NoCopyMove ncm;
};

// If a function is explicitly defaulted on its first declaration
//   -- it is implicitly considered to be constexpr if the implicit declaration
//      would be
struct S3 {
  S3() = default;
  S3(const S3&) = default;
  S3(S3&&) = default;
  constexpr S3(int n) : n(n) {}
  int n;
};
constexpr S3 s3a = S3(0);
constexpr S3 s3b = s3a;
constexpr S3 s3c = S3();
constexpr S3 s3d; // expected-error {{default initialization of an object of const type 'const S3' without a user-provided default constructor}}

struct S4 {
  S4() = default;
  S4(const S4&) = default; // expected-note {{here}}
  S4(S4&&) = default; // expected-note {{here}}
  NoCopyMove ncm;
};
constexpr S4 s4a{}; // ok
constexpr S4 s4b = S4(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor}}
constexpr S4 s4c = s4a; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}}

struct S5 {
  constexpr S5();
  int n = 1, m = n + 3;
};
constexpr S5::S5() = default;
static_assert(S5().m == 4, "");


// An explicitly-defaulted function may have a different exception specification
// from the exception specification on an implicit declaration.
struct E1 {
  E1() noexcept = default;
  E1(const E1&) noexcept = default;
  E1(E1&&) noexcept = default;
  E1 &operator=(const E1&) noexcept = default;
  E1 &operator=(E1&&) noexcept = default;
  ~E1() noexcept = default;
};
struct E2 {
  E2() noexcept(false) = default;
  E2(const E2&) noexcept(false) = default;
  E2(E2&&) noexcept(false) = default;
  E2 &operator=(const E2&) noexcept(false) = default;
  E2 &operator=(E2&&) noexcept(false) = default;
  ~E2() noexcept(false) = default;
};
E2 e2;
E2 make_e2() noexcept;
void take_e2(E2&&) noexcept;
static_assert(!noexcept(E2()), "");
static_assert(!noexcept(E2(e2)), "");
static_assert(!noexcept(E2(static_cast<E2&&>(e2))), "");
static_assert(!noexcept(e2 = e2), "");
static_assert(!noexcept(e2 = static_cast<E2&&>(e2)), "");
// FIXME: This expression results in destruction of an E2 temporary; the
// noexcept expression should evaluate to false.
static_assert(noexcept(take_e2(make_e2())), "");

// If a function is explicitly defaulted on its first declaration
//   -- it is implicitly considered to have the same exception-specification as
//      if it had been implicitly declared
struct E3 {
  E3() = default;
  E3(const E3&) = default;
  E3(E3&&) = default;
  E3 &operator=(const E3&) = default;
  E3 &operator=(E3&&) = default;
  ~E3() = default;
};
E3 e3;
static_assert(noexcept(E3(), E3(E3()), E3(e3), e3 = E3(), e3 = e3), "");
struct E4 {
  E4() noexcept(false);
  E4(const E4&) noexcept(false);
  E4(E4&&) noexcept(false);
  E4 &operator=(const E4&) noexcept(false);
  E4 &operator=(E4&&) noexcept(false);
  ~E4() noexcept(false);
};
struct E5 {
  E5() = default;
  E5(const E5&) = default;
  E5(E5&&) = default;
  E5 &operator=(const E5&) = default;
  E5 &operator=(E5&&) = default;
  ~E5() = default;

  E4 e4;
};
E5 e5;
static_assert(!noexcept(E5()), "");
static_assert(!noexcept(E5(static_cast<E5&&>(e5))), "");
static_assert(!noexcept(E5(e5)), "");
static_assert(!noexcept(e5 = E5()), "");
static_assert(!noexcept(e5 = e5), "");

namespace PR13492 {
  struct B {
    B() = default;
    int field;
  };

  void f() {
    const B b; // expected-error {{default initialization of an object of const type 'const PR13492::B' without a user-provided default constructor}}
  }
}