A union cannot contain static data members or data members of reference type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118381 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 8071daa..3fc525e 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -341,7 +341,7 @@
/// \brief Whether we have already declared a destructor within the class.
bool DeclaredDestructor : 1;
-
+
/// NumBases - The number of base class specifiers in Bases.
unsigned NumBases;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 33b8660..a5b0aa5 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -674,6 +674,10 @@
def note_nontrivial_user_defined : Note<
"because type %0 has a user-declared %select{constructor|copy constructor|"
"copy assignment operator|destructor}1">;
+def err_static_data_member_not_allowed_in_union_or_anon_struct : Error<
+ "static data member %0 not allowed in %select{anonymous struct|union}1">;
+def err_union_member_of_reference_type : Error<
+ "union member %0 has reference type %1">;
def err_different_return_type_for_overriding_virtual_function : Error<
"virtual function %0 has a different return type (%1) than the "
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 10a23ec..c246cad 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2788,6 +2788,15 @@
Diag(D.getIdentifierLoc(),
diag::err_static_data_member_not_allowed_in_local_class)
<< Name << RD->getDeclName();
+
+ // C++ [class.union]p1: If a union contains a static data member,
+ // the program is ill-formed.
+ //
+ // We also disallow static data members in anonymous structs.
+ if (CurContext->isRecord() && (RD->isUnion() || !RD->getDeclName()))
+ Diag(D.getIdentifierLoc(),
+ diag::err_static_data_member_not_allowed_in_union_or_anon_struct)
+ << Name << RD->isUnion();
}
}
@@ -6444,17 +6453,27 @@
}
if (!InvalidDecl && getLangOptions().CPlusPlus) {
- if (const RecordType *RT = EltTy->getAs<RecordType>()) {
- CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (RDecl->getDefinition()) {
- // C++ 9.5p1: An object of a class with a non-trivial
- // constructor, a non-trivial copy constructor, a non-trivial
- // destructor, or a non-trivial copy assignment operator
- // cannot be a member of a union, nor can an array of such
- // objects.
- // TODO: C++0x alters this restriction significantly.
- if (Record->isUnion() && CheckNontrivialField(NewFD))
- NewFD->setInvalidDecl();
+ if (Record->isUnion()) {
+ if (const RecordType *RT = EltTy->getAs<RecordType>()) {
+ CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (RDecl->getDefinition()) {
+ // C++ [class.union]p1: An object of a class with a non-trivial
+ // constructor, a non-trivial copy constructor, a non-trivial
+ // destructor, or a non-trivial copy assignment operator
+ // cannot be a member of a union, nor can an array of such
+ // objects.
+ // TODO: C++0x alters this restriction significantly.
+ if (CheckNontrivialField(NewFD))
+ NewFD->setInvalidDecl();
+ }
+ }
+
+ // C++ [class.union]p1: If a union contains a member of reference type,
+ // the program is ill-formed.
+ if (EltTy->isReferenceType()) {
+ Diag(NewFD->getLocation(), diag::err_union_member_of_reference_type)
+ << NewFD->getDeclName() << EltTy;
+ NewFD->setInvalidDecl();
}
}
}
diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp
index e974d82..b5dd4df 100644
--- a/test/CXX/class/class.union/p1.cpp
+++ b/test/CXX/class/class.union/p1.cpp
@@ -90,6 +90,14 @@
} m7;
};
+union U4 {
+ static int i1; // expected-error {{static data member 'i1' not allowed in union}}
+};
+
+union U5 {
+ int& i1; // expected-error {{union member 'i1' has reference type 'int &'}}
+};
+
template <class A, class B> struct Either {
bool tag;
union {
diff --git a/test/SemaCXX/member-expr-anonymous-union.cpp b/test/SemaCXX/member-expr-anonymous-union.cpp
index 0f03596..6e35eb2 100644
--- a/test/SemaCXX/member-expr-anonymous-union.cpp
+++ b/test/SemaCXX/member-expr-anonymous-union.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify
// PR5543
-struct A { int x; union { int* y; float& z; }; }; struct B : A {int a;};
+struct A { int x; union { int* y; float* z; }; }; struct B : A {int a;};
int* a(B* x) { return x->y; }
struct x { union { int y; }; }; x y; template <int X> int f() { return X+y.y; }