summaryrefslogtreecommitdiff
path: root/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/SemaCXX/cxx0x-nontrivial-union.cpp')
-rw-r--r--clang/test/SemaCXX/cxx0x-nontrivial-union.cpp124
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>();
+ }
+}