| // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
| |
| struct non_trivial { |
| non_trivial(); |
| non_trivial(const non_trivial&); |
| non_trivial& operator = (const non_trivial&); |
| ~non_trivial(); |
| }; |
| |
| union u { |
| non_trivial nt; |
| }; |
| union u2 { |
| non_trivial nt; |
| int k; |
| u2(int k) : k(k) {} |
| u2() : nt() {} |
| }; |
| |
| union static_data_member { |
| static int i; |
| }; |
| int static_data_member::i; |
| |
| union bad { |
| int &i; // expected-error {{union member 'i' has reference type 'int &'}} |
| }; |
| |
| struct s { |
| union { |
| non_trivial nt; |
| }; |
| }; |
| |
| // Don't crash on this. |
| struct TemplateCtor { template<typename T> TemplateCtor(T); }; |
| union TemplateCtorMember { TemplateCtor s; }; |
| |
| template<typename T> struct remove_ref { typedef T type; }; |
| template<typename T> struct remove_ref<T&> { typedef T type; }; |
| template<typename T> struct remove_ref<T&&> { typedef T type; }; |
| template<typename T> T &&forward(typename remove_ref<T>::type &&t); |
| template<typename T> T &&forward(typename remove_ref<T>::type &t); |
| template<typename T> typename remove_ref<T>::type &&move(T &&t); |
| |
| using size_t = decltype(sizeof(int)); |
| void *operator new(size_t, void *p) noexcept { return p; } |
| |
| namespace disabled_dtor { |
| template<typename T> |
| union disable_dtor { |
| T val; |
| template<typename...U> |
| disable_dtor(U &&...u) : val(forward<U>(u)...) {} |
| ~disable_dtor() {} |
| }; |
| |
| struct deleted_dtor { |
| deleted_dtor(int n, char c) : n(n), c(c) {} |
| int n; |
| char c; |
| ~deleted_dtor() = delete; |
| }; |
| |
| disable_dtor<deleted_dtor> dd(4, 'x'); |
| } |
| |
| namespace optional { |
| template<typename T> struct optional { |
| bool has; |
| union { T value; }; |
| |
| optional() : has(false) {} |
| template<typename...U> |
| optional(U &&...u) : has(true), value(forward<U>(u)...) {} |
| |
| optional(const optional &o) : has(o.has) { |
| if (has) new (&value) T(o.value); |
| } |
| optional(optional &&o) : has(o.has) { |
| if (has) new (&value) T(move(o.value)); |
| } |
| |
| optional &operator=(const optional &o) { |
| if (has) { |
| if (o.has) |
| value = o.value; |
| else |
| value.~T(); |
| } else if (o.has) { |
| new (&value) T(o.value); |
| } |
| has = o.has; |
| } |
| optional &operator=(optional &&o) { |
| if (has) { |
| if (o.has) |
| value = move(o.value); |
| else |
| value.~T(); |
| } else if (o.has) { |
| new (&value) T(move(o.value)); |
| } |
| has = o.has; |
| } |
| |
| ~optional() { |
| if (has) |
| value.~T(); |
| } |
| |
| explicit operator bool() const { return has; } |
| T &operator*() const { return value; } |
| }; |
| |
| optional<non_trivial> o1; |
| optional<non_trivial> o2{non_trivial()}; |
| optional<non_trivial> o3{*o2}; |
| void f() { |
| if (o2) |
| o1 = o2; |
| o2 = optional<non_trivial>(); |
| } |
| } |