aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2012-02-11 03:50:23 -0500
committerJason Merrill <jason@gcc.gnu.org>2012-02-11 03:50:23 -0500
commit4e92c31f3a3d1e85c3269348f1953658f11e694f (patch)
treed83848df093e0931613ba5a004396792d78d19cc /gcc
parentbd0ba05d4c778a42c0199f7868c36975431edcb2 (diff)
downloadgcc-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/ChangeLog10
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/repo10.C16
-rw-r--r--gcc/tlink.c98
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);