PR c++/47877 - -fvisibility-inlines-hidden and member templates.
authorJason Merrill <jason@redhat.com>
Tue, 7 Jan 2020 15:05:25 +0000 (10:05 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 7 Jan 2020 15:05:25 +0000 (10:05 -0500)
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.

* decl2.c (determine_visibility): -fvisibility-inlines-hidden beats
explicit class visibility for a template.

From-SVN: r279960

gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-5.C [new file with mode: 0644]
gcc/tree.h

index a82b6cf..a7234b8 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-07  Jason Merrill  <jason@redhat.com>
+
+       PR c++/47877 - -fvisibility-inlines-hidden and member templates.
+       * decl2.c (determine_visibility): -fvisibility-inlines-hidden beats
+       explicit class visibility for a template.
+
 2020-01-07  Richard Sandiford  <richard.sandiford@arm.com>
 
        * mangle.c (mangle_type_attribute_p): New function, split out from...
index 9fb1d81..a641667 100644 (file)
@@ -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 (file)
index 0000000..2937f35
--- /dev/null
@@ -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>();
+}
index a6e4e9e..9ca9ab5 100644 (file)
@@ -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)