1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
2 | |
3 | struct non_trivial { |
4 | non_trivial(); |
5 | non_trivial(const non_trivial&); |
6 | non_trivial& operator = (const non_trivial&); |
7 | ~non_trivial(); |
8 | }; |
9 | |
10 | union u { |
11 | non_trivial nt; |
12 | }; |
13 | union u2 { |
14 | non_trivial nt; |
15 | int k; |
16 | u2(int k) : k(k) {} |
17 | u2() : nt() {} |
18 | }; |
19 | |
20 | union static_data_member { |
21 | static int i; |
22 | }; |
23 | int static_data_member::i; |
24 | |
25 | union bad { |
26 | int &i; // expected-error {{union member 'i' has reference type 'int &'}} |
27 | }; |
28 | |
29 | struct s { |
30 | union { |
31 | non_trivial nt; |
32 | }; |
33 | }; |
34 | |
35 | // Don't crash on this. |
36 | struct TemplateCtor { template<typename T> TemplateCtor(T); }; |
37 | union TemplateCtorMember { TemplateCtor s; }; |
38 | |
39 | template<typename T> struct remove_ref { typedef T type; }; |
40 | template<typename T> struct remove_ref<T&> { typedef T type; }; |
41 | template<typename T> struct remove_ref<T&&> { typedef T type; }; |
42 | template<typename T> T &&forward(typename remove_ref<T>::type &&t); |
43 | template<typename T> T &&forward(typename remove_ref<T>::type &t); |
44 | template<typename T> typename remove_ref<T>::type &&move(T &&t); |
45 | |
46 | using size_t = decltype(sizeof(int)); |
47 | void *operator new(size_t, void *p) noexcept { return p; } |
48 | |
49 | namespace disabled_dtor { |
50 | template<typename T> |
51 | union disable_dtor { |
52 | T val; |
53 | template<typename...U> |
54 | disable_dtor(U &&...u) : val(forward<U>(u)...) {} |
55 | ~disable_dtor() {} |
56 | }; |
57 | |
58 | struct deleted_dtor { |
59 | deleted_dtor(int n, char c) : n(n), c(c) {} |
60 | int n; |
61 | char c; |
62 | ~deleted_dtor() = delete; |
63 | }; |
64 | |
65 | disable_dtor<deleted_dtor> dd(4, 'x'); |
66 | } |
67 | |
68 | namespace optional { |
69 | template<typename T> struct optional { |
70 | bool has; |
71 | union { T value; }; |
72 | |
73 | optional() : has(false) {} |
74 | template<typename...U> |
75 | optional(U &&...u) : has(true), value(forward<U>(u)...) {} |
76 | |
77 | optional(const optional &o) : has(o.has) { |
78 | if (has) new (&value) T(o.value); |
79 | } |
80 | optional(optional &&o) : has(o.has) { |
81 | if (has) new (&value) T(move(o.value)); |
82 | } |
83 | |
84 | optional &operator=(const optional &o) { |
85 | if (has) { |
86 | if (o.has) |
87 | value = o.value; |
88 | else |
89 | value.~T(); |
90 | } else if (o.has) { |
91 | new (&value) T(o.value); |
92 | } |
93 | has = o.has; |
94 | } |
95 | optional &operator=(optional &&o) { |
96 | if (has) { |
97 | if (o.has) |
98 | value = move(o.value); |
99 | else |
100 | value.~T(); |
101 | } else if (o.has) { |
102 | new (&value) T(move(o.value)); |
103 | } |
104 | has = o.has; |
105 | } |
106 | |
107 | ~optional() { |
108 | if (has) |
109 | value.~T(); |
110 | } |
111 | |
112 | explicit operator bool() const { return has; } |
113 | T &operator*() { return value; } |
114 | }; |
115 | |
116 | optional<non_trivial> o1; |
117 | optional<non_trivial> o2{non_trivial()}; |
118 | optional<non_trivial> o3{*o2}; |
119 | void f() { |
120 | if (o2) |
121 | o1 = o2; |
122 | o2 = optional<non_trivial>(); |
123 | } |
124 | } |
125 | |
126 | namespace pr16061 { |
127 | struct X { X(); }; |
128 | |
129 | template<typename T> struct Test1 { |
130 | union { |
131 | struct { |
132 | X x; |
133 | }; |
134 | }; |
135 | }; |
136 | |
137 | template<typename T> struct Test2 { |
138 | union { |
139 | struct { // expected-note {{default constructor of 'Test2<pr16061::X>' is implicitly deleted because variant field '' has a non-trivial default constructor}} |
140 | T x; |
141 | }; |
142 | }; |
143 | }; |
144 | |
145 | Test2<X> t2x; // expected-error {{call to implicitly-deleted default constructor of 'Test2<pr16061::X>'}} |
146 | } |
147 | |