commit 1f4b0d273cfd81948762d3922cdafac40a06a2cf
Author: Jason Merrill <jason@redhat.com>
Date: Thu Feb 2 00:07:44 2012 -0500
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
@@ -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.
new file mode 100644
@@ -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;
+}
@@ -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);