1// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
2
3struct non_trivial {
4  non_trivial();
5  non_trivial(const non_trivial&);
6  non_trivial& operator = (const non_trivial&);
7  ~non_trivial();
8};
9
10union u {
11  non_trivial nt;
12};
13union u2 {
14  non_trivial nt;
15  int k;
16  u2(int k) : k(k) {}
17  u2() : nt() {}
18};
19
20union static_data_member {
21  static int i;
22};
23int static_data_member::i;
24
25union bad {
26  int &i; // expected-error {{union member 'i' has reference type 'int &'}}
27};
28
29struct s {
30  union {
31    non_trivial nt;
32  };
33};
34
35// Don't crash on this.
36struct TemplateCtor { template<typename T> TemplateCtor(T); };
37union TemplateCtorMember { TemplateCtor s; };
38
39template<typename T> struct remove_ref { typedef T type; };
40template<typename T> struct remove_ref<T&> { typedef T type; };
41template<typename T> struct remove_ref<T&&> { typedef T type; };
42template<typename T> T &&forward(typename remove_ref<T>::type &&t);
43template<typename T> T &&forward(typename remove_ref<T>::type &t);
44template<typename T> typename remove_ref<T>::type &&move(T &&t);
45
46using size_t = decltype(sizeof(int));
47void *operator new(size_t, void *p) noexcept { return p; }
48
49namespace 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
68namespace 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*() const { 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
126namespace 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