"This patch implements the restrictions on union members detailed in
[class.union]p1", from John McCall!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76766 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp
new file mode 100644
index 0000000..0c7eafe
--- /dev/null
+++ b/test/CXX/class/class.union/p1.cpp
@@ -0,0 +1,105 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void abort();
+
+class Okay {
+ int a_;
+};
+
+class Virtual {
+ virtual void foo() { abort(); } // expected-note 3 {{because type 'class Virtual' has a virtual member function}}
+};
+
+class VirtualBase : virtual Okay { // expected-note 3 {{because type 'class VirtualBase' has a virtual base class}}
+};
+
+class Ctor {
+ Ctor() { abort(); } // expected-note 3 {{because type 'class Ctor' has a user-declared constructor}}
+};
+
+class CopyCtor {
+ CopyCtor(CopyCtor &cc) { abort(); } // expected-note 3 {{because type 'class CopyCtor' has a user-declared copy constructor}}
+};
+
+// FIXME: this should eventually trigger on the operator's declaration line
+class CopyAssign { // expected-note 3 {{because type 'class CopyAssign' has a user-declared copy assignment operator}}
+ CopyAssign& operator=(CopyAssign& CA) { abort(); }
+};
+
+class Dtor {
+ ~Dtor() { abort(); } // expected-note 3 {{because type 'class Dtor' has a user-declared destructor}}
+};
+
+union U1 {
+ Virtual v; // expected-error {{union member 'v' has a non-trivial copy constructor}}
+ VirtualBase vbase; // expected-error {{union member 'vbase' has a non-trivial copy constructor}}
+ Ctor ctor; // expected-error {{union member 'ctor' has a non-trivial constructor}}
+ CopyCtor copyctor; // expected-error {{union member 'copyctor' has a non-trivial copy constructor}}
+ CopyAssign copyassign; // expected-error {{union member 'copyassign' has a non-trivial copy assignment operator}}
+ Dtor dtor; // expected-error {{union member 'dtor' has a non-trivial destructor}}
+ Okay okay;
+};
+
+union U2 {
+ struct {
+ Virtual v; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}}
+ } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}}
+ struct {
+ VirtualBase vbase; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}}
+ } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}}
+ struct {
+ Ctor ctor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial constructor}}
+ } m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
+ struct {
+ CopyCtor copyctor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}}
+ } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
+ struct {
+ CopyAssign copyassign; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy assignment operator}}
+ } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}}
+ struct {
+ Dtor dtor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial destructor}}
+ } m6; // expected-error {{union member 'm6' has a non-trivial destructor}}
+ struct {
+ Okay okay;
+ } m7;
+};
+
+union U3 {
+ struct s1 : Virtual { // expected-note {{because type 'struct U3::s1' has a base class with a non-trivial copy constructor}}
+ } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}}
+ struct s2 : VirtualBase { // expected-note {{because type 'struct U3::s2' has a base class with a non-trivial copy constructor}}
+ } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}}
+ struct s3 : Ctor { // expected-note {{because type 'struct U3::s3' has a base class with a non-trivial constructor}}
+ } m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
+ struct s4 : CopyCtor { // expected-note {{because type 'struct U3::s4' has a base class with a non-trivial copy constructor}}
+ } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
+ struct s5 : CopyAssign { // expected-note {{because type 'struct U3::s5' has a base class with a non-trivial copy assignment operator}}
+ } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}}
+ struct s6 : Dtor { // expected-note {{because type 'struct U3::s6' has a base class with a non-trivial destructor}}
+ } m6; // expected-error {{union member 'm6' has a non-trivial destructor}}
+ struct s7 : Okay {
+ } m7;
+};
+
+template <class A, class B> struct Either {
+ bool tag;
+ union {
+ A a;
+ B b;
+ };
+
+ Either(A& a) : tag(true), a(a) {}
+ Either(B& b) : tag(false), b(b) {}
+};
+
+/* FIXME: this should work, but crashes in template code.
+void fred() {
+ Either<int,Virtual> virt(0);
+ Either<int,VirtualBase> vbase(0);
+ Either<int,Ctor> ctor(0);
+ Either<int,CopyCtor> copyctor(0);
+ Either<int,CopyAssign> copyassign(0);
+ Either<int,Dtor> dtor(0);
+ Either<int,Okay> okay(0);
+}
+ */