Patchwork fix PR51910, take 2

login
register
mail settings
Submitter Jakub Jelinek
Date Feb. 3, 2012, 9:27 a.m.
Message ID <20120203092717.GC18768@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/139323/
State New
Headers show

Comments

Jakub Jelinek - Feb. 3, 2012, 9:27 a.m.
On Thu, Feb 02, 2012 at 09:10:50PM -0700, Sandra Loosemore wrote:
> --- 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" }

I don't think you want to use this in the testsuite, that assumes the
linker handles it, which is not the case for non-GNU linkers.

Anyway, here is the tweaking all the symbols that demangle the same
equally patch (untested so far) as an alternative.  On the example it
unfortunately causes also the D2 dtor into the link which wasn't there
otherwise (and with -Wl,--no-demangle).  While D2 dtors are generally small,
perhaps it will sometimes force into the link also ctor or dtor variants
that couldn't be aliased together.

I wonder if it wouldn't be better to just use a linker plugin for -frepo
if the linker supports plugins.

2012-02-03  Jakub Jelinek  <jakub@redhat.com>

	PR c++/51910
	* tlink.c (demangleq_equiv): New typedef.
	(demangled): Add equiv field.
	(demangle_new_symbols): Chain mangled symbols that demangle the
	same into dem->equiv chain.
	(handle_sym): New function.
	(scan_linker_output): Use it.  Call handle_sym on all other symbols
	that demangle the same.


	Jakub
Jakub Jelinek - Feb. 3, 2012, 12:03 p.m.
On Fri, Feb 03, 2012 at 10:27:17AM +0100, Jakub Jelinek wrote:
> Anyway, here is the tweaking all the symbols that demangle the same
> equally patch (untested so far) as an alternative.  On the example it

Now bootstrapped/regtested on x86_64-linux and i686-linux.

	Jakub

Patch

--- gcc/tlink.c.jj	2012-01-30 00:08:28.000000000 +0100
+++ gcc/tlink.c	2012-02-03 10:13:08.799161429 +0100
@@ -67,10 +67,17 @@  typedef struct file_hash_entry
   int tweaking;
 } file;
 
+typedef struct demangled_equiv_entry
+{
+  const char *mangled;
+  struct demangled_equiv_entry *next;
+} demangled_equiv;
+
 typedef struct demangled_hash_entry
 {
   const char *key;
   const char *mangled;
+  demangled_equiv *equiv;
 } demangled;
 
 /* Hash and comparison functions for these hash tables.  */
@@ -598,10 +605,43 @@  demangle_new_symbols (void)
 	continue;
 
       dem = demangled_hash_lookup (p, true);
-      dem->mangled = sym->key;
+      if (dem->mangled)
+	{
+	  demangled_equiv *equiv = XCNEW (demangled_equiv);
+	  equiv->mangled = sym->key;
+	  equiv->next = dem->equiv;
+	  dem->equiv = equiv;
+	}
+      else
+        dem->mangled = sym->key;
     }
 }
 
+/* Helper function of scan_linker_output.  Handle a single symbol SYM.
+   Returns 1 if an error happened, 0 otherwise.  */
+
+static bool
+handle_sym (FILE *stream, symbol *sym)
+{
+  if (sym && sym->tweaked)
+    {
+      error ("'%s' was assigned to '%s', but was not defined "
+	     "during recompilation, or vice versa",
+	     sym->key, sym->file->key);
+      fclose (stream);
+      return true;
+    }
+  if (sym && !sym->tweaking)
+    {
+      if (tlink_verbose >= 2)
+	fprintf (stderr, _("collect: tweaking %s in %s\n"),
+		 sym->key, sym->file->key);
+      sym->tweaking = 1;
+      file_push (sym->file);
+    }
+  return false;
+}
+
 /* Step through the output of the linker, in the file named FNAME, and
    adjust the settings for each symbol encountered.  */
 
@@ -719,7 +759,19 @@  scan_linker_output (const char *fname)
 	      *q = 0;
 	      dem = demangled_hash_lookup (p, false);
 	      if (dem)
-		sym = symbol_hash_lookup (dem->mangled, false);
+		{
+		  if (dem->equiv)
+		    {
+		      demangled_equiv *equiv;
+		      for (equiv = dem->equiv; equiv; equiv = equiv->next)
+			{
+			  sym = symbol_hash_lookup (equiv->mangled, false);
+			  if (handle_sym (stream, sym))
+			    return 0;
+			}
+		    }
+		  sym = symbol_hash_lookup (dem->mangled, false);
+		}
 	      else
 		{
 		  if (!strncmp (p, USER_LABEL_PREFIX,
@@ -730,22 +782,8 @@  scan_linker_output (const char *fname)
 	    }
 	}
 
-      if (sym && sym->tweaked)
-	{
-	  error ("'%s' was assigned to '%s', but was not defined "
-		 "during recompilation, or vice versa",
-		 sym->key, sym->file->key);
-	  fclose (stream);
-	  return 0;
-	}
-      if (sym && !sym->tweaking)
-	{
-	  if (tlink_verbose >= 2)
-	    fprintf (stderr, _("collect: tweaking %s in %s\n"),
-		     sym->key, sym->file->key);
-	  sym->tweaking = 1;
-	  file_push (sym->file);
-	}
+      if (handle_sym (stream, sym))
+	return 0;
 
       obstack_free (&temporary_obstack, temporary_firstobj);
     }