diff options
Diffstat (limited to 'clang/test/SemaCXX/cxx0x-nontrivial-union.cpp')
-rw-r--r-- | clang/test/SemaCXX/cxx0x-nontrivial-union.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp new file mode 100644 index 0000000..0e4add8 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -0,0 +1,124 @@ +// 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>(); + } +} |