diff options
author | Jason Merrill <jason@redhat.com> | 2012-02-11 03:50:23 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2012-02-11 03:50:23 -0500 |
commit | 4e92c31f3a3d1e85c3269348f1953658f11e694f (patch) | |
tree | d83848df093e0931613ba5a004396792d78d19cc /gcc | |
parent | bd0ba05d4c778a42c0199f7868c36975431edcb2 (diff) | |
download | gcc-4e92c31f3a3d1e85c3269348f1953658f11e694f.zip gcc-4e92c31f3a3d1e85c3269348f1953658f11e694f.tar.gz gcc-4e92c31f3a3d1e85c3269348f1953658f11e694f.tar.bz2 |
re PR c++/51910 (-frepo linking failure)
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
From-SVN: r184127
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/repo10.C | 16 | ||||
-rw-r--r-- | gcc/tlink.c | 98 |
5 files changed, 108 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bad4a05..9dce424 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2012-02-10 Jason Merrill <jason@redhat.com> + + 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 <jakub@redhat.com> PR debug/52132 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 770925f..f6cf8ff 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 0cd6876..812cee10 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-02-10 Jason Merrill <jason@redhat.com> + + PR c++/51910 + * g++.dg/template/repo10.C: New. + 2012-02-11 Jakub Jelinek <jakub@redhat.com> 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 0000000..c92f7a5 --- /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<typename T> +struct Foo +{ + virtual ~Foo() { } +}; + +int main( int, char*[] ) +{ + Foo<int> test; +} diff --git a/gcc/tlink.c b/gcc/tlink.c index f054047..67c7086 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,8 +609,32 @@ 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 @@ -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) { - 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); + /* 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) + { + fclose (stream); + return 0; + } } fclose (stream); |