diff gcc/tlink.c @ 16:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/tlink.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/tlink.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,8 +1,7 @@
 /* Scan linker error messages for missing template instantiations and provide
    them.
 
-   Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008,
-   2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
    Contributed by Jason Merrill (jason@cygnus.com).
 
 This file is part of GCC.
@@ -27,9 +26,11 @@
 #include "tm.h"
 #include "intl.h"
 #include "obstack.h"
-#include "hashtab.h"
 #include "demangle.h"
 #include "collect2.h"
+#include "collect-utils.h"
+#include "filenames.h"
+#include "diagnostic-core.h"
 
 /* TARGET_64BIT may be defined to use driver specific functionality. */
 #undef TARGET_64BIT
@@ -65,10 +66,12 @@
   int tweaking;
 } file;
 
+typedef const char *str;
+
 typedef struct demangled_hash_entry
 {
   const char *key;
-  const char *mangled;
+  vec<str> mangled;
 } demangled;
 
 /* Hash and comparison functions for these hash tables.  */
@@ -100,8 +103,6 @@
 static symbol * symbol_pop (void);
 static void file_push (file *);
 static file * file_pop (void);
-static void tlink_init (void);
-static int tlink_execute (const char *, char **, const char *, const char *);
 static char * frob_extension (const char *, const char *);
 static char * obstack_fgets (FILE *, struct obstack *);
 static char * tfgets (FILE *);
@@ -271,7 +272,7 @@
   else
     {
       tlink_verbose = 1;
-      if (vflag)
+      if (verbose)
 	tlink_verbose = 2;
       if (debug)
 	tlink_verbose = 3;
@@ -282,21 +283,21 @@
 
 static int
 tlink_execute (const char *prog, char **argv, const char *outname,
-	       const char *errname)
+	       const char *errname, bool use_atfile)
 {
   struct pex_obj *pex;
 
-  pex = collect_execute (prog, argv, outname, errname, PEX_LAST | PEX_SEARCH);
+  pex = collect_execute (prog, argv, outname, errname,
+			 PEX_LAST | PEX_SEARCH, use_atfile);
   return collect_wait (prog, pex);
 }
 
 static char *
 frob_extension (const char *s, const char *ext)
 {
-  const char *p = strrchr (s, '/');
-  if (! p)
-    p = s;
-  p = strrchr (p, '.');
+  const char *p;
+
+  p = strrchr (lbasename (s), '.');
   if (! p)
     p = s + strlen (s);
 
@@ -434,9 +435,15 @@
       sym->tweaked = 1;
 
       if (line[0] == 'O')
-	line[0] = 'C';
+	{
+	  line[0] = 'C';
+	  sym->chosen = 1;
+	}
       else
-	line[0] = 'O';
+	{
+	  line[0] = 'O';
+	  sym->chosen = 0;
+	}
     }
 }
 
@@ -477,9 +484,9 @@
 	 the new file name already exists.  Therefore, we explicitly
 	 remove the old file first.  */
       if (remove (f->key) == -1)
-	fatal_perror ("removing .rpo file");
+	fatal_error (input_location, "removing .rpo file: %m");
       if (rename (outname, f->key) == -1)
-	fatal_perror ("renaming .rpo file");
+	fatal_error (input_location, "renaming .rpo file: %m");
 
       if (!f->args)
 	{
@@ -536,7 +543,7 @@
 	fprintf (stderr, _("collect: recompiling %s\n"), f->main);
 
       if (chdir (f->dir) != 0
-	  || tlink_execute (c_file_name, argv, NULL, NULL) != 0
+	  || tlink_execute (c_file_name, argv, NULL, NULL, false) != 0
 	  || chdir (initial_cwd) != 0)
 	return 0;
 
@@ -597,10 +604,34 @@
 	continue;
 
       dem = demangled_hash_lookup (p, true);
-      dem->mangled = sym->key;
+      dem->mangled.safe_push (sym->key);
     }
 }
 
+/* We want to tweak symbol SYM.  Return true if all is well, false on
+   error.  */
+
+static bool
+start_tweaking (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);
+      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);
+    }
+  return true;
+}
+
 /* Step through the output of the linker, in the file named FNAME, and
    adjust the settings for each symbol encountered.  */
 
