Hi,
sorry I forgot to include cgraph and varpool changes in the patch.

Index: varpool.c
===================================================================
--- varpool.c   (revision 279467)
+++ varpool.c   (working copy)
@@ -539,8 +539,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));
Index: cgraphunit.c
===================================================================
--- cgraphunit.c        (revision 279467)
+++ cgraphunit.c        (working copy)
@@ -2222,8 +2222,7 @@ cgraph_node::assemble_thunks_and_aliases
             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));
Index: varasm.c
===================================================================
--- varasm.c    (revision 279467)
+++ varasm.c    (working copy)
@@ -5970,9 +5970,47 @@ do_assemble_symver (tree decl, tree targ
   ultimate_transparent_alias_target (&id);
   ultimate_transparent_alias_target (&target);
 #ifdef ASM_OUTPUT_SYMVER_DIRECTIVE
-  ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file,
-                              IDENTIFIER_POINTER (target),
-                              IDENTIFIER_POINTER (id));
+  if (TREE_PUBLIC (target) && DECL_VISIBILITY (target) == VISIBILITY_DEFAULT)
+    ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file,
+                                IDENTIFIER_POINTER
+                                  (DECL_ASSEMBLER_NAME (target)),
+                                IDENTIFIER_POINTER (id));
+  else
+    {
+      int nameend;
+      for (nameend = 0; IDENTIFIER_POINTER (id)[nameend] != '@'; nameend++)
+       ;
+      if (IDENTIFIER_POINTER (id)[nameend + 1] != '@'
+         || IDENTIFIER_POINTER (id)[nameend + 2] == '@')
+       {
+         sorry_at (DECL_SOURCE_LOCATION (target),
+                   "can not produce %<symver%> of a symbol that is "
+                   "not exported with default visibility");
+         return;
+       }
+      tree tmpdecl = copy_node (decl);
+      char buf[256];
+      static int symver_labelno;
+      targetm.asm_out.generate_internal_label (buf,
+                                              "LSYMVER", symver_labelno++);
+      SET_DECL_ASSEMBLER_NAME (tmpdecl, get_identifier (buf));
+      globalize_decl (tmpdecl);
+#ifdef ASM_OUTPUT_DEF_FROM_DECLS
+      ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, tmpdecl,
+                                DECL_ASSEMBLER_NAME (target));
+#else
+      ASM_OUTPUT_DEF (asm_out_file,
+                     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tmpdecl)),
+                     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target)));
+#endif
+      memcpy (buf, IDENTIFIER_POINTER (id), nameend + 2);
+      buf[nameend + 2] = '@';
+      strcpy (buf + nameend + 3, IDENTIFIER_POINTER (id) + nameend + 2);
+      ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file,
+                                  IDENTIFIER_POINTER
+                                        (DECL_ASSEMBLER_NAME (tmpdecl)),
+                                  buf);
+    }
 #else
   error ("symver is only supported on ELF platforms");
 #endif
Index: lto/lto-common.c
===================================================================
--- lto/lto-common.c    (revision 279467)
+++ lto/lto-common.c    (working copy)
@@ -2818,6 +2818,10 @@ read_cgraph_and_symbols (unsigned nfiles
                           IDENTIFIER_POINTER
                             (DECL_ASSEMBLER_NAME (snode->decl)));
          }
+       /* Symbol versions are always used externally, but linker does not
+          report that correctly.  */
+       else if (snode->symver && *res == LDPR_PREVAILING_DEF_IRONLY)
+         snode->resolution = LDPR_PREVAILING_DEF_IRONLY_EXP;
        else
          snode->resolution = *res;
       }

Reply via email to