[cfe-commits] r150721 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/CXX/class/class.union/p1.cpp test/CXX/class/class.union/p2-0x.cpp test/CodeGenCXX/static-data-member.cpp test/SemaCXX/cxx0x-nontrivial-union.cpp test/SemaCXX/cxx98-compat.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Thu Feb 16 12:41:23 PST 2012
Author: rsmith
Date: Thu Feb 16 14:41:22 2012
New Revision: 150721
URL: http://llvm.org/viewvc/llvm-project?rev=150721&view=rev
Log:
C++11 allows unions to have static data members. Remove the corresponding
restriction and add some tests.
Added:
cfe/trunk/test/CXX/class/class.union/p2-0x.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CXX/class/class.union/p1.cpp
cfe/trunk/test/CodeGenCXX/static-data-member.cpp
cfe/trunk/test/SemaCXX/cxx0x-nontrivial-union.cpp
cfe/trunk/test/SemaCXX/cxx98-compat.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=150721&r1=150720&r2=150721&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Feb 16 14:41:22 2012
@@ -973,8 +973,13 @@
"because type %0 has a user-declared %select{constructor|copy constructor|"
"move constructor|copy assignment operator|move 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_static_data_member_not_allowed_in_anon_struct : Error<
+ "static data member %0 not allowed in anonymous struct">;
+def ext_static_data_member_in_union : ExtWarn<
+ "static data member %0 in union is a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_static_data_member_in_union : Warning<
+ "static data member %0 in union is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_union_member_of_reference_type : Error<
"union member %0 has reference type %1">;
def ext_anonymous_struct_union_qualified : Extension<
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=150721&r1=150720&r2=150721&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Feb 16 14:41:22 2012
@@ -3920,20 +3920,24 @@
} else if (SC == SC_None)
SC = SC_Static;
}
- if (SC == SC_Static) {
+ if (SC == SC_Static && CurContext->isRecord()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
if (RD->isLocalClass())
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()))
+ // C++98 [class.union]p1: If a union contains a static data member,
+ // the program is ill-formed. C++11 drops this restriction.
+ if (RD->isUnion())
+ Diag(D.getIdentifierLoc(),
+ getLangOptions().CPlusPlus0x
+ ? diag::warn_cxx98_compat_static_data_member_in_union
+ : diag::ext_static_data_member_in_union) << Name;
+ // We conservatively disallow static data members in anonymous structs.
+ else if (!RD->getDeclName())
Diag(D.getIdentifierLoc(),
- diag::err_static_data_member_not_allowed_in_union_or_anon_struct)
+ diag::err_static_data_member_not_allowed_in_anon_struct)
<< Name << RD->isUnion();
}
}
Modified: cfe/trunk/test/CXX/class/class.union/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.union/p1.cpp?rev=150721&r1=150720&r2=150721&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.union/p1.cpp (original)
+++ cfe/trunk/test/CXX/class/class.union/p1.cpp Thu Feb 16 14:41:22 2012
@@ -91,8 +91,9 @@
};
union U4 {
- static int i1; // expected-error {{static data member 'i1' not allowed in union}}
+ static int i1; // expected-warning {{static data member 'i1' in union is a C++11 extension}}
};
+int U4::i1 = 10;
union U5 {
int& i1; // expected-error {{union member 'i1' has reference type 'int &'}}
Added: cfe/trunk/test/CXX/class/class.union/p2-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.union/p2-0x.cpp?rev=150721&view=auto
==============================================================================
--- cfe/trunk/test/CXX/class/class.union/p2-0x.cpp (added)
+++ cfe/trunk/test/CXX/class/class.union/p2-0x.cpp Thu Feb 16 14:41:22 2012
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s
+
+// Unlike in C++98, C++11 allows unions to have static data members.
+
+union U1 {
+ static constexpr int k1 = 0;
+ static const int k2 = k1;
+ static int k3 = k2; // expected-error {{non-const static data member must be initialized out of line}}
+ static constexpr double k4 = k2;
+ static const double k5 = k4; // expected-warning {{GNU extension}} expected-note {{use 'constexpr'}}
+ int n[k1 + 3];
+};
+
+constexpr int U1::k1;
+constexpr int U1::k2;
+int U1::k3;
+
+const double U1::k4;
+const double U1::k5;
+
+template<typename T>
+union U2 {
+ static const int k1;
+ static double k2;
+ T t;
+};
+template<typename T> constexpr int U2<T>::k1 = sizeof(U2<T>);
+template<typename T> double U2<T>::k2 = 5.3;
+
+static_assert(U2<int>::k1 == sizeof(int), "");
+static_assert(U2<char>::k1 == sizeof(char), "");
+
+union U3 {
+ static const int k;
+ U3() : k(0) {} // expected-error {{does not name a non-static data member}}
+};
Modified: cfe/trunk/test/CodeGenCXX/static-data-member.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-data-member.cpp?rev=150721&r1=150720&r2=150721&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-data-member.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/static-data-member.cpp Thu Feb 16 14:41:22 2012
@@ -5,6 +5,12 @@
// CHECK: @_ZN5test31AIiE1xE = weak_odr global i32 0, align 4
// CHECK: @_ZGVN5test31AIiE1xE = weak_odr global i64 0
+// CHECK: _ZN5test51U2k0E = global i32 0
+// CHECK: _ZN5test51U2k1E = global i32 0
+// CHECK: _ZN5test51U2k2E = constant i32 76
+// CHECK-NOT: test51U2k3E
+// CHECK-NOT: test51U2k4E
+
// PR5564.
namespace test1 {
struct A {
@@ -78,3 +84,21 @@
return a->n;
}
}
+
+// Test that static data members in unions behave properly.
+namespace test5 {
+ union U {
+ static int k0;
+ static const int k1;
+ static const int k2 = 76;
+ static const int k3;
+ static const int k4 = 81;
+ };
+ int U::k0;
+ const int U::k1 = (k0 = 9, 42);
+ const int U::k2;
+
+ // CHECK: store i32 9, i32* @_ZN5test51U2k0E
+ // CHECK: store i32 {{.*}}, i32* @_ZN5test51U2k1E
+ // CHECK-NOT: store {{.*}} i32* @_ZN5test51U2k2E
+}
Modified: cfe/trunk/test/SemaCXX/cxx0x-nontrivial-union.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-nontrivial-union.cpp?rev=150721&r1=150720&r2=150721&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-nontrivial-union.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-nontrivial-union.cpp Thu Feb 16 14:41:22 2012
@@ -11,8 +11,13 @@
non_trivial nt;
};
+union static_data_member {
+ static int i;
+};
+int static_data_member::i;
+
union bad {
- static int i; // expected-error {{static data member}}
+ int &i; // expected-error {{union member 'i' has reference type 'int &'}}
};
struct s {
Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=150721&r1=150720&r2=150721&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Thu Feb 16 14:41:22 2012
@@ -34,8 +34,7 @@
}
void Lambda() {
- // FIXME: Enable when lambdas are minimally working.
- //[]{}; // FIXME-warning {{lambda expressions are incompatible with C++98}}
+ []{}(); // expected-warning {{lambda expressions are incompatible with C++98}}
}
int InitList() {
@@ -239,6 +238,11 @@
NonTrivDtor ntd; // expected-warning {{anonymous struct member 'ntd' with a non-trivial destructor is incompatible with C++98}}
};
};
+ union WithStaticDataMember {
+ static constexpr double d = 0.0; // expected-warning {{static data member 'd' in union is incompatible with C++98}} expected-warning {{'constexpr' specifier is incompatible with C++98}}
+ static const int n = 0; // expected-warning {{static data member 'n' in union is incompatible with C++98}}
+ static int k; // expected-warning {{static data member 'k' in union is incompatible with C++98}}
+ };
}
int EnumNNS = Enum::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}}
More information about the cfe-commits
mailing list