diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 13f34845818a378bc3a6bd9e70ac529385604058..11d458a364461054c911f97b8f19cd601f02b8de 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2012-01-23  Jason Merrill  <jason@redhat.com>
+
+	PR c++/51930
+	* decl2.c (determine_visibility): Check for visibility attribute
+	on template specialization.
+
 2012-01-23  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/51398
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f51790c551d12f37538c090c227f5ce711d2df2b..bdc962abcf9be6b77e69201a9a1409a5f4a96ccd 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2177,8 +2177,14 @@ determine_visibility (tree decl)
 		    ? TYPE_TEMPLATE_INFO (TREE_TYPE (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/ChangeLog b/gcc/testsuite/ChangeLog
index 0f1e4bf2bb8832351e323ad156b813ce2822f2ce..43794d3e5eba10209ce9727d63a289885b6f33d8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-01-23  Jason Merrill  <jason@redhat.com>
+
+	PR c++/51930
+	* g++.dg/ext/visibility/template10.C: New.
+
 2012-01-23  Tobias Burnus  <burnus@net-b.de>
 
 	PR fortran/51948
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 0000000000000000000000000000000000000000..01108aa7f4244c3b8ee8c242c82b76e4fa9510ae
--- /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() { }
+
+template
+__attribute__ ((visibility("default")))
+void testfunc<foo>();