Summary: | [5/6 Regression] Using lto causes gtkmm/gparted and gtkmm/inkscape compile to fail | ||
---|---|---|---|
Product: | gcc | Reporter: | john.frankish |
Component: | c++ | Assignee: | Martin Liška <marxin> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | hubicka, hubicka, jakub, jason, jason, vincent-gcc, webrown.cpp |
Priority: | P2 | Keywords: | lto, wrong-code |
Version: | 5.2.0 | ||
Target Milestone: | 5.5 | ||
Host: | Target: | ||
Build: | Known to work: | 4.9.2, 7.1.0, 8.0 | |
Known to fail: | 5.1.0, 6.0 | Last reconfirmed: | 2016-02-25 00:00:00 |
Attachments: |
preprocessed gtkmm-3.16.0/gtk/gtkmm/treeviewcolumn.cc
Patch I am testing gparted build log |
Description
john.frankish
2016-02-25 08:56:22 UTC
Find out which source file implements Gtk::TreeViewColumn. Attach the preprocessed file of that compilation unit here. Also try GCC 5.3 (or a recent snapshot from the branch). Hello. I've just tried to build latest inkscape (gparted) with latest GCC, and no problem seen for following configurations: inkscape: -Os -flto=9 -flto -fuse-linker-plugin -mtune=generic -Os -pipe gparted: -Os -flto=9 -flto -fuse-linker-plugin -mtune=generic -Os -pipe Martin Created attachment 37800 [details]
preprocessed gtkmm-3.16.0/gtk/gtkmm/treeviewcolumn.cc
I'm not too sure what I'm doing here, but Gtk::TreeViewColumn seems to be implemented by gtkmm-3.16.0/gtk/gtkmm/treeviewcolumn.cc
Outout attached from:
$ g++ -flto -fuse-linker-plugin -mtune=generic -Os -pipe -std=c++11 -E gtkmm-3.16.0/gtk/gtkmm/treeviewcolumn.cc -I/usr/local/include/glibmm-2.4 -I/usr/local/lib/glibmm-2.4/include -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/local/include/sigc++-2.0 -I/usr/local/lib/sigc++-2.0/include -I/usr/local/include/gtkmm-3.0 -I/usr/local/lib/gtkmm-3.0/include -I/usr/local/lib/gdkmm-3.0/include -I/usr/local/lib/pangomm-1.4/include -I/usr/local/include/gtk-3.0 -I/usr/local/include/pango-1.0 -I/usr/local/include/cairo -I/usr/local/include/gdk-pixbuf-2.0 -I/usr/local/include/atk-1.0 -I/usr/local/include/pangomm-1.4 -I/usr/local/include/cairomm-1.0 -I/usr/local/include/freetype2 -I/usr/local/include/atkmm-1.6 -I/usr/local/include/gdkmm-3.0 -I/usr/local/include/giomm-2.4
markus@x4 tmp % g++ -flto -c -O2 -std=c++11 treeviewcolumn.i && nm treeviewcolumn.o | grep _ZTVN3Gtk14TreeViewColumnE 00000000 W _ZTVN3Gtk14TreeViewColumnE markus@x4 tmp % g++ -c -O2 -std=c++11 treeviewcolumn.i && nm treeviewcolumn.o | grep _ZTVN3Gtk14TreeViewColumnE 0000000000000000 V _ZTVN3Gtk14TreeViewColumnE In the resulting lib: x4 ~ # nm /usr/lib64/libgtkmm-2.4.so.1.1.0 | grep _ZTVN3Gtk14TreeViewColumnE 00000000003408e0 d _ZTVN3Gtk14TreeViewColumnE.lto_priv.729 (without lto:) x4 ~ # nm /tmp/libgtkmm-2.4.so.1.1.0 | grep _ZTVN3Gtk14TreeViewColumnE 00000000004331a0 V _ZTVN3Gtk14TreeViewColumnE markus@x4 tmp % g++ -flto -fPIC -DPIC -shared -nostdlib treeviewcolumn.i && nm ./a.out | grep _ZTVN3Gtk14TreeViewColumnE 000000000000b4d8 d _ZTVN3Gtk14TreeViewColumnE.lto_priv.2 markus@x4 tmp % g++ -fPIC -DPIC -shared -nostdlib treeviewcolumn.i && nm ./a.out | grep _ZTVN3Gtk14TreeViewColumnE 000000000000d648 V _ZTVN3Gtk14TreeViewColumnE err, OK - excuse my ignorance, but that does that imply? (In reply to john.frankish from comment #7) > err, OK - excuse my ignorance, but that does that imply? It it the reason for your link failure. Now the question is, if the compiler is right to make the symbol local with LTO? clang makes the symbol external for both lto and non-lto: 000000000000d5f0 D _ZTVN3Gtk14TreeViewColumnE Reducing... markus@x4 tmp % cat foo.ii namespace Glib { class ObjectBase { protected: virtual ~ObjectBase(); }; class A : virtual public ObjectBase {}; class B : virtual public ObjectBase {}; } namespace Gtk { class C : Glib::A {}; class D : public Glib::B {}; class TreeViewColumn : C, D { ~TreeViewColumn(); }; TreeViewColumn::~TreeViewColumn() {} } markus@x4 tmp % g++ -Os -flto -fPIC -shared -nostdlib -std=c++11 foo.ii && nm ./a.out | grep "_ZTVN3Gtk14TreeViewColumnE" 00000000000026a8 d _ZTVN3Gtk14TreeViewColumnE markus@x4 tmp % g++ -Os -fPIC -shared -nostdlib -std=c++11 foo.ii && nm ./a.out | grep "_ZTVN3Gtk14TreeViewColumnE" 00000000000025c8 V _ZTVN3Gtk14TreeViewColumnE markus@x4 tmp % g++ -O2 -fPIC -shared -nostdlib -std=c++11 foo.ii && nm ./a.out | grep "_ZTVN3Gtk14TreeViewColumnE" 00000000000013a8 V _ZTVN3Gtk14TreeViewColumnE markus@x4 tmp % clang++ -O2 -fPIC -shared -nostdlib -std=c++11 foo.ii && nm ./a.out | grep "_ZTVN3Gtk14TreeViewColumnE" 0000000000002900 D _ZTVN3Gtk14TreeViewColumnE markus@x4 tmp % clang++ -flto -O2 -fPIC -shared -nostdlib -std=c++11 foo.ii && nm ./a.out | grep "_ZTVN3Gtk14TreeViewColumnE" 0000000000002450 D _ZTVN3Gtk14TreeViewColumnE Here's another testcase that only produces a local symbol for all -O levels with -flto: namespace Glib { class A {}; class Object : virtual A { protected: ~Object(); }; class B : virtual A {}; } class C : Glib::Object {}; namespace Gtk { class D : Glib::B {}; class TreeViewColumn : C, D { virtual ~TreeViewColumn(); }; TreeViewColumn::~TreeViewColumn() {} } Is there any hope of a patch to fix this? 'Kind of digressing, but when I try with clang, I get this: $ clang++ -v -flto -O2 -fPIC -shared -nostdlib -std=c++11 foo.ii clang version 3.7.0 (tags/RELEASE_370/final) Target: x86_64-unknown-linux-gnu Thread model: posix Found candidate GCC installation: /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0 Selected GCC installation: /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0 Candidate multilib: .;@m64 Selected multilib: .;@m64 "/usr/local/bin/clang" -cc1 -triple x86_64-unknown-linux-gnu -flto -emit-llvm-bc -disable-free -disable-llvm-verifier -main-file-name clang.ii -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-linker-version 2.25.1 -momit-leaf-frame-pointer -v -dwarf-column-info -resource-dir /usr/local/bin/../lib/clang/3.7.0 -O2 -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /usr/src -ferror-limit 19 -fmessage-length 134 -mstackrealign -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -vectorize-loops -vectorize-slp -o /tmp/clang-920273.o -x c++-cpp-output clang.ii clang -cc1 version 3.7.0 based upon LLVM 3.7.0 default target x86_64-unknown-linux-gnu #include "..." search starts here: End of search list. "/usr/local/bin/ld" --eh-frame-hdr -m elf_x86_64 -shared -o a.out -L/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0 -L/lib/../lib64 -L/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../.. -L/usr/local/bin/../lib -L/lib -L/usr/lib -plugin /usr/local/bin/../lib/LLVMgold.so -plugin-opt=mcpu=x86-64 /tmp/clang-920273.o /tmp/clang-920273.o: file not recognized: File format not recognized clang: error: linker command failed with exit code 1 (use -v to see invocation) Will take a look Ah - clang works when I replace ld with ld.gold renamed to ld. Any news on a possible patch? This is perhaps worse than I thought - I went back and re-compiled libsigc++, glibmm, atkmm, cairomm, pangomm and gtkmm using gcc-5.2.0 without "-flto -fuse-linker-plugin". I then compiled inkscape-0.91 again and it fails at the final linking stage in a similar fashion as that when I compiled all of the above using lto: CXXLD inkscape widgets/gradient-selector.o: In function `Gtk::TreeViewColumn::TreeViewColumn<int>(Glib::ustring const&, Gtk::TreeModelColumn<int> const&)': gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0x29): undefined reference to `VTT for Gtk::TreeViewColumn' gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0x65): undefined reference to `VTT for Gtk::TreeViewColumn' gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0x81): undefined reference to `VTT for Gtk::TreeViewColumn' gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0x91): undefined reference to `vtable for Gtk::TreeViewColumn' gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0x9a): undefined reference to `vtable for Gtk::TreeViewColumn' gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0xa8): undefined reference to `vtable for Gtk::TreeViewColumn' gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0xda): undefined reference to `VTT for Gtk::TreeViewColumn' gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0xef): undefined reference to `VTT for Gtk::TreeViewColumn' gradient-selector.cpp:(.text._ZN3Gtk14TreeViewColumnC1IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IiEERKN4Glib7ustringERKNS_15TreeModelColumnIT_EE]+0x104): undefined reference to `VTT for Gtk::TreeViewColumn' ... input.cpp:(.text._ZN3Gtk14TreeViewColumnC1IN4Glib6RefPtrIN3Gdk6PixbufEEEEERKNS2_7ustringERKNS_15TreeModelColumnIT_EE[_ZN3Gtk14TreeViewColumnC5IN4Glib6RefPtrIN3Gdk6PixbufEEEEERKNS2_7ustringERKNS_15TreeModelColumnIT_EE]+0x104): undefined reference to `VTT for Gtk::TreeViewColumn' collect2: error: ld returned 1 exit status Makefile:6891: recipe for target 'inkscape' failed make[3]: *** [inkscape] Error 1 make[3]: Leaving directory '/usr/src/inkscape-0.91/src' Makefile:5048: recipe for target 'all' failed make[2]: *** [all] Error 2 make[2]: Leaving directory '/usr/src/inkscape-0.91/src' Makefile:1401: recipe for target 'all-recursive' failed make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory '/usr/src/inkscape-0.91' Makefile:1096: recipe for target 'all' failed make: *** [all] Error 2 The problem is that the symbol shares comdat group with _ZTCN3Gtk14TreeViewColumnE0_N4Glib6ObjectE/10 (_ZTCN3Gtk14TreeViewColumnE0_N4Glib6ObjectE) @0x7ffff6816980 Type: variable definition analyzed Visibility: forced_by_abi externally_visible prevailing_def_ironly public weak comdat comdat_group:_ZTVN3Gtk14TreeViewColumnE one_only visibility_specified visibility:hidden virtual artificial Same comdat group as: _ZTCN3Gtk14TreeViewColumnE0_1C/9 References: _ZTIN4Glib6ObjectE/31 (addr) Referring: _ZTTN3Gtk14TreeViewColumnE/8 (addr) Read from file: t.o Availability: available Varpool flags: initialized read-only const-value-known the symbol itself is: _ZTVN3Gtk14TreeViewColumnE/7 (_ZTVN3Gtk14TreeViewColumnE) @0x7ffff6816000 Type: variable definition analyzed Visibility: forced_by_abi externally_visible prevailing_def_ironly public weak comdat comdat_group:_ZTVN3Gtk14TreeViewColumnE one_only virtual artificial Same comdat group as: _ZTCN3Gtk14TreeViewColumnE8_N4Glib1BE/12 References: _ZTIN3Gtk14TreeViewColumnE/23 (addr)_ZN3Gtk14TreeViewColumnD1Ev/5 (addr)_ZN3Gtk14TreeViewColumnD0Ev/6 (addr)_ZTIN3Gtk14TreeViewColumnE/23 (addr) Referring: _ZN3Gtk14TreeViewColumnD1Ev/5 (addr)_ZTTN3Gtk14TreeViewColumnE/8 (addr)_ZTTN3Gtk14TreeViewColumnE/8 (addr)_ZN3Gtk14TreeViewColumnD0Ev/6 (addr) Read from file: /tmp/cc2mBAHW.o Availability: not-ready Varpool flags: initialized read-only const-value-known The problem is that one is hidden and other is exported. The hidden one will make us to privatize the whole comdat group. Jason, is this intentional? What is the reason for hidding some symbols and keeping other exported? If it is intentional I wonder what to do - I suppose we can privatize the hidden symbols and take them out of the comdat groups as long as we know they are not accessed by the non-IR code. Otherwise we need to keep whole comdat group untouched? This is bit tricky, but of course not that hard to implement. > _ZTCN3Gtk14TreeViewColumnE0_N4Glib6ObjectE/10
> (_ZTCN3Gtk14TreeViewColumnE0_N4Glib6ObjectE) @0x7ffff6816980
Aha, this is an construction vtable and the privatization is done by:
/* Don't export construction vtables from shared libraries. Even on
targets that don't support hidden visibility, this tells
can_refer_decl_in_current_unit_p not to assume that it's safe to
access from a different compilation unit (bz 54314). */
DECL_VISIBILITY (vtbl) = VISIBILITY_HIDDEN;
DECL_VISIBILITY_SPECIFIED (vtbl) = true;
If I recall correctly the reason for that hunk is that C++ ABI does not specify
if the construction vtable mangling. I wonder why those are part of the same
COMDAT group when the symbol itself is GNU extension. Won't things break if
one compiler produce COMDAT group definining the construction vtable while
other produce COMDAT group w/o and one w/o wins at static linking time?
Honza
FE issue manifesting as wrong-code with LTO. GCC 5.4 is being released, adjusting target milestone. I get the same kind of errors with "make check" for GMP 6.1.1 by using GCC 6.2.1 and LTO (-flto=jobserve -fuse-linker-plugin), e.g. /tmp/ccZvS3pG.ltrans0.ltrans.o: In function `main': <artificial>:(.text.startup+0xc): undefined reference to `tests_start' <artificial>:(.text.startup+0x17): undefined reference to `mp_trace_base' <artificial>:(.text.startup+0x43): undefined reference to `__gmpn_random' [...] but this is plain C, not C++. Is this the same bug? (I'm wondering because this bug is attributed to the c++ component.) (In reply to Vincent Lefèvre from comment #22) > I get the same kind of errors with "make check" for GMP 6.1.1 by using GCC > 6.2.1 and LTO (-flto=jobserve -fuse-linker-plugin), e.g. > > /tmp/ccZvS3pG.ltrans0.ltrans.o: In function `main': > <artificial>:(.text.startup+0xc): undefined reference to `tests_start' > <artificial>:(.text.startup+0x17): undefined reference to `mp_trace_base' > <artificial>:(.text.startup+0x43): undefined reference to `__gmpn_random' > [...] > > but this is plain C, not C++. Is this the same bug? (I'm wondering because > this bug is attributed to the c++ component.) No, this must be a different issue. Thanks for confirming. And indeed, I also get a failure with GCC 4.9.4, so that it is really different. For the reference, I've reported bug 78795. Why can't the middle-end/LTO handle comdat groups with some hidden and some non-hidden aliases? I don't see something inherently wrong on what the C++ FE is doing. Shouldn't we privatize the whole comdat group only if it has no exported symbols in it? (In reply to Jan Hubicka from comment #19) > > _ZTCN3Gtk14TreeViewColumnE0_N4Glib6ObjectE/10 > > (_ZTCN3Gtk14TreeViewColumnE0_N4Glib6ObjectE) @0x7ffff6816980 > > Aha, this is an construction vtable and the privatization is done by: > /* Don't export construction vtables from shared libraries. Even on > targets that don't support hidden visibility, this tells > can_refer_decl_in_current_unit_p not to assume that it's safe to > access from a different compilation unit (bz 54314). */ > DECL_VISIBILITY (vtbl) = VISIBILITY_HIDDEN; > DECL_VISIBILITY_SPECIFIED (vtbl) = true; > > If I recall correctly the reason for that hunk is that C++ ABI does not > specify > if the construction vtable mangling. I wonder why those are part of the same > COMDAT group when the symbol itself is GNU extension. Won't things break if > one compiler produce COMDAT group definining the construction vtable while > other produce COMDAT group w/o and one w/o wins at static linking time? Please read PR54314, I think it explains it nicely. The hidden construction vtable symbols are meant to be emitted in comdat group XYZ and have all the uses only from the same comdat group XYZ, therefore it should not be an ABI issue how it is mangled (the Itanium C++ ABI mangling indeed does not seem to specify TC) etc. as long as the linker picks or drops comdat groups from one input object always as whole, never picks one section of comdat group XYZ from object a.o and another section of comdat group XYZ from object b.o. Created attachment 41176 [details]
Patch I am testing
Hi,
I am testing the attached patch. This is but subtle issue, but I hope that it works right now. For a first time we make difference what symbols in a comdat to privatize. In this case we only turn the construction vtable into comdat local and dissolve the whole comdat group incrementally.
Author: hubicka Date: Thu Apr 13 08:04:52 2017 New Revision: 246899 URL: https://gcc.gnu.org/viewcvs?rev=246899&root=gcc&view=rev Log: PR lto/69953 * ipa-visibility.c (non_local_p): Fix typos. (localize_node): When localizing symbol in same comdat group, dissolve the group only when we know external symbols are going to be privatized. (function_and_variable_visibility): Do not localize DECL_EXTERNAL. Modified: trunk/gcc/ChangeLog trunk/gcc/ipa-visibility.c Fixed on the trunk so far, thanks Honza. I get similar issues when compiling glibmm-2.4 from git with g++ 6.3 and LTO, but not without LTO: undefined references to destructors for Glib::RefPtr<Gtk::TreeModel> and Glib::RefPtr<Gtk::Application>. Can this be related, or should I open another bug? Uh, sorry. I mean when compiling my own application against glibmm and gtkmm, using LTO on my app (only). Author: marxin Date: Thu Jun 22 11:16:16 2017 New Revision: 249514 URL: https://gcc.gnu.org/viewcvs?rev=249514&root=gcc&view=rev Log: Backport r246899 2017-06-22 Martin Liska <mliska@suse.cz> Backport from mainline 2017-04-12 Jan Hubicka <hubicka@ucw.cz> PR lto/69953 * ipa-visibility.c (non_local_p): Fix typos. (localize_node): When localizing symbol in same comdat group, dissolve the group only when we know external symbols are going to be privatized. (function_and_variable_visibility): Do not localize DECL_EXTERNAL. Modified: branches/gcc-6-branch/gcc/ChangeLog branches/gcc-6-branch/gcc/ipa-visibility.c Fixed on GCC 6.x, no plan to backport back to GCC 5, closing as resolved. According to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69953 *not* fixed for gcc-6. Oops sorry, that should have been: According to https://bugs.gentoo.org/show_bug.cgi?id=629342 *not* fixed for gcc-6. Please provide one more test-case that still fails and I will take a look. Feel free to reopen it. Created attachment 42140 [details]
gparted build log
Here's the build log from my Gentoo colleague.
If you need more, please tell me precisely what - I dont have that much experience reporting here yet. Can't reopen the bug either.
So downloading the package and testing that with problematic 6.3 does not reproduce. Can you please verify you have really GCC 6.4? If so, would it be possible to create a virtual machine or a Docker image which I can replay and thus reproduce? |