aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/special/class.copy/p13-0x.cpp
blob: 16c8a4029cbac669dca3dbdac8e82df7e5abaa7d (plain) (blame)
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
// 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;

// An explicitly-defaulted constructor doesn't become constexpr until the end of
// its class. Make sure we note that the class has a constexpr constructor when
// that happens.
namespace PR13052 {
  template<typename T> struct S {
    S() = default; // expected-note 2{{here}}
    S(S&&) = default;
    S(const S&) = default;
    T t;
  };

  struct U {
    U() = default;
    U(U&&) = default;
    U(const U&) = default;
  };

  struct V {
    V(); // expected-note {{here}}
    V(V&&) = default;
    V(const V&) = default;
  };

  struct W {
    W(); // expected-note {{here}}
  };

  static_assert(__is_literal_type(U), "");
  static_assert(!__is_literal_type(V), "");
  static_assert(!__is_literal_type(W), "");
  static_assert(__is_literal_type(S<U>), "");
  static_assert(!__is_literal_type(S<V>), "");
  static_assert(!__is_literal_type(S<W>), "");

  struct X {
    friend constexpr U::U() noexcept;
    friend constexpr U::U(U&&) noexcept;
    friend constexpr U::U(const U&) noexcept;
    friend constexpr V::V(); // expected-error {{follows non-constexpr declaration}}
    friend constexpr V::V(V&&) noexcept;
    friend constexpr V::V(const V&) noexcept;
    friend constexpr W::W(); // expected-error {{follows non-constexpr declaration}}
    friend constexpr W::W(W&&) noexcept;
    friend constexpr W::W(const W&) noexcept;
    friend constexpr S<U>::S() noexcept;
    friend constexpr S<U>::S(S<U>&&) noexcept;
    friend constexpr S<U>::S(const S<U>&) noexcept;
    friend constexpr S<V>::S(); // expected-error {{follows non-constexpr declaration}}
    friend constexpr S<V>::S(S<V>&&) noexcept;
    friend constexpr S<V>::S(const S<V>&) noexcept;
    friend constexpr S<W>::S(); // expected-error {{follows non-constexpr declaration}}
    friend constexpr S<W>::S(S<W>&&) noexcept;
    friend constexpr S<W>::S(const S<W>&) noexcept;
  };
}

namespace Mutable {
  struct A {
    constexpr A(A &);
    A(const A &);
  };
  struct B {
    constexpr B(const B &) = default; // ok
    mutable A a;
  };
  struct C {
    constexpr C(const C &) = default; // expected-error {{not constexpr}}
    A a;
  };
}