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;
u2(int k)16   u2(int k) : k(k) {}
u2()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));
operator new(size_t,void * p)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>
disable_dtor(U &&...u)54     disable_dtor(U &&...u) : val(forward<U>(u)...) {}
~disable_dtor()55     ~disable_dtor() {}
56   };
57 
58   struct deleted_dtor {
deleted_dtordisabled_dtor::deleted_dtor59     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 
optionaloptional::optional73     optional() : has(false) {}
74     template<typename...U>
optionaloptional::optional75     optional(U &&...u) : has(true), value(forward<U>(u)...) {}
76 
optionaloptional::optional77     optional(const optional &o) : has(o.has) {
78       if (has) new (&value) T(o.value);
79     }
optionaloptional::optional80     optional(optional &&o) : has(o.has) {
81       if (has) new (&value) T(move(o.value));
82     }
83 
operator =optional::optional84     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     }
operator =optional::optional95     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 
~optionaloptional::optional107     ~optional() {
108       if (has)
109         value.~T();
110     }
111 
operator booloptional::optional112     explicit operator bool() const { return has; }
operator *optional::optional113     T &operator*() { return value; }
114   };
115 
116   optional<non_trivial> o1;
117   optional<non_trivial> o2{non_trivial()};
118   optional<non_trivial> o3{*o2};
f()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