We were wrongly considering two classes in anonymous namespaces in different files to be the same class due to string comparison. We have a way to avoid that, by putting a '*' at the beginning of the typeinfo name, but weren't doing that in this case because TREE_PUBLIC was wrongly set on the typeinfo by set_linkage_according_to_type. Rather than try to fix that function, we should just use determine_visibility, which already gets this stuff right.

While looking at this, I also noticed that we were adopting a tentative alias as first_global_object_name because its linkage flags hadn't been set properly yet.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 5576725d9e58e9201695756f6cd228199e3ea724
Author: Jason Merrill <ja...@redhat.com>
Date:   Wed Jun 22 23:39:42 2011 -0400

    	PR c++/49440
    	* class.c (set_linkage_according_to_type): Just check TREE_PUBLIC
    	on the type's name.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 09444fb..9e387a6 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -677,21 +677,10 @@ get_vtable_name (tree type)
    the abstract.  */
 
 void
-set_linkage_according_to_type (tree type, tree decl)
+set_linkage_according_to_type (tree type ATTRIBUTE_UNUSED, tree decl)
 {
-  /* If TYPE involves a local class in a function with internal
-     linkage, then DECL should have internal linkage too.  Other local
-     classes have no linkage -- but if their containing functions
-     have external linkage, it makes sense for DECL to have external
-     linkage too.  That will allow template definitions to be merged,
-     for example.  */
-  if (no_linkage_check (type, /*relaxed_p=*/true))
-    {
-      TREE_PUBLIC (decl) = 0;
-      DECL_INTERFACE_KNOWN (decl) = 1;
-    }
-  else
-    TREE_PUBLIC (decl) = 1;
+  TREE_PUBLIC (decl) = 1;
+  determine_visibility (decl);
 }
 
 /* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
diff --git a/gcc/testsuite/g++.dg/rtti/anon-ns1.C b/gcc/testsuite/g++.dg/rtti/anon-ns1.C
new file mode 100644
index 0000000..fd6f8af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/rtti/anon-ns1.C
@@ -0,0 +1,15 @@
+// PR c++/49440
+// The typeinfo name for A should start with * so we compare
+// it by address rather than contents.
+
+// { dg-final { scan-assembler "\"\*N\[^\"\]+1AE\"" } }
+
+namespace
+{
+  class A { };
+}
+
+void f()
+{
+  throw A();
+}

commit d567cac789228a15f7ce98350e19a7b4c52429ab
Author: Jason Merrill <ja...@redhat.com>
Date:   Wed Jun 22 23:40:07 2011 -0400

    	* optimize.c (maybe_clone_body): Set linkage flags before
    	cgraph_same_body_alias.

diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 87302dc..b9e3551 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -310,8 +310,11 @@ maybe_clone_body (tree fn)
 	      || (HAVE_COMDAT_GROUP
 		  && DECL_WEAK (fns[0])))
 	  && (flag_syntax_only
-	      || cgraph_same_body_alias (cgraph_get_node (fns[0]), clone,
-					 fns[0])))
+	      /* Set linkage flags appropriately before
+		 cgraph_create_function_alias looks at them.  */
+	      || (expand_or_defer_fn_1 (clone)
+		  && cgraph_same_body_alias (cgraph_get_node (fns[0]),
+					     clone, fns[0]))))
 	{
 	  alias = true;
 	  if (DECL_ONE_ONLY (fns[0]))

Reply via email to