gcc/ChangeLog:

        * cgraphunit.c (process_symver_attribute): Remove checks that
        are not needed now.
        (cgraph_node::assemble_thunks_and_aliases): Change second
        argument to decl.
        * config/elfos.h (ASM_OUTPUT_SYMVER_DIRECTIVE): Add new
        VISIBILITY parameter.
        * doc/extend.texi: Document that .symver supports visibility.
        * symtab.c (symtab_node::verify_base): Remove checks that
        are not needed now.
        * varasm.c (do_assemble_symver): Detect visibility .symver
        directive argument.
        * varpool.c (varpool_node::assemble_aliases): Change second
        argument to decl.

gcc/testsuite/ChangeLog:

        * gcc.dg/ipa/symver2.c: New test.
        * gcc.dg/ipa/symver3.c: New test.
---
 gcc/cgraphunit.c                   | 15 +--------------
 gcc/config/elfos.h                 | 20 +++++++++++---------
 gcc/doc/extend.texi                |  3 +--
 gcc/symtab.c                       | 16 ----------------
 gcc/testsuite/gcc.dg/ipa/symver2.c |  9 +++++++++
 gcc/testsuite/gcc.dg/ipa/symver3.c | 13 +++++++++++++
 gcc/varasm.c                       | 12 ++++++++++--
 gcc/varpool.c                      |  3 +--
 8 files changed, 46 insertions(+), 45 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/ipa/symver2.c
 create mode 100644 gcc/testsuite/gcc.dg/ipa/symver3.c

diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index fa3aec79a48..c85d3482c8b 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -765,18 +765,6 @@ process_symver_attribute (symtab_node *n)
 		    "%<weakref%> cannot be versioned");
 	  return;
 	}
-      if (!TREE_PUBLIC (n->decl))
-	{
-	  error_at (DECL_SOURCE_LOCATION (n->decl),
-		    "versioned symbol must be public");
-	  return;
-	}
-      if (DECL_VISIBILITY (n->decl) != VISIBILITY_DEFAULT)
-	{
-	  error_at (DECL_SOURCE_LOCATION (n->decl),
-		    "versioned symbol must have default visibility");
-	  return;
-	}
 
       /* Create new symbol table entry representing the version.  */
       tree new_decl = copy_node (n->decl);
@@ -2239,8 +2227,7 @@ cgraph_node::assemble_thunks_and_aliases (void)
 	     of buffering it in same alias pairs.  */
 	  TREE_ASM_WRITTEN (decl) = 1;
 	  if (alias->symver)
-	    do_assemble_symver (alias->decl,
-				DECL_ASSEMBLER_NAME (decl));
+	    do_assemble_symver (alias->decl, decl);
 	  else
 	    do_assemble_alias (alias->decl,
 			       DECL_ASSEMBLER_NAME (decl));
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index 74a3eafda6b..6c9b73320b9 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -248,15 +248,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     }					\
   while (0)
 
