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
This commit is contained in:
Jason Merrill 2012-02-11 03:50:23 -05:00 committed by Jason Merrill
parent bd0ba05d4c
commit 4e92c31f3a
5 changed files with 108 additions and 23 deletions

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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;
}

View file

@ -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);