Index: gcc/collect2.c
===================================================================
--- gcc/collect2.c	(revision 183674)
+++ gcc/collect2.c	(working copy)
@@ -403,13 +403,13 @@ collect_exit (int status)
 
   if (ldout != 0 && ldout[0])
     {
-      dump_file (ldout, stdout);
+      dump_file (ldout, stdout, DEMANGLE_IN_LD);
       maybe_unlink (ldout);
     }
 
   if (lderrout != 0 && lderrout[0])
     {
-      dump_file (lderrout, stderr);
+      dump_file (lderrout, stderr, DEMANGLE_IN_LD);
       maybe_unlink (lderrout);
     }
 
@@ -515,7 +515,7 @@ extract_string (const char **pp)
 }
 
 void
-dump_file (const char *name, FILE *to)
+dump_file (const char *name, FILE *to, int demangle_in_ld)
 {
   FILE *stream = fopen (name, "r");
 
@@ -540,14 +540,10 @@ dump_file (const char *name, FILE *to)
 	  if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
 	    p += strlen (USER_LABEL_PREFIX);
 
-#ifdef HAVE_LD_DEMANGLE
-	  result = 0;
-#else
-	  if (no_demangle)
+	  if (no_demangle || demangle_in_ld)
 	    result = 0;
 	  else
 	    result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
-#endif
 
 	  if (result)
 	    {
@@ -1114,9 +1110,8 @@ main (int argc, char **argv)
 
   num_c_args = argc + 9;
 
-#ifndef HAVE_LD_DEMANGLE
   no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
-
+#ifndef HAVE_LD_DEMANGLE
   /* Suppress demangling by the real linker, which may be broken.  */
   putenv (xstrdup ("COLLECT_NO_DEMANGLE=1"));
 #endif
@@ -1566,15 +1561,14 @@ main (int argc, char **argv)
 	    case '-':
 	      if (strcmp (arg, "--no-demangle") == 0)
 		{
-#ifndef HAVE_LD_DEMANGLE
 		  no_demangle = 1;
+#ifndef HAVE_LD_DEMANGLE
 		  ld1--;
 		  ld2--;
 #endif
 		}
 	      else if (strncmp (arg, "--demangle", 10) == 0)
 		{
-#ifndef HAVE_LD_DEMANGLE
 		  no_demangle = 0;
 		  if (arg[10] == '=')
 		    {
@@ -1585,6 +1579,7 @@ main (int argc, char **argv)
 		      else
 			current_demangling_style = style;
 		    }
+#ifndef HAVE_LD_DEMANGLE
 		  ld1--;
 		  ld2--;
 #endif
Index: gcc/collect2.h
===================================================================
--- gcc/collect2.h	(revision 183674)
+++ gcc/collect2.h	(working copy)
@@ -30,7 +30,7 @@ extern void collect_exit (int) ATTRIBUTE
 
 extern int collect_wait (const char *, struct pex_obj *);
 
-extern void dump_file (const char *, FILE *);
+extern void dump_file (const char *, FILE *, int);
 
 extern int file_exists (const char *);
 
@@ -40,6 +40,13 @@ extern const char *c_file_name;
 extern struct obstack temporary_obstack;
 extern char *temporary_firstobj;
 extern bool vflag, debug;
+extern int no_demangle;
+
+#ifdef HAVE_LD_DEMANGLE
+#define DEMANGLE_IN_LD 1
+#else
+#define DEMANGLE_IN_LD 0
+#endif
 
 extern void notice_translated (const char *, ...) ATTRIBUTE_PRINTF_1;
 extern void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
Index: gcc/tlink.c
===================================================================
--- gcc/tlink.c	(revision 183674)
+++ gcc/tlink.c	(working copy)
@@ -766,8 +766,49 @@ scan_linker_output (const char *fname)
 void
 do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
 {
-  int exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+  int demangle_in_ld = DEMANGLE_IN_LD;
+  int map_file = FALSE;
+  int exit;
+  char **ld1_argv = ld_argv;
 
+#ifdef HAVE_LD_DEMANGLE
+  /* If there are repositories, proper processing of them depends on
+     the linker passing back mangled symbols.  So, explicitly tell the
+     linker not to demangle.  Also note whether the user requested a map
+     file, which requires special postprocessing.
+     We can skip this whole business if the user already asked
+     for non-demangled output.  */
+  if (!no_demangle)
+    {
+      int argc = 0;
+      int repo_files_exist = FALSE;
+      while (ld_argv[argc])
+	{
+	  if (*ld_argv[argc] == '-')
+	    {
+	      if (strncmp (ld_argv[argc], "-Map", 4) == 0)
+		map_file = TRUE;
+	    }
+	  else if (!repo_files_exist)
+	    {
+	      const char *p = frob_extension (ld_argv[argc], ".rpo");
+	      if (file_exists (p))
+		repo_files_exist = TRUE;
+	    }
+	  ++argc;
+	}
+      if (repo_files_exist)
+	{
+	  ld1_argv = XNEWVEC (char *, argc + 2);
+	  memcpy (ld1_argv, ld_argv, sizeof (ld_argv[0]) * argc);
+	  ld1_argv[argc] = CONST_CAST (char *, "--no-demangle");
+	  ld1_argv[argc + 1] = NULL;
+	  demangle_in_ld = FALSE;
+	}
+    }
+#endif
+
+  exit = tlink_execute ("ld", ld1_argv, ldout, lderrout);
   tlink_init ();
 
   if (exit)
@@ -781,8 +822,8 @@ do_tlink (char **ld_argv, char **object_
 	  {
 	    if (tlink_verbose >= 3)
 	      {
-		dump_file (ldout, stdout);
-		dump_file (lderrout, stderr);
+		dump_file (ldout, stdout, demangle_in_ld);
+		dump_file (lderrout, stderr, demangle_in_ld);
 	      }
 	    demangle_new_symbols ();
 	    if (! scan_linker_output (ldout)
@@ -792,13 +833,30 @@ do_tlink (char **ld_argv, char **object_
 	      break;
 	    if (tlink_verbose)
 	      fprintf (stderr, _("collect: relinking\n"));
-	    exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+	    exit = tlink_execute ("ld", ld1_argv, ldout, lderrout);
 	  }
     }
 
-  dump_file (ldout, stdout);
+#ifdef HAVE_LD_DEMANGLE
+  if (!demangle_in_ld)
+    {
+      XDELETEVEC (ld1_argv);
+      /* If the user specified all of demangling, a map file, and repositories,
+	 we must re-link once more with the original options to get the map
+	 file demangled. */
+      if (map_file)
+	{
+	  demangle_in_ld = TRUE;
+	  if (tlink_verbose)
+	    fprintf (stderr, _("collect: relinking\n"));
+	  exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+	}
+    }
+#endif
+
+  dump_file (ldout, stdout, demangle_in_ld);
   unlink (ldout);
-  dump_file (lderrout, stderr);
+  dump_file (lderrout, stderr, demangle_in_ld);
   unlink (lderrout);
   if (exit)
     {
Index: gcc/testsuite/g++.dg/torture/pr51910.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr51910.C	(revision 0)
+++ gcc/testsuite/g++.dg/torture/pr51910.C	(revision 0)
@@ -0,0 +1,19 @@
+// PR c++/51910 
+// Check that -frepo works in the presence of linker symbol demangling.
+//
+// { dg-options "-frepo -Wl,--demangle" }
+// { dg-require-host-local "" }
+// { dg-skip-if "dkms are not final links" { vxworks_kernel } }
+
+template<typename T>
+struct Foo
+{
+  virtual ~Foo() { }
+};
+
+int main( int, char*[] )
+{
+  Foo<int> test;
+}
+
+// { dg-final { cleanup-repo-files } }
