[Ooops, resending to include the attachment, this time....]
As discussed in PR c++/51910, my patch from last summer
http://gcc.gnu.org/ml/gcc-patches/2011-06/msg01368.html
to make HAVE_LD_DEMANGLE the default when using GNU ld exposed a bug in
collect2's link-time -frepo handling -- it depends on the linker passing
back mangled names of undefined symbols to collect2. This patch fixes
that by explicitly adding --no-demangle to the options passed to the
linker in the repository-processing loop. Then the original settings
are restored for the final link, so that (for instance) if the user
requested a map file or if there are messages for real link errors, they
respect the user-specified demangling options. This patch therefore
adds two extra link steps to the case where HAVE_LD_DEMANGLE is defined,
there is repository information, and recompilation is necessary to
resolve undefined symbols from the repository. In other cases it adds
no overhead.
Bootstrapped and regression-tested on i636 linux. OK to check in?
-Sandra
2012-01-29 Sandra Loosemore <san...@codesourcery.com>
Jason Merrill <ja...@redhat.com>
Jakub Jelinek <ja...@redhat.com>
PR c++/51910
gcc/
* tlink.c (do_tlink): Explicitly pass --no-demangle to linker
for repo processing when HAVE_LD_DEMANGLE is defined.
gcc/testsuite/
* g++.dg/torture/pr51910.C: New testcase.
Index: gcc/tlink.c
===================================================================
--- gcc/tlink.c (revision 183674)
+++ gcc/tlink.c (working copy)
@@ -777,23 +777,53 @@ do_tlink (char **ld_argv, char **object_
/* Until collect does a better job of figuring out which are object
files, assume that everything on the command line could be. */
if (read_repo_files (ld_argv))
- while (exit && i++ < MAX_ITERATIONS)
- {
- if (tlink_verbose >= 3)
- {
- dump_file (ldout, stdout);
- dump_file (lderrout, stderr);
- }
- demangle_new_symbols ();
- if (! scan_linker_output (ldout)
- && ! scan_linker_output (lderrout))
- break;
- if (! recompile_files ())
- break;
- if (tlink_verbose)
- fprintf (stderr, _("collect: relinking\n"));
- exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
- }
+ {
+ char **ld1_argv = ld_argv;
+
+#ifdef HAVE_LD_DEMANGLE
+ /* We must explicitly tell the linker not to demangle names
+ and re-do the initial link attempt, since repository processing
+ requires demangled error output from the linker. */
+ int argc = 0;
+ while (ld_argv[argc])
+ ++argc;
+ 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;
+ if (tlink_verbose)
+ fprintf (stderr, _("collect: relinking\n"));
+ exit = tlink_execute ("ld", ld1_argv, ldout, lderrout);
+#endif
+
+ while (exit && i++ < MAX_ITERATIONS)
+ {
+ if (tlink_verbose >= 3)
+ {
+ dump_file (ldout, stdout);
+ dump_file (lderrout, stderr);
+ }
+ demangle_new_symbols ();
+ if (! scan_linker_output (ldout)
+ && ! scan_linker_output (lderrout))
+ break;
+ if (! recompile_files ())
+ break;
+ if (tlink_verbose)
+ fprintf (stderr, _("collect: relinking\n"));
+ exit = tlink_execute ("ld", ld1_argv, ldout, lderrout);
+ }
+
+#ifdef HAVE_LD_DEMANGLE
+ /* Now redo the final link with the original options so that
+ any remaining errors, the link map, etc are presented to
+ the user with the original mangling options.*/
+ XDELETEVEC (ld1_argv);
+ if (tlink_verbose)
+ fprintf (stderr, _("collect: relinking\n"));
+ exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+#endif
+ }
}
dump_file (ldout, stdout);
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 } }