Patchwork C++ PATCH for c++/51813 (visibility of template instantiation)

login
register
mail settings
Submitter Jason Merrill
Date Jan. 13, 2012, 5:50 p.m.
Message ID <4F106ED1.7010505@redhat.com>
Download mbox | patch
Permalink /patch/135944/
State New
Headers show

Comments

Jason Merrill - Jan. 13, 2012, 5:50 p.m.
For PR 35688 I fixed the compiler to reduce the visibility of a template 
instantiation based on the visibility of its template arguments.  As a 
result of this, we seem to have started marking some external symbols as 
.hidden because:

1) One of the template arguments is hidden, so the instantiation is as well.
2) The template has DECL_VISIBILITY_SPECIFIED because it is inside a 
namespace with a visibility attribute.
3) default_binds_local_p_1 decides that a decl with explicit non-default 
visibility binds locally, so it gets a .hidden directive.

The issue here is that there is no explicit non-default visibility, so 
we should clear DECL_VISIBILITY_SPECIFIED when reducing the visibility 
of a declaration.

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

Patch

commit 5b39abcbdeb088fe7c19c7ff1a280ca4f7876366
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jan 13 12:39:40 2012 -0500

    	PR c++/51813
    	* decl2.c (constrain_visibility): Clear DECL_VISIBILITY_SPECIFIED
    	when reducing the visibility.

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 05f4b42..0cde6c6 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1984,6 +1984,8 @@  constrain_visibility (tree decl, int visibility, bool tmpl)
 	   && (tmpl || !DECL_VISIBILITY_SPECIFIED (decl)))
     {
       DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
+      /* This visibility was not specified.  */
+      DECL_VISIBILITY_SPECIFIED (decl) = false;
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template9.C b/gcc/testsuite/g++.dg/ext/visibility/template9.C
new file mode 100644
index 0000000..d160846
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/template9.C
@@ -0,0 +1,14 @@ 
+// PR c++/51813
+// { dg-options -fvisibility=hidden }
+// { dg-final { scan-assembler-not "hidden\\s+_ZN1N1fI1AEEvT" } }
+
+struct A { };
+namespace N __attribute((visibility("default"))) {
+  template <class T> void f(T) { }
+  extern template void f(A);
+}
+
+int main()
+{
+  N::f(A());
+}