OSDN Git Service

Fix PR43354: Correctly handle default definitions.
[pf3gnuchains/gcc-fork.git] / gcc / tlink.c
index bf4e1d7..7b58983 100644 (file)
@@ -1,7 +1,7 @@
 /* Scan linker error messages for missing template instantiations and provide
    them.
 
 /* Scan linker error messages for missing template instantiations and provide
    them.
 
-   Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005
+   Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008
    Free Software Foundation, Inc.
    Contributed by Jason Merrill (jason@cygnus.com).
 
    Free Software Foundation, Inc.
    Contributed by Jason Merrill (jason@cygnus.com).
 
@@ -9,7 +9,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -18,9 +18,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -31,6 +30,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "hashtab.h"
 #include "demangle.h"
 #include "collect2.h"
 #include "hashtab.h"
 #include "demangle.h"
 #include "collect2.h"
+#include "libiberty.h"
+
+/* TARGET_64BIT may be defined to use driver specific functionality. */
+#undef TARGET_64BIT
+#define TARGET_64BIT TARGET_64BIT_DEFAULT
 
 #define MAX_ITERATIONS 17
 
 
 #define MAX_ITERATIONS 17
 
@@ -39,7 +43,7 @@ extern int prepends_underscore;
 
 static int tlink_verbose;
 
 
 static int tlink_verbose;
 
-static char initial_cwd[MAXPATHLEN + 1];
+static char *initial_cwd;
 \f
 /* Hash table boilerplate for working with htab_t.  We have hash tables
    for symbol names, file names, and demangled symbols.  */
 \f
 /* Hash table boilerplate for working with htab_t.  We have hash tables
    for symbol names, file names, and demangled symbols.  */
@@ -98,7 +102,7 @@ static symbol * symbol_pop (void);
 static void file_push (file *);
 static file * file_pop (void);
 static void tlink_init (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 *);
+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 *);
 static char * frob_extension (const char *, const char *);
 static char * obstack_fgets (FILE *, struct obstack *);
 static char * tfgets (FILE *);
@@ -125,10 +129,10 @@ symbol_hash_lookup (const char *string, int create)
   if (*e == NULL)
     {
       struct symbol_hash_entry *v;
   if (*e == NULL)
     {
       struct symbol_hash_entry *v;
-      *e = v = xcalloc (1, sizeof (*v));
+      *e = v = XCNEW (struct symbol_hash_entry);
       v->key = xstrdup (string);
     }
       v->key = xstrdup (string);
     }
-  return *e;
+  return (struct symbol_hash_entry *) *e;
 }
 
 static htab_t file_table;
 }
 
 static htab_t file_table;
@@ -145,10 +149,10 @@ file_hash_lookup (const char *string)
   if (*e == NULL)
     {
       struct file_hash_entry *v;
   if (*e == NULL)
     {
       struct file_hash_entry *v;
-      *e = v = xcalloc (1, sizeof (*v));
+      *e = v = XCNEW (struct file_hash_entry);
       v->key = xstrdup (string);
     }
       v->key = xstrdup (string);
     }
-  return *e;
+  return (struct file_hash_entry *) *e;
 }
 
 static htab_t demangled_table;
 }
 
 static htab_t demangled_table;
@@ -167,10 +171,10 @@ demangled_hash_lookup (const char *string, int create)
   if (*e == NULL)
     {
       struct demangled_hash_entry *v;
   if (*e == NULL)
     {
       struct demangled_hash_entry *v;
-      *e = v = xcalloc (1, sizeof (*v));
+      *e = v = XCNEW (struct demangled_hash_entry);
       v->key = xstrdup (string);
     }
       v->key = xstrdup (string);
     }
-  return *e;
+  return (struct demangled_hash_entry *) *e;
 }
 \f
 /* Stack code.  */
 }
 \f
 /* Stack code.  */
@@ -194,8 +198,8 @@ struct file_stack_entry *file_stack;
 static void
 symbol_push (symbol *p)
 {
 static void
 symbol_push (symbol *p)
 {
-  struct symbol_stack_entry *ep = obstack_alloc
-    (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
+  struct symbol_stack_entry *ep
+    = XOBNEW (&symbol_stack_obstack, struct symbol_stack_entry);
   ep->value = p;
   ep->next = symbol_stack;
   symbol_stack = ep;
   ep->value = p;
   ep->next = symbol_stack;
   symbol_stack = ep;
@@ -222,8 +226,7 @@ file_push (file *p)
   if (p->tweaking)
     return;
 
   if (p->tweaking)
     return;
 
-  ep = obstack_alloc
-    (&file_stack_obstack, sizeof (struct file_stack_entry));
+  ep = XOBNEW (&file_stack_obstack, struct file_stack_entry);
   ep->value = p;
   ep->next = file_stack;
   file_stack = ep;
   ep->value = p;
   ep->next = file_stack;
   file_stack = ep;
@@ -275,15 +278,16 @@ tlink_init (void)
        tlink_verbose = 3;
     }
 
        tlink_verbose = 3;
     }
 
-  getcwd (initial_cwd, sizeof (initial_cwd));
+  initial_cwd = getpwd ();
 }
 
 static int
 }
 
 static int
