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