This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/55877 (wrong linkage for nested classes)


When an anonymous class gets a linkage name from a typedef, we recalculate its visibility; anonymous types have internal linkage, but types with linkage names have external linkage and therefore can have visibility. But we were forgetting to also recalculate the visibility of any nested types, which were also affected by the former anonymity of the enclosing class.

Tested x86_64-pc-linux-gnu, applying to trunk, 4.7, 4.6.
commit 28beb0d493a46f126f23d15216d4ae9279223514
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jan 4 10:50:46 2013 -0500

    	PR c++/55877
    	* decl.c (reset_type_linkage, bt_reset_linkage): New.
    	(grokdeclarator): Use reset_type_linkage.
    	* name-lookup.c (binding_table_foreach): Handle null table.
    	* tree.c (decl_anon_ns_mem_p): Check TYPE_MAIN_DECL, not TYPE_NAME.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5c268b1..9640824 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8513,6 +8513,23 @@ check_var_type (tree identifier, tree type)
   return type;
 }
 
+/* Functions for adjusting the visibility of a tagged type and its nested
+   types when it gets a name for linkage purposes from a typedef.  */
+
+static void bt_reset_linkage (binding_entry, void *);
+static void
+reset_type_linkage (tree type)
+{
+  set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
+  if (CLASS_TYPE_P (type))
+    binding_table_foreach (CLASSTYPE_NESTED_UTDS (type), bt_reset_linkage, NULL);
+}
+static void
+bt_reset_linkage (binding_entry b, void */*data*/)
+{
+  reset_type_linkage (b->type);
+}
+
 /* Given declspecs and a declarator (abstract or otherwise), determine
    the name and type of the object declared and construct a DECL node
    for it.
@@ -10053,8 +10070,7 @@ grokdeclarator (const cp_declarator *declarator,
 	      = TYPE_IDENTIFIER (type);
 
 	  /* Adjust linkage now that we aren't anonymous anymore.  */
-	  set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
-	  determine_visibility (TYPE_MAIN_DECL (type));
+	  reset_type_linkage (type);
 
 	  /* FIXME remangle member functions; member functions of a
 	     type with external linkage have external linkage.  */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 87b1f51..754e830 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -251,9 +251,13 @@ binding_table_find (binding_table table, tree name)
 void
 binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data)
 {
-  const size_t chain_count = table->chain_count;
+  size_t chain_count;
   size_t i;
 
+  if (!table)
+    return;
+
+  chain_count = table->chain_count;
   for (i = 0; i < chain_count; ++i)
     {
       binding_entry entry = table->chain[i];
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c658582..fcab1a4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2404,7 +2404,7 @@ decl_anon_ns_mem_p (const_tree decl)
       /* Classes and namespaces inside anonymous namespaces have
          TREE_PUBLIC == 0, so we can shortcut the search.  */
       else if (TYPE_P (decl))
-	return (TREE_PUBLIC (TYPE_NAME (decl)) == 0);
+	return (TREE_PUBLIC (TYPE_MAIN_DECL (decl)) == 0);
       else if (TREE_CODE (decl) == NAMESPACE_DECL)
 	return (TREE_PUBLIC (decl) == 0);
       else
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon11.C b/gcc/testsuite/g++.dg/ext/visibility/anon11.C
new file mode 100644
index 0000000..dfb4f12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon11.C
@@ -0,0 +1,13 @@
+// PR c++/55877
+// { dg-final { scan-assembler-not "\\.local" } }
+
+typedef struct {
+  typedef enum { X, Y } A;
+  typedef struct { } B;
+  struct C { };
+} D;
+
+D d;
+D::A a;
+D::B b;
+D::C c;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]