-tlink_execute (const char *prog, char **argv, const char *redir)
+tlink_execute (const char *prog, char **argv, const char *outname,
+              const char *errname)
 {
   struct pex_obj *pex;
 
 {
   struct pex_obj *pex;
 
-  pex = collect_execute (prog, argv, redir);
+  pex = collect_execute (prog, argv, outname, errname, PEX_LAST | PEX_SEARCH);
   return collect_wait (prog, pex);
 }
 
   return collect_wait (prog, pex);
 }
 
@@ -298,7 +302,7 @@ frob_extension (const char *s, const char *ext)
     p = s + strlen (s);
 
   obstack_grow (&temporary_obstack, s, p - s);
     p = s + strlen (s);
 
   obstack_grow (&temporary_obstack, s, p - s);
-  return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
+  return (char *) obstack_copy0 (&temporary_obstack, ext, strlen (ext));
 }
 
 static char *
 }
 
 static char *
@@ -310,7 +314,7 @@ obstack_fgets (FILE *stream, struct obstack *ob)
   if (obstack_object_size (ob) == 0)
     return NULL;
   obstack_1grow (ob, '\0');
   if (obstack_object_size (ob) == 0)
     return NULL;
   obstack_1grow (ob, '\0');
-  return obstack_finish (ob);
+  return XOBFINISH (ob, char *);
 }
 
 static char *
 }
 
 static char *
@@ -470,7 +474,13 @@ recompile_files (void)
        }
       fclose (stream);
       fclose (output);
        }
       fclose (stream);
       fclose (output);
