diff mbox series

[C++] PR c++/47877 - -fvisibility-inlines-hidden and member templates.

Message ID 20200107150515.27751-1-jason@redhat.com
State New
Headers show
Series [C++] PR c++/47877 - -fvisibility-inlines-hidden and member templates. | expand

Commit Message

Jason Merrill Jan. 7, 2020, 3:05 p.m. UTC
DECL_VISIBILITY_SPECIFIED is also true if an enclosing scope has explicit
visibility, and we don't want that to override -fvisibility-inlines-hidden.
So check for the attribute specifically on the function, like we already do
for template argument visibility restriction.

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

	* decl2.c (determine_visibility): -fvisibility-inlines-hidden beats
	explicit class visibility for a template.
---
 gcc/tree.h                                          |  4 ++--
 gcc/cp/decl2.c                                      |  5 +++--
 .../ext/visibility/fvisibility-inlines-hidden-5.C   | 13 +++++++++++++
 3 files changed, 18 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-5.C


base-commit: 31bfdb85acb36bfdae772c7fa253abb6d6e8c4ca
diff mbox series

Patch

diff --git a/gcc/tree.h b/gcc/tree.h
index a6e4e9e6b8c..9ca9ab58ec0 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2903,8 +2903,8 @@  extern void decl_value_expr_insert (tree, tree);
 #define DECL_VISIBILITY(NODE) \
   (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.visibility)
 
-/* Nonzero means that the decl had its visibility specified rather than
-   being inferred.  */
+/* Nonzero means that the decl (or an enclosing scope) had its
+   visibility specified rather than being inferred.  */
 #define DECL_VISIBILITY_SPECIFIED(NODE) \
   (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.visibility_specified)
 
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 9fb1d81a881..a641667991f 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2629,6 +2629,7 @@  determine_visibility (tree decl)
       tree attribs = (TREE_CODE (decl) == TYPE_DECL
 		      ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
 		      : DECL_ATTRIBUTES (decl));
+      tree attr = lookup_attribute ("visibility", attribs);
       
       if (args != error_mark_node)
 	{
@@ -2636,7 +2637,7 @@  determine_visibility (tree decl)
 
 	  if (!DECL_VISIBILITY_SPECIFIED (decl))
 	    {
-	      if (!DECL_VISIBILITY_SPECIFIED (pattern)
+	      if (!attr
 		  && determine_hidden_inline (decl))
 		DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
 	      else
@@ -2650,7 +2651,7 @@  determine_visibility (tree decl)
 	  if (args
 	      /* Template argument visibility outweighs #pragma or namespace
 		 visibility, but not an explicit attribute.  */
-	      && !lookup_attribute ("visibility", attribs))
+	      && !attr)
 	    {
 	      int depth = TMPL_ARGS_DEPTH (args);
 	      if (DECL_VISIBILITY_SPECIFIED (decl))
diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-5.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-5.C
new file mode 100644
index 00000000000..2937f35d9a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-5.C
@@ -0,0 +1,13 @@ 
+// PR c++/47877
+// { dg-options "-fvisibility-inlines-hidden" }
+// { dg-require-visibility "" }
+// { dg-final { scan-hidden "_ZN3Foo3barIS_EEvv" } }
+
+struct __attribute__((visibility("default"))) Foo {
+  template <class C> inline void bar() {};
+};
+
+int main()
+{
+  Foo().bar<Foo>();
+}