[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