Mercurial > hg > CbC > CbC_gcc
diff gcc/tlink.c @ 111: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; } }