From mboxrd@z Thu Jan 1 00:00:00 1970 From: Hans-Peter Nilsson To: binutils@sources.redhat.com Subject: [RFA:] New test for bug in --gc-sections: selective6 Date: Sun, 24 Sep 2000 13:45:00 -0000 Message-id: X-SW-Source: 2000-09/msg00421.html I'm trying to prepare a presentation, where a paragraph mentions the benefits of --gc-sections et al. (Clouded by the fact that it only works with -static, bummer...) I wrote some example code to show, where it seems I catch myself lying about what --gc-sections really does, when used together with the corresponding GCC option, -fvtable-gc. Here's a test, selective6, based on selective5 (4.cc), in which functions to-be-dropped cause a .vtable_entry mark to be emitted, but where it sem that mark is not in turn garbage-collected, as I believe it should: B::foo is there, as well as drop1 and drop2 for some reason, perhaps another bug. Right now I don't know whether it is fixable or if there's a built-in limitation. I hope to give it a try. The test fails with assembly output from reasonably-current gcc CVS i686-pc-linux-gnulibc1 20000923 (and much earlier too), but works for the other test-cases in selective.exp, and the assembly code looks right, modulo an unrelated but harmless extra "*" from label mishandling of '__asm__ ("_start")'. BTW; that's a bad assumption about the start-label for a target. Right now I'm not looking into fixing it, though. Ok to commit? 2000-09-24 Hans-Peter Nilsson * ld-selective/5.cc: New test. * ld-selective/selective.exp: Run it as xfailed. Index: selective.exp =================================================================== RCS file: /cvs/src/src/ld/testsuite/ld-selective/selective.exp,v retrieving revision 1.7 diff -p -c -r1.7 selective.exp *** selective.exp 2000/09/05 04:07:46 1.7 --- selective.exp 2000/09/24 19:48:47 *************** set test2 "selective2" *** 32,37 **** --- 32,38 ---- set test3 "selective3" set test4 "selective4" set test5 "selective5" + set test6 "selective6" set cflags "-w -O2 -ffunction-sections -fdata-sections" set cxxflags "-fvtable-gc -fno-exceptions -fno-rtti" *************** if { [which $CXX] == 0 } { *** 43,48 **** --- 44,50 ---- untested $test3 untested $test4 untested $test5 + untested $test6 return } *************** if ![ld_simple_link $ld tmpdir/4.x "$ldf *** 191,193 **** --- 193,242 ---- } } } + + if { ![ld_compile "$CC $cflags $cxxflags" $srcdir/$subdir/5.cc tmpdir/5.o]} { + unresolved $test6 + return + } + + # Exposes a bug, currently. FIXME: Fix it. + # FIXME: Break out the nesting to a function that takes two lists, one + # with expected present symbols, one with expected absent symbols, and + # iterates over nm output. Use that function in all tests here. + + setup_xfail "*-*-*" + + if ![ld_simple_link $ld tmpdir/5.x "$ldflags tmpdir/5.o"] { + fail $test6 + } else { + if ![ld_nm $nm tmpdir/5.x] { + unresolved $test6 + } else { + if {[info exists nm_output(foo__1B)]} { + send_log "foo__1B == $nm_output(foo__1B)\n" + verbose "foo__1B == $nm_output(foo__1B)" + fail $test6 + } else { + if {[info exists nm_output(foo__1A)]} { + send_log "foo__1A == $nm_output(foo__1A)\n" + verbose "foo__1A == $nm_output(foo__1A)" + fail $test6 + } else { + if {[info exists nm_output(dropme1__Fv)]} { + send_log "dropme1__Fv == $nm_output(dropme1__Fv)\n" + verbose "dropme1__Fv == $nm_output(dropme1__Fv)" + fail $test6 + } else { + if {[info exists nm_output(dropme2__Fv)]} { + send_log "dropme2__Fv == $nm_output(dropme2__Fv)\n" + verbose "dropme2__Fv == $nm_output(dropme2__Fv)" + fail $test6 + } else { + pass $test6 + } + } + } + } + } + } + *** /dev/null Tue Jan 1 05:00:00 1980 --- 5.cc Sun Sep 24 21:02:51 2000 *************** *** 0 **** --- 1,32 ---- + struct A + { + virtual void foo(); + virtual void bar(); + }; + + void A::foo() { } // loose + void A::bar() { } // keep + + struct B : public A + { + virtual void foo(); + }; + + void B::foo() { } // loose + + void _start() __asm__("_start"); // keep + + A a; // keep + B b; + A *getme() { return &a; } // keep + + extern B* dropme2(); + void dropme1() { dropme2()->foo(); } // loose + B *dropme2() { return &b; } // loose + + void _start() + { + getme()->bar(); + } + + extern "C" void __main() { } brgds, H-P