diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bad4a057e7f..9dce4240230 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2012-02-10 Jason Merrill + + PR c++/51910 + * tlink.c (demangled_hash_entry): Change mangled to a VEC. + (demangle_new_symbols): Fill it. + (scan_linker_output): Walk it. + (start_tweaking): Split out from scan_linker_output. + (maybe_tweak): Update sym->chosen. + * Makefile.in (COLLECT2_OBJS): Add vec.o and gcc-none.o + 2012-02-11 Jakub Jelinek PR debug/52132 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 770925f2b36..f6cf8ffca33 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1946,7 +1946,7 @@ gcc-ranlib.c: gcc-ar.c gcc-nm.c: gcc-ar.c cp $^ $@ -COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o +COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o vec.o ggc-none.o COLLECT2_LIBS = @COLLECT2_LIBS@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) # Don't try modifying collect2 (aka ld) in place--it might be linking this. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0cd68764224..812cee10c3b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-02-10 Jason Merrill + + PR c++/51910 + * g++.dg/template/repo10.C: New. + 2012-02-11 Jakub Jelinek PR debug/52132 diff --git a/gcc/testsuite/g++.dg/template/repo10.C b/gcc/testsuite/g++.dg/template/repo10.C new file mode 100644 index 00000000000..c92f7a52b60 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/repo10.C @@ -0,0 +1,16 @@ +// PR c++/51910 +// { dg-options -frepo } +// { dg-require-host-local "" } +// { dg-skip-if "dkms are not final links" { vxworks_kernel } } +// { dg-final cleanup-repo-files } + +template +struct Foo +{ + virtual ~Foo() { } +}; + +int main( int, char*[] ) +{ + Foo test; +} diff --git a/gcc/tlink.c b/gcc/tlink.c index f0540478e72..67c7086ceb1 100644 --- a/gcc/tlink.c +++ b/gcc/tlink.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "collect2.h" #include "filenames.h" #include "diagnostic-core.h" +#include "vec.h" /* TARGET_64BIT may be defined to use driver specific functionality. */ #undef TARGET_64BIT @@ -67,10 +68,14 @@ typedef struct file_hash_entry int tweaking; } file; +typedef const char *str; +DEF_VEC_P(str); +DEF_VEC_ALLOC_P(str,heap); + typedef struct demangled_hash_entry { const char *key; - const char *mangled; + VEC(str,heap) *mangled; } demangled; /* Hash and comparison functions for these hash tables. */ @@ -435,9 +440,15 @@ maybe_tweak (char *line, file *f) 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; + } } } @@ -598,10 +609,34 @@ demangle_new_symbols (void) continue; dem = demangled_hash_lookup (p, true); - dem->mangled = sym->key; + VEC_safe_push (str, heap, dem->mangled, 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. */ @@ -616,8 +651,11 @@ scan_linker_output (const char *fname) { 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 @@ -662,7 +700,6 @@ scan_linker_output (const char *fname) /* 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\)* */ @@ -718,9 +755,7 @@ scan_linker_output (const char *fname) { *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))) @@ -730,24 +765,43 @@ scan_linker_output (const char *fname) } } - if (sym && sym->tweaked) + if (dem) + { + /* 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 suceed, 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 = VEC_length (str, dem->mangled); + ok = true; + FOR_EACH_VEC_ELT (str, 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) { - 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); - } - - obstack_free (&temporary_obstack, temporary_firstobj); } fclose (stream);