-      rename (outname, f->key);
+      /* On Windows "rename" returns -1 and sets ERRNO to EACCESS if
+        the new file name already exists.  Therefore, we explicitly
+        remove the old file first.  */
+      if (remove (f->key) == -1)
+       fatal_perror ("removing .rpo file");
+      if (rename (outname, f->key) == -1)
+       fatal_perror ("renaming .rpo file");
 
       if (!f->args)
        {
 
       if (!f->args)
        {
@@ -521,13 +531,13 @@ recompile_files (void)
     done:
       obstack_ptr_grow (&temporary_obstack, f->main);
       obstack_ptr_grow (&temporary_obstack, NULL);
     done:
       obstack_ptr_grow (&temporary_obstack, f->main);
       obstack_ptr_grow (&temporary_obstack, NULL);
-      argv = obstack_finish (&temporary_obstack);
+      argv = XOBFINISH (&temporary_obstack, char **);
 
       if (tlink_verbose)
        fprintf (stderr, _("collect: recompiling %s\n"), f->main);
 
       if (chdir (f->dir) != 0
 
       if (tlink_verbose)
        fprintf (stderr, _("collect: recompiling %s\n"), f->main);
 
       if (chdir (f->dir) != 0
-         || tlink_execute (c_file_name, argv, NULL) != 0
+         || tlink_execute (c_file_name, argv, NULL, NULL) != 0
          || chdir (initial_cwd) != 0)
        return 0;
 
          || chdir (initial_cwd) != 0)
        return 0;
 
@@ -600,12 +610,20 @@ scan_linker_output (const char *fname)
 {
   FILE *stream = fopen (fname, "r");
   char *line;
 {
   FILE *stream = fopen (fname, "r");
   char *line;
+  int skip_next_in_line = 0;
 
   while ((line = tfgets (stream)) != NULL)
     {
       char *p = line, *q;
       symbol *sym;
       int end;
 
   while ((line = tfgets (stream)) != NULL)
     {
       char *p = line, *q;
       symbol *sym;
       int end;
+      int ok = 0;
+
+      /* On darwin9, we might have to skip " in " lines as well.  */
+      if (skip_next_in_line
+         && strstr (p, " in "))
+         continue;
+      skip_next_in_line = 0;
 
       while (*p && ISSPACE ((unsigned char) *p))
        ++p;
 
       while (*p && ISSPACE ((unsigned char) *p))
        ++p;
@@ -643,10 +661,25 @@ scan_linker_output (const char *fname)
       if (! sym && ! end)
        /* Try a mangled name in quotes.  */
        {
       if (! sym && ! end)
        /* Try a mangled name in quotes.  */
        {
-         const char *oldq = q + 1;
+         char *oldq = q + 1;
          demangled *dem = 0;
          q = 0;
 
          demangled *dem = 0;
          q = 0;
 
+         /* On darwin9, we look for "foo" referenced from:\n\(.* in .*\n\)*  */
+         if (strcmp (oldq, "referenced from:") == 0)
+           {
+             /* We have to remember that we found a symbol to tweak.  */
+             ok = 1;
+
+             /* We actually want to start from the first word on the
+                line.  */
+             oldq = p;
+
+             /* Since the format is multiline, we have to skip
+                following lines with " in ".  */
+             skip_next_in_line = 1;
+           }
+
          /* First try `GNU style'.  */
          p = strchr (oldq, '`');
          if (p)
          /* First try `GNU style'.  */
          p = strchr (oldq, '`');
          if (p)
@@ -654,6 +687,9 @@ scan_linker_output (const char *fname)
          /* Then try "double quotes".  */
          else if (p = strchr (oldq, '"'), p)
            p++, q = strchr (p, '"');
          /* Then try "double quotes".  */
          else if (p = strchr (oldq, '"'), p)
            p++, q = strchr (p, '"');
+         /* Then try 'single quotes'.  */
+         else if (p = strchr (oldq, '\''), p)
+           p++, q = strchr (p, '\'');
          else {
            /* Then try entire line.  */
            q = strchr (oldq, 0);
          else {
            /* Then try entire line.  */
            q = strchr (oldq, 0);
@@ -674,7 +710,8 @@ scan_linker_output (const char *fname)
 
          /* We need to check for certain error keywords here, or we would
             mistakenly use GNU ld's "In function `foo':" message.  */
 
          /* We need to check for certain error keywords here, or we would
             mistakenly use GNU ld's "In function `foo':" message.  */
-         if (q && (strstr (oldq, "ndefined")
+         if (q && (ok
+                   || strstr (oldq, "ndefined")
                    || strstr (oldq, "nresolved")
                    || strstr (oldq, "nsatisfied")
                    || strstr (oldq, "ultiple")))
                    || strstr (oldq, "nresolved")
                    || strstr (oldq, "nsatisfied")
                    || strstr (oldq, "ultiple")))
@@ -696,7 +733,7 @@ scan_linker_output (const char *fname)
       if (sym && sym->tweaked)
        {
          error ("'%s' was assigned to '%s', but was not defined "
       if (sym && sym->tweaked)
        {
          error ("'%s' was assigned to '%s', but was not defined "
-                "during recompilation, or vice versa", 
+                "during recompilation, or vice versa",
                 sym->key, sym->file->key);
          fclose (stream);
          return 0;
                 sym->key, sym->file->key);
          fclose (stream);
          return 0;
@@ -729,7 +766,7 @@ scan_linker_output (const char *fname)
 void
 do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
 {
 void
 do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
 {
-  int exit = tlink_execute ("ld", ld_argv, ldout);
+  int exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
 
   tlink_init ();
 
 
   tlink_init ();
 
@@ -743,20 +780,26 @@ do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
        while (exit && i++ < MAX_ITERATIONS)
          {
            if (tlink_verbose >= 3)
        while (exit && i++ < MAX_ITERATIONS)
          {
            if (tlink_verbose >= 3)
-             dump_file (ldout);
+             {
+               dump_file (ldout, stdout);
+               dump_file (lderrout, stderr);
+             }
            demangle_new_symbols ();
            demangle_new_symbols ();
-           if (! scan_linker_output (ldout))
+           if (! scan_linker_output (ldout)
+               && ! scan_linker_output (lderrout))
              break;
            if (! recompile_files ())
              break;
            if (tlink_verbose)
              fprintf (stderr, _("collect: relinking\n"));
              break;
            if (! recompile_files ())
              break;
            if (tlink_verbose)
              fprintf (stderr, _("collect: relinking\n"));
-           exit = tlink_execute ("ld", ld_argv, ldout);
+           exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
          }
     }
 
          }
     }
 
-  dump_file (ldout);
+  dump_file (ldout, stdout);
   unlink (ldout);
   unlink (ldout);
+  dump_file (lderrout, stderr);
+  unlink (lderrout);
   if (exit)
     {
       error ("ld returned %d exit status", exit);
   if (exit)
     {
       error ("ld returned %d exit status", exit);