diff mbox

C++ PATCH for c++/55877 (names for linkage purposes)

Message ID 530D07F0.3050205@redhat.com
State New
Headers show

Commit Message

Jason Merrill Feb. 25, 2014, 9:15 p.m. UTC
My earlier patch didn't go far enough; when we apply a name for linkage 
purposes and fix up the visibility of the type, we also need to fix up 
the visibility and names of any members and implementation bits.

At first I thought we would need to deal with static data members as 
well as functions, but it turns out that an unnamed class can't have 
static data members.  So the second patch enforces that better.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 8bf3ffa515e08c9fb815e6663c16acd39af9056a
Author: Jason Merrill <jason@redhat.com>
Date:   Sun Feb 9 19:31:28 2014 -0500

    	* decl2.c (finish_static_data_member_decl): Diagnose static data
    	member in unnamed class.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index e861e4d..f61dc9d 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2851,7 +2851,9 @@  finish_struct_anon_r (tree field, bool complain)
 
       if (TREE_CODE (elt) != FIELD_DECL)
 	{
-	  if (complain)
+	  /* We already complained about static data members in
+	     finish_static_data_member_decl.  */
+	  if (complain && TREE_CODE (elt) != VAR_DECL)
 	    {
 	      if (is_union)
 		permerror (input_location,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 35707a0..f512541 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -802,6 +802,17 @@  finish_static_data_member_decl (tree decl,
       && !DECL_TEMPLATE_INSTANTIATION (decl))
     permerror (input_location, "local class %q#T shall not have static data member %q#D",
 	       current_class_type, decl);
+  else
+    for (tree t = current_class_type; TYPE_P (t);
+	 t = CP_TYPE_CONTEXT (t))
+      if (TYPE_ANONYMOUS_P (t))
+	{
+	  if (permerror (DECL_SOURCE_LOCATION (decl),
+			 "static data member %qD in unnamed class", decl))
+	    inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)),
+		    "unnamed class defined here");
+	  break;
+	}
 
   DECL_IN_AGGR_P (decl) = 1;
 
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct5.C b/gcc/testsuite/g++.dg/ext/anon-struct5.C
index 8b697cc..ec02225 100644
--- a/gcc/testsuite/g++.dg/ext/anon-struct5.C
+++ b/gcc/testsuite/g++.dg/ext/anon-struct5.C
@@ -2,12 +2,12 @@ 
 
 struct A
 {
-  struct { static int i; }; // { dg-error "prohibits anonymous structs|an anonymous struct" }
+  struct { static int i; }; // { dg-error "prohibits anonymous structs|an anonymous struct|unnamed class" }
   void foo() { i; }
 };
 
 struct B
 {
-  union { static int i; }; // { dg-error "an anonymous union|member of a union" }
+  union { static int i; }; // { dg-error "an anonymous union|member of a union|unnamed class" }
   void foo() { i; }
 };
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct6.C b/gcc/testsuite/g++.dg/ext/anon-struct6.C
index 11a7bbd..66d4b32 100644
--- a/gcc/testsuite/g++.dg/ext/anon-struct6.C
+++ b/gcc/testsuite/g++.dg/ext/anon-struct6.C
@@ -4,7 +4,7 @@  struct A
 {
   struct
   {  // { dg-error "anonymous struct cannot have function members" }
-    struct { static int i; }; // { dg-error "prohibits anonymous structs|non-static data members" } 
+    struct { static int i; }; // { dg-error "prohibits anonymous structs|non-static data members|unnamed class" }
     void foo() { i; }
   }; // { dg-error "prohibits anonymous structs" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/unnamed1.C b/gcc/testsuite/g++.dg/parse/unnamed1.C
new file mode 100644
index 0000000..f5972f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/unnamed1.C
@@ -0,0 +1,6 @@ 
+// 9.4.2/4: Unnamed classes and classes contained directly or indirectly
+// within unnamed classes shall not contain static data members.
+
+typedef struct {		// { dg-message "unnamed" }
+  static int i;			// { dg-error "static data member" }
+} A;