-#define ASM_OUTPUT_SYMVER_DIRECTIVE(FILE, NAME, NAME2)		\
-  do								\
-    {								\
-      fputs ("\t.symver\t", (FILE));				\
-      assemble_name ((FILE), (NAME));				\
-      fputs (", ", (FILE));					\
-      assemble_name ((FILE), (NAME2));				\
-      fputc ('\n', (FILE));					\
-    }								\
+#define ASM_OUTPUT_SYMVER_DIRECTIVE(FILE, NAME, NAME2, VISIBILITY)  \
+  do								    \
+    {								    \
+      fputs ("\t.symver\t", (FILE));				    \
+      assemble_name ((FILE), (NAME));				    \
+      fputs (", ", (FILE));					    \
+      assemble_name ((FILE), (NAME2));				    \
+      if (visibility != NULL)					    \
+	fprintf ((FILE), ", %s", (VISIBILITY));			    \
+      fputc ('\n', (FILE));					    \
+    }								    \
   while (0)
 
 /* The following macro defines the format used to output the second
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 97ae1ee0843..22e62f36714 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3729,8 +3729,7 @@ On ELF targets this attribute creates a symbol version.  The @var{name2} part
 of the parameter is the actual name of the symbol by which it will be
 externally referenced.  The @code{nodename} portion should be the name of a
 node specified in the version script supplied to the linker when building a
-shared library.  Versioned symbol must be defined and must be exported with
-default visibility.
+shared library.
 
 @smallexample
 __attribute__ ((__symver__ ("foo@@VERS_1"))) int
diff --git a/gcc/symtab.c b/gcc/symtab.c
index d7dfbb676df..51628fe625f 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -1178,22 +1178,6 @@ symtab_node::verify_base (void)
       error ("node is symver but not alias");
       error_found = true;
     }
-  /* Limitation of gas requires us to output targets of symver aliases as
-     global symbols.  This is binutils PR 25295.  */
-  if (symver
-      && (!TREE_PUBLIC (get_alias_target ()->decl)
-	  || DECL_VISIBILITY (get_alias_target ()->decl) != VISIBILITY_DEFAULT))
-    {
-      error ("symver target is not exported with default visibility");
-      error_found = true;
-    }
-  if (symver
-      && (!TREE_PUBLIC (decl)
-	  || DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT))
-    {
-      error ("symver is not exported with default visibility");
-      error_found = true;
-    }
   if (same_comdat_group)
     {
       symtab_node *n = same_comdat_group;
diff --git a/gcc/testsuite/gcc.dg/ipa/symver2.c b/gcc/testsuite/gcc.dg/ipa/symver2.c
new file mode 100644
index 00000000000..9cb50a54e08
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/symver2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+__attribute__ ((__symver__ ("foo@VER_2")))
+static int foo()
+{
+  return 2;
+}
+
+/* { dg-final { scan-assembler ".symver.*foo, foo@VER_2, remove" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/symver3.c b/gcc/testsuite/gcc.dg/ipa/symver3.c
new file mode 100644
index 00000000000..fb30503d808
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/symver3.c
@@ -0,0 +1,13 @@
+/* { dg-do link } */
+/* { dg-require-symver "" } */
+
+__attribute__ ((__symver__ ("foo@VERS_2")))
+int foo()
+{
+  return 2;
+}
+
+int main()
+{
+  return foo() - 2;
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 84df52013d7..9a0f12e17f3 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -5964,15 +5964,23 @@ do_assemble_alias (tree decl, tree target)
 /* Output .symver directive.  */
 
 void
-do_assemble_symver (tree decl, tree target)
+do_assemble_symver (tree decl, tree origin_decl)
 {
+  tree target = DECL_ASSEMBLER_NAME (origin_decl);
   tree id = DECL_ASSEMBLER_NAME (decl);
   ultimate_transparent_alias_target (&id);
   ultimate_transparent_alias_target (&target);
 #ifdef ASM_OUTPUT_SYMVER_DIRECTIVE
+  const char *visibility = NULL;
+  if (!TREE_PUBLIC (origin_decl))
+    visibility = "remove";
+  else if (DECL_VISIBILITY (origin_decl) == VISIBILITY_INTERNAL)
+    visibility = "local";
+  else if (DECL_VISIBILITY (origin_decl) == VISIBILITY_HIDDEN)
+    visibility = "hidden";
   ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file,
 			       IDENTIFIER_POINTER (target),
-			       IDENTIFIER_POINTER (id));
+			       IDENTIFIER_POINTER (id), visibility);
 #else
   error ("symver is only supported on ELF platforms");
 #endif
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 458cdf1bf37..95d7844a398 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -540,8 +540,7 @@ varpool_node::assemble_aliases (void)
     {
       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
       if (alias->symver)
-	do_assemble_symver (alias->decl,
-			    DECL_ASSEMBLER_NAME (decl));
+	do_assemble_symver (alias->decl, decl);
       else if (!alias->transparent_alias)
 	do_assemble_alias (alias->decl,
 			   DECL_ASSEMBLER_NAME (decl));

Reply via email to