C++ PATCH for c++/51930 (instantiation hidden despite visibility attribute)

Message ID 4F1DC0EC.6040609@redhat.com
State New
Headers show

Commit Message

Jason Merrill Jan. 23, 2012, 8:19 p.m.
DECL_VISIBILITY_SPECIFIED is set if the decl occurs after a #pragma 
visibility or within a namespace with explicit visibility.  In these 
cases, we want the visibility of template arguments to be able to 
further restrict the visibility of template specializations.  But if the 
specialization itself has explicitly specified visibility, we should 
respect that.

This patch will also mean that an attribute on the template will 
override argument visibility, which I could go either way on.  But if 
this is a problem for users they can use a pragma instead.

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


Jason Merrill March 5, 2012, 6:05 p.m. | #1
While looking at the class variant of this issue, I noticed that some of 
the code in determine_visibility was wrong; template_class_depth only 
considers unbound template parameters, and the number we want is the 
total number of levels.  I've also adjusted the diagnostic for misplaced 
class attributes as manu requested.

Tested x86_64-pc-linux-pc, applying to trunk.


commit e3f4b4e6d7c54ec96c77aa3e36fe9d38b7922391
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jan 23 14:31:23 2012 -0500

    	PR c++/51930
    	* decl2.c (determine_visibility): Check for visibility attribute
    	on template specialization.

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f51790c..bdc962a 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2177,8 +2177,14 @@  determine_visibility (tree decl)
 		    : DECL_TEMPLATE_INFO (decl));
       tree args = TI_ARGS (tinfo);
+      tree attribs = (TREE_CODE (decl) == TYPE_DECL
+		      ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
+		      : DECL_ATTRIBUTES (decl));
-      if (args != error_mark_node)
+      if (args != error_mark_node
+	  /* Template argument visibility outweighs #pragma or namespace
+	     visibility, but not an explicit attribute.  */
+	  && !lookup_attribute ("visibility", attribs))
 	  int depth = TMPL_ARGS_DEPTH (args);
 	  tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template10.C b/gcc/testsuite/g++.dg/ext/visibility/template10.C
new file mode 100644
index 0000000..01108aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/template10.C
@@ -0,0 +1,16 @@ 
+// PR c++/51930
+// { dg-require-visibility }
+// { dg-options -fvisibility=hidden }
+// { dg-final { scan-not-hidden "_Z8testfuncI3fooEvv" } }
+struct foo { };
+template<typename T>
+__attribute__ ((visibility("default")))
+void testfunc();
+template<typename T> void testfunc() { }
+__attribute__ ((visibility("default")))
+void testfunc<foo>();