@@ -615,8 +646,11 @@
     {
       char *p = line, *q;
       symbol *sym;
+      demangled *dem = 0;
       int end;
       int ok = 0;
+      unsigned ix;
+      str s;
 
       /* On darwin9, we might have to skip " in " lines as well.  */
       if (skip_next_in_line
@@ -661,7 +695,6 @@
 	/* Try a mangled name in quotes.  */
 	{
 	  char *oldq = q + 1;
-	  demangled *dem = 0;
 	  q = 0;
 
 	  /* On darwin9, we look for "foo" referenced from:\n\(.* in .*\n\)*  */
@@ -717,9 +750,7 @@
 	    {
 	      *q = 0;
 	      dem = demangled_hash_lookup (p, false);
-	      if (dem)
-		sym = symbol_hash_lookup (dem->mangled, false);
-	      else
+	      if (!dem)
 		{
 		  if (!strncmp (p, USER_LABEL_PREFIX,
 				strlen (USER_LABEL_PREFIX)))
@@ -729,24 +760,43 @@
 	    }
 	}
 
-      if (sym && sym->tweaked)
+      if (dem)
 	{
-	  error ("'%s' was assigned to '%s', but was not defined "
-		 "during recompilation, or vice versa",
-		 sym->key, sym->file->key);
+	  /* We found a demangled name.  If this is the name of a
+	     constructor or destructor, there can be several mangled names
+	     that match it, so choose or unchoose all of them.  If some are
+	     chosen and some not, leave the later ones that don't match
+	     alone for now; either this will cause the link to succeed, or
+	     on the next attempt we will switch all of them the other way
+	     and that will cause it to succeed.  */
+	  int chosen = 0;
+	  int len = dem->mangled.length ();
+	  ok = true;
+	  FOR_EACH_VEC_ELT (dem->mangled, ix, s)
+	    {
+	      sym = symbol_hash_lookup (s, false);
+	      if (ix == 0)
+		chosen = sym->chosen;
+	      else if (sym->chosen != chosen)
+		/* Mismatch.  */
+		continue;
+	      /* Avoid an error about re-tweaking when we guess wrong in
+		 the case of mismatch.  */
+	      if (len > 1)
+		sym->tweaked = false;
+	      ok = start_tweaking (sym);
+	    }
+	}
+      else
+	ok = start_tweaking (sym);
+
+      obstack_free (&temporary_obstack, temporary_firstobj);
+
+      if (!ok)
+	{
 	  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);
-	}
-
-      obstack_free (&temporary_obstack, temporary_firstobj);
     }
 
   fclose (stream);
@@ -765,23 +815,24 @@
 void
 do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
 {
-  int exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+  int ret = tlink_execute ("ld", ld_argv, ldout, lderrout,
+			   HAVE_GNU_LD && at_file_supplied);
 
   tlink_init ();
 
-  if (exit)
+  if (ret)
     {
       int i = 0;
 
       /* 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)
+	while (ret && i++ < MAX_ITERATIONS)
 	  {
 	    if (tlink_verbose >= 3)
 	      {
-		dump_file (ldout, stdout);
-		dump_file (lderrout, stderr);
+		dump_ld_file (ldout, stdout);
+		dump_ld_file (lderrout, stderr);
 	      }
 	    demangle_new_symbols ();
 	    if (! scan_linker_output (ldout)
@@ -791,17 +842,24 @@
 	      break;
 	    if (tlink_verbose)
 	      fprintf (stderr, _("collect: relinking\n"));
-	    exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+	    ret = tlink_execute ("ld", ld_argv, ldout, lderrout,
+				 HAVE_GNU_LD && at_file_supplied);
 	  }
     }
 
-  dump_file (ldout, stdout);
+  dump_ld_file (ldout, stdout);
   unlink (ldout);
-  dump_file (lderrout, stderr);
+  dump_ld_file (lderrout, stderr);
   unlink (lderrout);
-  if (exit)
+  if (ret)
     {
-      error ("ld returned %d exit status", exit);
-      collect_exit (exit);
+      error ("ld returned %d exit status", ret);
+      exit (ret);
+    }
+  else
+    {
+      /* We have just successfully produced an output file, so assume that we
+	 may unlink it if need be for now on.  */ 
+      may_unlink_output_file = true;
     }
 }