Consider the following two files: foo.cc: struct foo { virtual void bar(); }; void foo::bar() {} >>>>>>>> end of foo.cc main.cc struct foo { virtual void bar(); }; int main() { foo var1; } >>>>>>>> end of main.cc Compiling with g++ main.cc foo.cc works, but g++ -funit-at-a-time main.cc foo.cc results in /tmp/cc85sQ35.o: In function `foo::foo[in-charge]()': /tmp/cc85sQ35.o(.gnu.linkonce.t._ZN3fooC1Ev+0x8): undefined reference to `vtable for foo' collect2: ld returned 1 exit status Doing a "nm foo.o" shows that the vtable is not in the object file. This test was done with gcc version 3.4 20030703 (experimental), with the suggested fix for PR 11403 applied to gcc/cp/typeck.c
Subject: Re: New: [3.4 regression] vtables are not emitted in unit-at-a-time mode > > struct foo { > virtual void bar(); > }; > > void foo::bar() {} > > >>>>>>>> end of foo.cc > > main.cc > > struct foo { > virtual void bar(); > }; > > int main() { > foo var1; > } > > >>>>>>>> end of main.cc > > Compiling with > g++ main.cc foo.cc > works, but > g++ -funit-at-a-time main.cc foo.cc > results in > /tmp/cc85sQ35.o: In function `foo::foo[in-charge]()': > /tmp/cc85sQ35.o(.gnu.linkonce.t._ZN3fooC1Ev+0x8): undefined reference to > `vtable for foo' > collect2: ld returned 1 exit status Thanks, this is also usefull testcase as it finally got me into the problem of explicit inline instantiations we were discussing with Mark. Mark, the situation seems to be that all classes put into keyed_vtables list must be always output and the extension works by forcing vtable on that list. The attached patch makes this to happen and replaced the EXPLICIT_INSTANTIATION test we concluded to last time. Regtested/bootstrapped i686, OK? Honza Thu Jul 3 14:19:25 CEST 2003 Jan Hubicka <jh@suse.cz> * decl2.c (maybe_emit_vtables): New argument keyed; when set; mark vtable as needed. (finish_file): Update call of maybe_emit_vtables. Index: decl2.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v retrieving revision 1.636 diff -c -3 -p -r1.636 decl2.c *** decl2.c 2 Jul 2003 09:36:17 -0000 1.636 --- decl2.c 3 Jul 2003 12:17:36 -0000 *************** typedef struct priority_info_s { *** 63,69 **** static void mark_vtable_entries (tree); static void grok_function_init (tree, tree); ! static bool maybe_emit_vtables (tree); static void add_using_namespace (tree, tree, bool); static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *, int); static tree build_anon_union_vars (tree); --- 63,69 ---- static void mark_vtable_entries (tree); static void grok_function_init (tree, tree); ! static bool maybe_emit_vtables (tree, bool); static void add_using_namespace (tree, tree, bool); static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *, int); static tree build_anon_union_vars (tree); *************** prepare_assemble_variable (tree vars) *** 1631,1640 **** } /* If necessary, write out the vtables for the dynamic class CTYPE. ! Returns true if any vtables were emitted. */ static bool ! maybe_emit_vtables (tree ctype) { tree vtbl; tree primary_vtbl; --- 1643,1655 ---- } /* If necessary, write out the vtables for the dynamic class CTYPE. ! Returns true if any vtables were emitted. ! When KEYED is true, ensure that the vtables are marked as needed when they ! are output. This is used for virtual tables that are output only in files ! deifning some method and thus must appear even when they are unused. */ static bool ! maybe_emit_vtables (tree ctype, bool keyed) { tree vtbl; tree primary_vtbl; *************** maybe_emit_vtables (tree ctype) *** 1676,1682 **** mark_vtable_entries (vtbl); /* If we know that DECL is needed, mark it as such for the varpool. */ ! if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype)) cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl)); if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0) --- 1691,1697 ---- mark_vtable_entries (vtbl); /* If we know that DECL is needed, mark it as such for the varpool. */ ! if (keyed) cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl)); if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0) *************** finish_file () *** 2647,2653 **** have to look at it again. */ while (keyed_classes != NULL_TREE ! && maybe_emit_vtables (TREE_VALUE (keyed_classes))) { reconsider = true; keyed_classes = TREE_CHAIN (keyed_classes); --- 2662,2668 ---- have to look at it again. */ while (keyed_classes != NULL_TREE ! && maybe_emit_vtables (TREE_VALUE (keyed_classes), true)) { reconsider = true; keyed_classes = TREE_CHAIN (keyed_classes); *************** finish_file () *** 2660,2666 **** while (next) { ! if (maybe_emit_vtables (TREE_VALUE (next))) { reconsider = true; TREE_CHAIN (t) = TREE_CHAIN (next); --- 2675,2681 ---- while (next) { ! if (maybe_emit_vtables (TREE_VALUE (next), false)) { reconsider = true; TREE_CHAIN (t) = TREE_CHAIN (next);
Confirmed with the mainline (20030702).
Subject: Re: New: [3.4 regression] vtables are not emitted in unit-at-a-time mode On Thu, Jul 03, 2003 at 02:23:32PM +0200, Jan Hubicka wrote: > Index: decl2.c > =================================================================== > RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v > retrieving revision 1.636 > diff -c -3 -p -r1.636 decl2.c > *** decl2.c 2 Jul 2003 09:36:17 -0000 1.636 > --- decl2.c 3 Jul 2003 12:17:36 -0000 > *************** prepare_assemble_variable (tree vars) > *** 1631,1640 **** > } > > /* If necessary, write out the vtables for the dynamic class CTYPE. > ! Returns true if any vtables were emitted. */ > > static bool > ! maybe_emit_vtables (tree ctype) > { > tree vtbl; > tree primary_vtbl; > --- 1643,1655 ---- > } > > /* If necessary, write out the vtables for the dynamic class CTYPE. > ! Returns true if any vtables were emitted. > ! When KEYED is true, ensure that the vtables are marked as needed when they > ! are output. This is used for virtual tables that are output only in files > ! deifning some method and thus must appear even when they are unused. */ ^^^^^^^^ "defining"
Jan, your patch fixes the testcase. Unfortunately it does not fix the problem in my real-world code. I'll investigate some more and try to provide another testcase. Cheers, Martin
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode > PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org. > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11421 > > > > ------- Additional Comments From martin at mpa-garching dot mpg dot de 2003-07-03 16:34 ------- > Jan, > > your patch fixes the testcase. Unfortunately it does not fix the problem > in my real-world code. I'll investigate some more and try to provide > another testcase. too bad :( I am leaving and won't be online for day or two in few hours, so if you have some info early, I will be able to take a look into it, but otherwise it will take some time. What kind of unresolved symbols you get? Are these still vtables or something else? Thanks! Honza > > Cheers, > Martin > > > > > ------- You are receiving this mail because: ------- > You are on the CC list for the bug, or are watching someone who is.
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode Hi, does this by any chance help? *************** void *** 1607,1618 **** --- 1607,1619 ---- prepare_assemble_variable (tree vars) { tree parent; + #if 1 + tree vtbl; + #endif rtx child_rtx, parent_rtx; if (!flag_vtable_gc || TREE_CODE (vars) != VAR_DECL || !DECL_VTABLE_OR_VTT_P (vars)) return; + #if 1 + vtbl = CLASSTYPE_VTABLES (DECL_CONTEXT (vars)); + /* The ABI requires that we emit all of the vtables if we emit any + of them. */ + if (vtbl == vars || !cgraph_varpool_node (vtbl)->needed) + for (; vtbl; vtbl = TREE_CHAIN (vtbl)) + cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl)); + #endif + child_rtx = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */ parent = binfo_for_vtable (vars);
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode On Thu, Jul 03, 2003 at 04:49:22PM -0000, jh at suse dot cz wrote: > too bad :( > I am leaving and won't be online for day or two in few hours, so if you > have some info early, I will be able to take a look into it, but > otherwise it will take some time. I'm trying to distil a short example but this is harder than I thought. Probably I won't manage to finish in a few hours, so it's probably better to postpone it. I'm in no hurry at all; I just wanted to report the problems as soon as I ran across them. > What kind of unresolved symbols you get? Are these still vtables or > something else? It's still the vtables that are missing. Thanks, Martin
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode On Thu, Jul 03, 2003 at 04:57:24PM -0000, jh at suse dot cz wrote: > does this by any chance help? I've started a compilation and let you know as soon as possible. Cheers, Martin
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode > PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org. > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11421 > > > > ------- Additional Comments From martin at mpa-garching dot mpg dot de 2003-07-03 17:21 ------- > Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode > > On Thu, Jul 03, 2003 at 04:49:22PM -0000, jh at suse dot cz wrote: > > too bad :( > > I am leaving and won't be online for day or two in few hours, so if you > > have some info early, I will be able to take a look into it, but > > otherwise it will take some time. > > I'm trying to distil a short example but this is harder than I thought. > Probably I won't manage to finish in a few hours, so it's probably > better to postpone it. I'm in no hurry at all; I just wanted to report > the problems as soon as I ran across them. > > > What kind of unresolved symbols you get? Are these still vtables or > > something else? > > It's still the vtables that are missing. OK, please try my other patch. In the case it won't help it would be nice if you was able to figure out why the vtable must be emit and told maybe_emit_vtables to mark is as needed (this is the place touched by my next-to-last patch), in case you want to have some GCC fun :) Honza > > Thanks, > Martin > > > > > ------- You are receiving this mail because: ------- > You are on the CC list for the bug, or are watching someone who is.
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode On Thu, Jul 03, 2003 at 05:30:11PM -0000, jh at suse dot cz wrote: > OK, please try my other patch. In the case it won't help it would be > nice if you was able to figure out why the vtable must be emit and told > maybe_emit_vtables to mark is as needed (this is the place touched by my > next-to-last patch), in case you want to have some GCC fun :) Too bad, it still didn't work. I played around some more and the problem only occurs when -finline-functions is on. So it must be some interplay between unit-at-a-time and inlining. Hopefully I can give you more information in a few days. I don't dare fiddling with GCC itself, since I don't know much about compiler internals. Thanks again for your help, Martin
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode > PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org. > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11421 > > > > ------- Additional Comments From martin at mpa-garching dot mpg dot de 2003-07-03 18:34 ------- > Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode > > On Thu, Jul 03, 2003 at 05:30:11PM -0000, jh at suse dot cz wrote: > > OK, please try my other patch. In the case it won't help it would be > > nice if you was able to figure out why the vtable must be emit and told > > maybe_emit_vtables to mark is as needed (this is the place touched by my > > next-to-last patch), in case you want to have some GCC fun :) > > Too bad, it still didn't work. I played around some more and the problem > only occurs when -finline-functions is on. So it must be some interplay > between unit-at-a-time and inlining. It is probably the case where virtual table must be output, but unit-at-a-time is not told to do it and it suceeds to elliminate all references to it in the whole unit. I will try to check it from the US asap. Honza > > Hopefully I can give you more information in a few days. I don't dare > fiddling with GCC itself, since I don't know much about compiler internals. > > Thanks again for your help, > Martin > > > > > ------- You are receiving this mail because: ------- > You are on the CC list for the bug, or are watching someone who is.
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode Hi, I finally have a testcase that reproduces the problem even with your patch applied. Hopefully it helps you identify the problem; I'm more or less at my wits' end. Cheers, Martin
Created attachment 4358 [details] a small, but multi-file, testcase
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode > PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org. > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11421 > > > > ------- Additional Comments From martin at mpa-garching dot mpg dot de 2003-07-07 09:53 ------- > Subject: Re: [3.4 regression] vtables are not emitted > in unit-at-a-time mode > > Hi, > > I finally have a testcase that reproduces the problem even with your > patch applied. Hopefully it helps you identify the problem; I'm > more or less at my wits' end. Hi, it is again problem with marking vtables as needed. I don't quite understand the rules, but it seems to me that all public vtables must be output. This is at least what old code did because it uses DECL_NEEDED_P that test it this way. This patch changes the code to imitate it in unit-at-a-time (for PUBLIC and !COMDAT vtables before comdat_linkage is called we mark the vtables as needed). Does this look OK? Mon Jul 7 23:34:24 CEST 2003 Jan Hubicka <jh@suse.cz> * decl2.c (maybe_emit_vtables): Fix marking vtables as needed in unit-at-a-time Index: decl2.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v retrieving revision 1.642 diff -c -3 -p -r1.642 decl2.c *** decl2.c 6 Jul 2003 23:23:44 -0000 1.642 --- decl2.c 7 Jul 2003 21:32:13 -0000 *************** maybe_emit_vtables (tree ctype) *** 1635,1640 **** --- 1635,1641 ---- { tree vtbl; tree primary_vtbl; + bool needed; /* If the vtables for this class have already been emitted there is nothing more to do. */ *************** maybe_emit_vtables (tree ctype) *** 1652,1658 **** for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl)) if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl)) break; - if (!vtbl) { /* If the references to this class' vtables are optimized away, --- 1653,1658 ---- *************** maybe_emit_vtables (tree ctype) *** 1663,1668 **** --- 1663,1671 ---- note_debug_info_needed (ctype); return false; } + else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl)) + needed = 1; + /* The ABI requires that we emit all of the vtables if we emit any of them. */ *************** maybe_emit_vtables (tree ctype) *** 1673,1679 **** mark_vtable_entries (vtbl); /* If we know that DECL is needed, mark it as such for the varpool. */ ! if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype)) cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl)); if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0) --- 1676,1682 ---- mark_vtable_entries (vtbl); /* If we know that DECL is needed, mark it as such for the varpool. */ ! if (needed) cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl)); if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode "jh at suse dot cz" <gcc-bugzilla@gcc.gnu.org> writes: > --- 1635,1641 ---- > { > tree vtbl; > tree primary_vtbl; > + bool needed; Shouldn't this be initialized to false? > --- 1663,1671 ---- > note_debug_info_needed (ctype); > return false; > } > + else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl)) > + needed = 1; > + And this should probably be true instead of 1...
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode falk dot hueffner at student dot uni-tuebingen dot de wrote: > >>--- 1635,1641 ---- >> { >> tree vtbl; >> tree primary_vtbl; >>+ bool needed; > > > Shouldn't this be initialized to false? > > >>--- 1663,1671 ---- >> note_debug_info_needed (ctype); >> return false; >> } >>+ else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl)) >>+ needed = 1; >>+ > > > And this should probably be true instead of 1... Jan's patch with your corrections does the trick, and my code compiles again. Thanks very much! Martin
Subject: [C++ Patch]Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode > > > >>--- 1635,1641 ---- > >> { > >> tree vtbl; > >> tree primary_vtbl; > >>+ bool needed; > > > > > > Shouldn't this be initialized to false? > > > > > >>--- 1663,1671 ---- > >> note_debug_info_needed (ctype); > >> return false; > >> } > >>+ else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl)) > >>+ needed = 1; > >>+ > > > > > > And this should probably be true instead of 1... > > Jan's patch with your corrections does the trick, and my code compiles > again. Thanks very much! > Thanks for spotting it. Bit too much hurry :*( I noticed it while bootstrapping the patch too, here is updated one that bootstraps and regtests fully. Mon Jul 7 23:34:24 CEST 2003 Jan Hubicka <jh@suse.cz> * decl2.c (maybe_emit_vtables): Fix marking vtables as needed in unit-at-a-time Index: decl2.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v retrieving revision 1.642 diff -c -3 -p -r1.642 decl2.c *** decl2.c 6 Jul 2003 23:23:44 -0000 1.642 --- decl2.c 7 Jul 2003 21:32:13 -0000 *************** maybe_emit_vtables (tree ctype) *** 1635,1640 **** --- 1635,1641 ---- { tree vtbl; tree primary_vtbl; + bool needed = false; /* If the vtables for this class have already been emitted there is nothing more to do. */ *************** maybe_emit_vtables (tree ctype) *** 1652,1658 **** for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl)) if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl)) break; - if (!vtbl) { /* If the references to this class' vtables are optimized away, --- 1653,1658 ---- *************** maybe_emit_vtables (tree ctype) *** 1663,1668 **** --- 1663,1671 ---- note_debug_info_needed (ctype); return false; } + else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl)) + needed = true; + /* The ABI requires that we emit all of the vtables if we emit any of them. */ *************** maybe_emit_vtables (tree ctype) *** 1673,1679 **** mark_vtable_entries (vtbl); /* If we know that DECL is needed, mark it as such for the varpool. */ ! if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype)) cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl)); if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0) --- 1676,1682 ---- mark_vtable_entries (vtbl); /* If we know that DECL is needed, mark it as such for the varpool. */ ! if (needed) cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl)); if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
Subject: Re: [C++ Patch]Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode > > > > > >>--- 1635,1641 ---- > > >> { > > >> tree vtbl; > > >> tree primary_vtbl; > > >>+ bool needed; > > > > > > > > > Shouldn't this be initialized to false? > > > > > > > > >>--- 1663,1671 ---- > > >> note_debug_info_needed (ctype); > > >> return false; > > >> } > > >>+ else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl)) > > >>+ needed = 1; > > >>+ > > > > > > > > > And this should probably be true instead of 1... > > > > Jan's patch with your corrections does the trick, and my code compiles > > again. Thanks very much! > > > Thanks for spotting it. Bit too much hurry :*( > I noticed it while bootstrapping the patch too, here is updated one that > bootstraps and regtests fully. > > Mon Jul 7 23:34:24 CEST 2003 Jan Hubicka <jh@suse.cz> > * decl2.c (maybe_emit_vtables): Fix marking vtables as needed in > unit-at-a-time Hi, since this problems affects quite a lot of C++ programs compiled with -O3 (SPEC2000 EON for instance), I've commited the patch as obvious. We may try to find better sollution later. Honza
Subject: Re: [3.4 regression] vtables are not emitted in unit-at-a-time mode On Mon, 2003-07-07 at 14:36, Jan Hubicka wrote: > > PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org. > > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11421 > > > > > > > > ------- Additional Comments From martin at mpa-garching dot mpg dot de 2003-07-07 09:53 ------- > > Subject: Re: [3.4 regression] vtables are not emitted > > in unit-at-a-time mode > > > > Hi, > > > > I finally have a testcase that reproduces the problem even with your > > patch applied. Hopefully it helps you identify the problem; I'm > > more or less at my wits' end. > > Hi, > it is again problem with marking vtables as needed. I don't quite > understand the rules, but it seems to me that all public vtables must be > output. This is at least what old code did because it uses > DECL_NEEDED_P that test it this way. This patch changes the code to > imitate it in unit-at-a-time (for PUBLIC and !COMDAT vtables before > comdat_linkage is called we mark the vtables as needed). > > Does this look OK? Yes, thanks.
Fixed by my patch