pykde4-4.11.2 fails to build: CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart5.cpp.o:sipphononpart5.cpp:function release_Phonon_BackendCapabilities_Notifier: error: undefined reference to 'vtable for Phonon::BackendCapabilities::Notifier' /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.0/../../../../x86_64-pc-linux-gnu/bin/ld: the vtable symbol may be undefined because the class is missing its key function CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart5.cpp.o:sipphononpart5.cpp:function Phonon::BackendCapabilities::Notifier::~Notifier(): error: undefined reference to 'vtable for Phonon::BackendCapabilities::Notifier' /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.0/../../../../x86_64-pc-linux-gnu/bin/ld: the vtable symbol may be undefined because the class is missing its key function CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart5.cpp.o:sipphononpart5.cpp:function Phonon::BackendCapabilities::Notifier::~Notifier(): error: undefined reference to 'vtable for Phonon::BackendCapabilities::Notifier' /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.0/../../../../x86_64-pc-linux-gnu/bin/ld: the vtable symbol may be undefined because the class is missing its key function collect2: error: ld returned 1 exit status Reduced: markus@x4 tmp % cat test.ii class A { public: virtual ~A(); }; class B : A { virtual int m_fn1(); }; void fn1() { delete reinterpret_cast<B*>(1); } markus@x4 tmp % g++ -O1 -c test.ii markus@x4 tmp % nm test.o | c++filt 0000000000000000 T fn1() markus@x4 tmp % g++ -O2 -c test.ii markus@x4 tmp % nm test.o | c++filt 0000000000000000 T fn1() U operator delete(void*) U A::~A() 0000000000000000 W B::~B() 0000000000000000 W B::~B() 0000000000000000 W B::~B() 0000000000000000 n B::~B() U vtable for B markus@x4 tmp % clang++ -O2 -c test.ii markus@x4 tmp % nm test.o | c++filt 0000000000000000 T fn1() markus@x4 tmp % Started with r202145.
Hmm, what prevents us from devirtualizing here? It seems to be bug to include a class without linking with its implementation..
(In reply to Jan Hubicka from comment #1) > Hmm, what prevents us from devirtualizing here? It seems to be bug to > include a class without linking with its implementation.. In this case the implementation is linked in, but the symbol is only local. # nm /usr/lib64/libphonon.so.4.6.0 | c++filt | grep "vtable for Phonon::BackendCapabilities::Notifier" 0000000000066380 d vtable for Phonon::BackendCapabilities::Notifier
Adding __attribute__ ((visibility ("default"))) to Phonon::BackendCapabilities::Notifier fixes the issue.
Actually ipa-devirt has a code that is supposed to not make devirt happen in this case - I will check out why it doesn't here. But I think it is KDE's bug here. You have library with -fvisibility=hidden and the class has no visibility attributes attached, so it is fully captured in the library and you should not include it from file that is not part of the library. Not exactly C++ standard, since it does not speak about visibilities, but it is how we figure out what we can reffer: static bool can_refer_decl_in_current_unit_p (tree decl, tree from_decl) which has clause /* We are folding reference from external vtable. The vtable may reffer to a symbol keyed to other compilation unit. The other compilation unit may be in separate DSO and the symbol may be hidden. */ if (DECL_VISIBILITY_SPECIFIED (decl) && DECL_EXTERNAL (decl) && (!(snode = symtab_get_node (decl)) || !snode->symbol.in_other_partition)) return false; that is supposed to catch cases where user specifies visibilities. It won't catch this case because command line option is used. I am adding Jason into CC, perhaps we need to revisit logic above. I will also check why the devirtualization survive - it should not since it seems useless. Honza
Actually one thing I am puzzled about is the fact that ~B() that is being devirtualized is COMDAT, but it reffers to the vtable that is external: _ZTV1B/6 (int (* B::_ZTV1B [5])(...)) @0x7ffff7036a28 Type: variable definition analyzed Visibility: external public virtual artificial Aux: @0x1 References: _ZTI1B/9 (addr)_ZN1BD1Ev/3 (addr)_ZN1BD0Ev/4 (addr)virtual int B::m_fn1()/10 (addr) Referring: _ZN1BD2Ev/2 (addr) Availability: not-ready Varpool flags: initialized read-only const-value-known _ZN1BD0Ev/4 (virtual B::~B()) @0x7ffff70405f0 Type: function definition analyzed Visibility: public weak comdat comdat_group:_ZN1BD0Ev one_only virtual artificial Same comdat group as: _ZN1BD2Ev/2 Address is taken. Aux: @0x1 References: Referring: _ZTV1B/6 (addr) Function flags: body Called by: Calls: void operator delete(void*)/5 (1.00 per call) _ZN1BD1Ev/3 (1.00 per call) (can throw external) Backend believe that every function with body defined can actually be inlined (or there is no point to pass it down from FE at first place). I wonder how C++ ends up with two different visibilities for these - B seems keyed by the virtual function it defines, but why the destructor is not keyed then as well?
I am still affected by this on trunk with pykde4-4.12.1. Should I report it as pykde bug to its maintainers? CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart5.cpp.o: In function `~Notifier': /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart5.cpp.o: In function `Phonon::BackendCapabilities::Notifier::~Notifier()': /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' collect2: error: ld returned 1 exit status
Gcc 4.8.2 compiles the same source code without errors reported for all selected Python 2.7, 3.2 and 3.3 versions. (Regression?)
I'm still not 100% sure. Lets reopen to ponder this further.
Maybe this is a same type of problem (kde-base/korganizer-4.12.1): CMakeFiles/korganizer_core.dir/kocore.o: In function `~Part': /var/tmp/portage/kde-base/korganizer-4.12.1/work/korganizer-4.12.1/korganizer/interfaces/korganizer/part.h:55: undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o: In function `KOrg::Part::~Part()': /var/tmp/portage/kde-base/korganizer-4.12.1/work/korganizer-4.12.1/korganizer/interfaces/korganizer/part.h:55: undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o: In function `~Part': /var/tmp/portage/kde-base/korganizer-4.12.1/work/korganizer-4.12.1/korganizer/interfaces/korganizer/part.h:55: undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTIN4KOrg4PartE[_ZTIN4KOrg4PartE]+0x10): undefined reference to `typeinfo for KParts::Part' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x10): undefined reference to `typeinfo for KParts::PartBase' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x18): undefined reference to `KParts::PartBase::~PartBase()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x20): undefined reference to `KParts::PartBase::~PartBase()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x28): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x30): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&, bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0xb0): undefined reference to `typeinfo for KParts::PartBase' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0xb8): undefined reference to `virtual thunk to KParts::PartBase::~PartBase()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0xc0): undefined reference to `virtual thunk to KParts::PartBase::~PartBase()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0xf8): undefined reference to `virtual thunk to KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x10): undefined reference to `typeinfo for KParts::Part' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x18): undefined reference to `KParts::Part::metaObject() const' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x20): undefined reference to `KParts::Part::qt_metacast(char const*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x28): undefined reference to `KParts::Part::qt_metacall(QMetaObject::Call, int, void**)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x30): undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x38): undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x60): undefined reference to `KParts::Part::customEvent(QEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x78): undefined reference to `KParts::Part::embed(QWidget*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x80): undefined reference to `KParts::Part::widget()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x88): undefined reference to `KParts::Part::setManager(KParts::PartManager*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x90): undefined reference to `KParts::Part::hitTest(QWidget*, QPoint const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x98): undefined reference to `KParts::Part::setSelectable(bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xa0): undefined reference to `KParts::Part::setWidget(QWidget*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xa8): undefined reference to `KParts::Part::partActivateEvent(KParts::PartActivateEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xb0): undefined reference to `KParts::Part::partSelectEvent(KParts::PartSelectEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xb8): undefined reference to `KParts::Part::guiActivateEvent(KParts::GUIActivateEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xd0): undefined reference to `typeinfo for KParts::Part' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xd8): undefined reference to `non-virtual thunk to KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xe0): undefined reference to `non-virtual thunk to KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xe8): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xf0): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&, bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x170): undefined reference to `typeinfo for KParts::Part' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x178): undefined reference to `virtual thunk to KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x180): undefined reference to `virtual thunk to KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x1b8): undefined reference to `virtual thunk to KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x18): undefined reference to `KParts::Part::metaObject() const' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x20): undefined reference to `KParts::Part::qt_metacast(char const*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x28): undefined reference to `KParts::Part::qt_metacall(QMetaObject::Call, int, void**)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x60): undefined reference to `KParts::Part::customEvent(QEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x78): undefined reference to `KParts::Part::embed(QWidget*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x80): undefined reference to `KParts::Part::widget()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x88): undefined reference to `KParts::Part::setManager(KParts::PartManager*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x90): undefined reference to `KParts::Part::hitTest(QWidget*, QPoint const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x98): undefined reference to `KParts::Part::setSelectable(bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xa0): undefined reference to `KParts::Part::setWidget(QWidget*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xa8): undefined reference to `KParts::Part::partActivateEvent(KParts::PartActivateEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xb0): undefined reference to `KParts::Part::partSelectEvent(KParts::PartSelectEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xb8): undefined reference to `KParts::Part::guiActivateEvent(KParts::GUIActivateEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xf8): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x100): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&, bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x1c8): undefined reference to `virtual thunk to KParts::PartBase::setComponentData(KComponentData const&)'
I reported this as Calligra error but it is not. Gcc-4.8.2 can compile the same source code. Trunk can't: CMakeFiles/calligrasheetscommon.dir/commands/ConditionCommand.cpp.o: In function `Calligra::Sheets::Conditions::operator<(Calligra::Sheets::Conditions const&) const': /var/tmp/portage/app-office/calligra-2.7.5/work/calligra-2.7.5/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.7.5/work/calligra-2.7.5/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.7.5/work/calligra-2.7.5/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.7.5/work/calligra-2.7.5/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.7.5/work/calligra-2.7.5/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' CMakeFiles/calligrasheetscommon.dir/commands/ConditionCommand.cpp.o:/var/tmp/portage/app-office/calligra-2.7.5/work/calligra-2.7.5/sheets/Condition.h:170: more undefined references to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' follow collect2: error: ld returned 1 exit status sheets/CMakeFiles/calligrasheetscommon.dir/build.make:3108: recipe for target 'lib/libcalligrasheetscommon.so.12.0.0' failed make[2]: *** [lib/libcalligrasheetscommon.so.12.0.0] Error 1 I think this is the same type of error.
David, without testcases it's very hard to tell what's going on.
I can provide .ii files. Is this reducable? I can try target c-reduce to linker error. Is any of the http://gcc.gnu.org/wiki/A_guide_to_testcase_reduction applicable here please? What is clear is that gcc-4.8.2 can compile it, trunk gcc not. All of these packages. Thank you.
The issue from comment 9 is indeed the same problem. markus@x4 tmp % cat test.ii class Part { public: virtual ~Part(); }; class A : Part {}; void fn1() { A *a; delete a; } markus@x4 tmp % g++ -O2 -c test.ii markus@x4 tmp % nm test.o | c++filt 0000000000000000 T fn1() U operator delete(void*) 0000000000000000 W A::~A() 0000000000000000 W A::~A() 0000000000000000 W A::~A() 0000000000000000 n A::~A() U Part::~Part() 0000000000000000 V typeinfo for A U typeinfo for Part 0000000000000000 V typeinfo name for A 0000000000000000 V vtable for A U vtable for __cxxabiv1::__vmi_class_type_info markus@x4 tmp % /usr/x86_64-pc-linux-gnu/gcc-bin/4.8.3/g++ -O2 -c test.ii markus@x4 tmp % nm test.o | c++filt 0000000000000000 T fn1() markus@x4 tmp %
Jason, any idea? From middle-end perspective I see nothing that prevents me from devirtualizing here and I would incline to assume that one can not use a virtual method of a class that is in different DSO with hidden visibility. Adding explicit visibility into the sources (either default or hidden) should prevent GCC from trying to access the method directly. But without having annotation in the source one would basically have to disable all devirtualization to all external virtual methods if one would like to support this. I am changing component to C++.
It is still present in rev. 207565 and pykde4-4.12.2: CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart5.cpp.o: In function `~Notifier': /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart5.cpp.o: In function `Phonon::BackendCapabilities::Notifier::~Notifier()': /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' collect2: error: ld returned 1 exit status
I am also seeing this in libreoffice. We devirtualize into destructor of ZCodec that is a base class of other codec used in the library, but the library is not linking with its implementation. I believe it is a bug to include a class and not link with its implementation and not explicitly specify that the class may be hidden from the current DSO and thus it should be solved on the source code side. We ought to mention this in news.html and explain the issue. For libreoffice I go with class __attribute__ ((hidden)) TOOLS_DLLPUBLIC ZCodec in include/tools/zcodec.hxx I was thinking that with LTO I may reduce these problems by ruling out extern inline bodies that reference UNDEF symbols, but that will not solve non-flto I wrote bit more on the topic in http://hubicka.blogspot.ca/2014/01/devirtualization-in-c-part-2-low-level.html We however need opinion of a C++ maintainer.
(In reply to Markus Trippelsdorf from comment #0) > class A { > public: > virtual ~A(); > }; > class B : A { > virtual int m_fn1(); > }; > void fn1() { > delete reinterpret_cast<B*>(1); > } I don't understand how this could be devirtualized, since there is no actual B object. But this is beside the point. In general I agree with you: there's a fundamental problem here with devirtualization knowing which function to call vs. that function being hidden in another DSO. Client code has no way to know whether the library was built with -fvisibility=hidden. I think we want to add a GCC flag to force more conservative assumptions about visibility, i.e. that we can't refer to anything that might not be defined in the current object, and KDE programs could use that flag. Perhaps we should even make it the default in non-LTO mode.
It is a speculative devirtualization; we see no other option than B, so we try to inline it. Speculative devirtualization already has logic in it so it won't pick method without definition (it also will pick if the method is const/pure, I can change that) Here we have extern inline function with a definition so speculative devirtualization is happy and inline it. I don't think we should be checking at devirtualization time if the inlined function has refernce to something external or not. So I would say that C++ FE should not produce extern inlines that can not be inlined after all or better mark them UNINLINABLE so they can be used for side effects analysis. Or perhaps we can extend tree_inlinable_function_p this way? Honza
I think it would make sense to suppress speculative devirtualization of a DECL_ARTIFICIAL destructor, since that seems to be the problem here (and in 53808). I think it's better to address this in devirtualization rather than inlining so that an explicitly non-virtual call (e.g. from a destructor to a base destructor) can still be inlined. This doesn't address user-declared inline destructors, including those declared as =default in the class body, but I'm comfortable saying that people who do that should expect it to be inlined, whereas people who don't mention a destructor at all can be forgiven for being surprised that we inline the destructor they weren't thinking about. I think I'm also inclined to allow non-speculative devirtualization, since in cases where we know the type of the object we presumably have access to the vtable in the current shared object. Do you have an opinion about whether this restriction should apply to virtual operator= as well? I think that's much less likely to occur, but it probably makes most sense to handle it the same way. Testing a patch now.
Author: jason Date: Sat Mar 1 00:17:09 2014 New Revision: 208241 URL: http://gcc.gnu.org/viewcvs?rev=208241&root=gcc&view=rev Log: PR c++/58678 * ipa-devirt.c (ipa_devirt): Don't choose an implicitly-declared function. Added: trunk/gcc/testsuite/g++.dg/ipa/devirt-28.C Modified: trunk/gcc/ChangeLog trunk/gcc/ipa-devirt.c
Fixed.
I got this now with rev. 208241: /usr/bin/x86_64-pc-linux-gnu-g++ -fPIC -O2 -ggdb -pipe -march=native -mtune=native -mno-3dnow -mno-sse4.2 -mno-avx -Wnon-virtual-dtor -Wno-long-long -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-exceptions -DQT_NO_EXCEPTIONS -fno-check-new -fno-common -Woverloaded-virtual -fno-threadsafe-statics -fvisibility=hidden -fvisibility-inlines-hidden -fexceptions -UQT_NO_EXCEPTIONS -Wl,--enable-new-dtags -Wl,--no-undefined -lc -Wl,--as-needed -Wl,-O2 -O2 -ggdb -pipe -march=native -mtune=native -shared -Wl,-soname,libkorganizer_core.so.4 -o ../lib/libkorganizer_core.so.4.12.3 CMakeFiles/korganizer_core.dir/korganizer_core_automoc.o CMakeFiles/korganizer_core.dir/koprefs.o CMakeFiles/korganizer_core.dir/kocore.o CMakeFiles/korganizer_core.dir/koprefs_base.o -L/var/tmp/portage/kde-base/korganizer-4.12.3/work/korganizer-4.12.3_build/lib -L/usr/lib64/qt4 ../lib/libcalendarsupport.so.4.12.3 -leventviews ../lib/libincidenceeditorsng.so.4.12.3 -lkdepim ../lib/libkorganizer_interfaces.so.4.12.3 /usr/lib64/libakonadi-kde.so.4.12.3 /usr/lib64/libkcalcore.so.4.12.3 /usr/lib64/libkcalutils.so.4.12.3 /usr/lib64/libkmime.so.4.12.3 /usr/lib64/libkpimidentities.so.4.12.3 /usr/lib64/libkdecore.so.5.12.3 /usr/lib64/libkio.so.5.12.3 /usr/lib64/qt4/libQtUiTools.a -lz -lkdepim /usr/lib64/libkldap.so.4.12.3 /usr/lib64/libkcmutils.so.4.12.3 -lkdgantt2 -lakonadi_next -lakonadi-calendar ../lib/libcalendarsupport.so.4.12.3 /usr/lib64/libkcalutils.so.4.12.3 /usr/lib64/libkpimidentities.so.4.12.3 /usr/lib64/libkpimtextedit.so.4.12.3 /usr/lib64/libkholidays.so.4.12.3 /usr/lib64/libakonadi-contact.so.4.12.3 /usr/lib64/libkcalcore.so.4.12.3 /usr/lib64/libkabc.so.4.12.3 /usr/lib64/libkresources.so.4.12.3 /usr/lib64/libkpimutils.so.4.12.3 /usr/lib64/libnepomukcore.so.4.12.3 -lphonon /usr/lib64/libkmime.so.4.12.3 /usr/lib64/libakonadi-kde.so.4.12.3 /usr/lib64/libakonadiprotocolinternals.so.1.11.0 /usr/lib64/libkio.so.5.12.3 /usr/lib64/libsolid.so.4.12.3 /usr/lib64/qt4/libQtNetwork.so /usr/lib64/qt4/libQtXml.so /usr/lib64/libkdeui.so.5.12.3 /usr/lib64/libkdecore.so.5.12.3 /usr/lib64/qt4/libQtCore.so -lpthread /usr/lib64/qt4/libQtDBus.so /usr/lib64/qt4/libQtGui.so /usr/lib64/qt4/libQtSvg.so -lsoprano -Wl,-rpath,/var/tmp/portage/kde-base/korganizer-4.12.3/work/korganizer-4.12.3_build/lib:/usr/lib64/qt4: CMakeFiles/korganizer_core.dir/kocore.o: In function `~Part': /var/tmp/portage/kde-base/korganizer-4.12.3/work/korganizer-4.12.3/korganizer/interfaces/korganizer/part.h:55: undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o: In function `KOrg::Part::~Part()': /var/tmp/portage/kde-base/korganizer-4.12.3/work/korganizer-4.12.3/korganizer/interfaces/korganizer/part.h:55: undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o: In function `~Part': /var/tmp/portage/kde-base/korganizer-4.12.3/work/korganizer-4.12.3/korganizer/interfaces/korganizer/part.h:55: undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTIN4KOrg4PartE[_ZTIN4KOrg4PartE]+0x10): undefined reference to `typeinfo for KParts::Part' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x10): undefined reference to `typeinfo for KParts::PartBase' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x18): undefined reference to `KParts::PartBase::~PartBase()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x20): undefined reference to `KParts::PartBase::~PartBase()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x28): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0x30): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&, bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0xb0): undefined reference to `typeinfo for KParts::PartBase' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0xb8): undefined reference to `virtual thunk to KParts::PartBase::~PartBase()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0xc0): undefined reference to `virtual thunk to KParts::PartBase::~PartBase()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE16_N6KParts8PartBaseE[_ZTVN4KOrg4PartE]+0xf8): undefined reference to `virtual thunk to KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x10): undefined reference to `typeinfo for KParts::Part' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x18): undefined reference to `KParts::Part::metaObject() const' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x20): undefined reference to `KParts::Part::qt_metacast(char const*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x28): undefined reference to `KParts::Part::qt_metacall(QMetaObject::Call, int, void**)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x30): undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x38): undefined reference to `KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x60): undefined reference to `KParts::Part::customEvent(QEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x78): undefined reference to `KParts::Part::embed(QWidget*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x80): undefined reference to `KParts::Part::widget()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x88): undefined reference to `KParts::Part::setManager(KParts::PartManager*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x90): undefined reference to `KParts::Part::hitTest(QWidget*, QPoint const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x98): undefined reference to `KParts::Part::setSelectable(bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xa0): undefined reference to `KParts::Part::setWidget(QWidget*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xa8): undefined reference to `KParts::Part::partActivateEvent(KParts::PartActivateEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xb0): undefined reference to `KParts::Part::partSelectEvent(KParts::PartSelectEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xb8): undefined reference to `KParts::Part::guiActivateEvent(KParts::GUIActivateEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xd0): undefined reference to `typeinfo for KParts::Part' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xd8): undefined reference to `non-virtual thunk to KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xe0): undefined reference to `non-virtual thunk to KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xe8): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0xf0): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&, bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x170): undefined reference to `typeinfo for KParts::Part' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x178): undefined reference to `virtual thunk to KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x180): undefined reference to `virtual thunk to KParts::Part::~Part()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTCN4KOrg4PartE0_N6KParts4PartE[_ZTVN4KOrg4PartE]+0x1b8): undefined reference to `virtual thunk to KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x18): undefined reference to `KParts::Part::metaObject() const' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x20): undefined reference to `KParts::Part::qt_metacast(char const*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x28): undefined reference to `KParts::Part::qt_metacall(QMetaObject::Call, int, void**)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x60): undefined reference to `KParts::Part::customEvent(QEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x78): undefined reference to `KParts::Part::embed(QWidget*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x80): undefined reference to `KParts::Part::widget()' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x88): undefined reference to `KParts::Part::setManager(KParts::PartManager*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x90): undefined reference to `KParts::Part::hitTest(QWidget*, QPoint const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x98): undefined reference to `KParts::Part::setSelectable(bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xa0): undefined reference to `KParts::Part::setWidget(QWidget*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xa8): undefined reference to `KParts::Part::partActivateEvent(KParts::PartActivateEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xb0): undefined reference to `KParts::Part::partSelectEvent(KParts::PartSelectEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xb8): undefined reference to `KParts::Part::guiActivateEvent(KParts::GUIActivateEvent*)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0xf8): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x100): undefined reference to `KParts::PartBase::setComponentData(KComponentData const&, bool)' CMakeFiles/korganizer_core.dir/kocore.o:(.data.rel.ro._ZTVN4KOrg4PartE[_ZTVN4KOrg4PartE]+0x1c8): undefined reference to `virtual thunk to KParts::PartBase::setComponentData(KComponentData const&)' collect2: error: ld returned 1 exit status korganizer/CMakeFiles/korganizer_core.dir/build.make:211: recipe for target 'lib/libkorganizer_core.so.4.12.3' failed make[2]: *** [lib/libkorganizer_core.so.4.12.3] Error 1 make[2]: Leaving directory '/var/tmp/portage/kde-base/korganizer-4.12.3/work/korganizer-4.12.3_build' CMakeFiles/Makefile2:965: recipe for target 'korganizer/CMakeFiles/korganizer_core.dir/all' failed make[1]: *** [korganizer/CMakeFiles/korganizer_core.dir/all] Error 2 make[1]: Leaving directory '/var/tmp/portage/kde-base/korganizer-4.12.3/work/korganizer-4.12.3_build' Makefile:126: recipe for target 'all' failed make: *** [all] Error 2 * ERROR: kde-base/korganizer-4.12.3::gentoo failed (compile phase): * emake failed Is this a new re-occurence?
> Is this a new re-occurence? Looks likely: markus@x4 tmp % < test.ii template <typename T> class A { public: A (T &); typename T::const_iterator i; }; template <typename T> class B { public: class const_iterator { public: T &operator*(); }; }; namespace KParts { class PartBase { public: virtual ~PartBase (); }; class Part : PartBase { }; } class Part : KParts::Part { public: typedef B<Part *> List; ~Part () {} }; void fn1 (Part::List &p1) { for (A<__typeof__ p1> a (p1);;) for (Part *b = *a.i;;) delete b; } markus@x4 tmp % g++ -Wall -Wextra -c -O2 test.ii markus@x4 tmp % nm test.o | c++filt 0000000000000000 T fn1(B<Part*>&) U operator delete(void*) U A<B<Part*> >::A(B<Part*>&) U B<Part*>::const_iterator::operator*() 0000000000000000 W Part::~Part() 0000000000000000 W Part::~Part() 0000000000000000 W Part::~Part() 0000000000000000 n Part::~Part() 0000000000000000 W KParts::Part::~Part() 0000000000000000 W KParts::Part::~Part() 0000000000000000 W KParts::Part::~Part() 0000000000000000 n KParts::Part::~Part() U KParts::PartBase::~PartBase() 0000000000000000 V typeinfo for KParts::Part U typeinfo for KParts::PartBase 0000000000000000 V typeinfo name for KParts::Part U vtable for __cxxabiv1::__vmi_class_type_info 0000000000000000 V vtable for KParts::Part markus@x4 tmp % /usr/x86_64-pc-linux-gnu/gcc-bin/4.8.3/g++ -Wall -Wextra -c -O2 test.ii markus@x4 tmp % nm test.o | c++filt 0000000000000000 T fn1(B<Part*>&) U A<B<Part*> >::A(B<Part*>&) U B<Part*>::const_iterator::operator*() markus@x4 tmp %
Created attachment 32272 [details] Unreduced testcase Here's the unreduced testcase: markus@x4 tmp % g++ -Wall -Wextra -c -O2 test.ii markus@x4 tmp % nm test.o | c++filt | grep KPart U KParts::Part::setManager(KParts::PartManager*) U KParts::Part::customEvent(QEvent*) U KParts::Part::qt_metacall(QMetaObject::Call, int, void**) U KParts::Part::qt_metacast(char const*) U KParts::Part::setSelectable(bool) U KParts::Part::partSelectEvent(KParts::PartSelectEvent*) U KParts::Part::guiActivateEvent(KParts::GUIActivateEvent*) U KParts::Part::partActivateEvent(KParts::PartActivateEvent*) U KParts::Part::embed(QWidget*) U KParts::Part::widget() U KParts::Part::hitTest(QWidget*, QPoint const&) U KParts::Part::setWidget(QWidget*) U KParts::Part::~Part() U KParts::Part::~Part() U KParts::Part::~Part() U KParts::PartBase::setComponentData(KComponentData const&) U KParts::PartBase::setComponentData(KComponentData const&, bool) U KParts::PartBase::~PartBase() U KParts::PartBase::~PartBase() U KParts::Part::metaObject() const 0000000000000000 V construction vtable for KParts::Part-in-KOrg::Part 0000000000000000 V construction vtable for KParts::PartBase-in-KOrg::Part U non-virtual thunk to KParts::Part::~Part() U non-virtual thunk to KParts::Part::~Part() U typeinfo for KParts::Part U typeinfo for KParts::PartBase U virtual thunk to KParts::Part::~Part() U virtual thunk to KParts::Part::~Part() U virtual thunk to KParts::PartBase::~PartBase() U virtual thunk to KParts::PartBase::~PartBase() U virtual thunk to KParts::PartBase::setComponentData(KComponentData const&)
OK, this testcase wasn't affected by my earlier patch because ~Part is user-defined, so it's fair game for devirtualization. I notice, however, that in the unreduced testcase Part is an abstract class, so it doesn't make sense to choose its destructor for speculative devirtualization: that can never be the right answer. I'll fix that.
Hello Markus, Could you kindly please write here how are you reducing this? (So next time I can try to do it myself.) Thank you in advance.
(In reply to David Kredba from comment #26) > Hello Markus, > Could you kindly please write here how are you reducing this? > > (So next time I can try to do it myself.) Sure. First thing is to find out which object files contains these undefined symbols. cd /var/tmp/portage/kde-base/korganizer-4.12.3 for f in **/*.o ; do echo $f && nm $f | c++filt | grep "KParts::Part::~Part()" ; done This will point to kocore.o. Then lookup how kocore.o was compiled in the build.log. Add --save-temps to the invocation. Write a check.sh script for creduce, e.g. something like: % cat check.sh #!/bin/sh /usr/x86_64-pc-linux-gnu/gcc-bin/4.8.3/g++ -Wall -Wextra -c -O2 -Werror -Wfatal-errors -c test.ii -pipe if ! test $? = 0; then exit 1 fi nm test.o | grep _ZN6KParts4PartD0Ev if test $? = 0; then exit 1 fi g++ -Wall -Wextra -c -O2 -Werror -Wfatal-errors test.ii -pipe if ! test $? = 0; then exit 1 fi nm test.o | grep _ZN6KParts4PartD0Ev if ! test $? = 0; then exit 1 fi And finally run creduce.
Created attachment 32279 [details] New patch Does this fix KDE?
(In reply to Jason Merrill from comment #28) > Created attachment 32279 [details] > New patch > > Does this fix KDE? Yes. Thanks Jason.
Honza was going to make some adjustments to my patch.
Calligra-2.8.0 is now affected too with revision /var/tmp/portage/app-office/calligra-2.8.0/temp/ccAMiINB.ltrans1.ltrans.o: In function `operator<': /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/temp/ccAMiINB.ltrans1.ltrans.o: In function `qMapLessThanKey': /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/temp/ccAMiINB.ltrans1.ltrans.o: In function `operator<': /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/temp/ccAMiINB.ltrans1.ltrans.o:/var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: more undefined references to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' follow collect2: error: ld returned 1 exit status sheets/CMakeFiles/calligrasheetscommon.dir/build.make:3104: recipe for target 'lib/libcalligrasheetscommon.so.13.0.0' failed
208516
Author: jason Date: Fri Mar 14 19:06:54 2014 New Revision: 208573 URL: http://gcc.gnu.org/viewcvs?rev=208573&root=gcc&view=rev Log: PR c++/58678 * search.c (dfs_get_pure_virtuals): Treat the destructor of an abstract class as pure. Added: trunk/gcc/testsuite/g++.dg/ipa/devirt-30.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/search.c
(In reply to David Kredba from comment #31) > Calligra-2.8.0 is now affected too Does the patch I just checked in fix Calligra? If not, please reopen the bug with a testcase.
Author: jason Date: Sat Mar 15 01:39:03 2014 New Revision: 208586 URL: http://gcc.gnu.org/viewcvs?rev=208586&root=gcc&view=rev Log: PR c++/60532 PR c++/58678 * search.c (get_pure_virtuals): Handle abstract dtor here. (dfs_get_pure_virtuals): Not here. Added: trunk/gcc/testsuite/g++.dg/other/abstract6.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/search.c
I did not: /var/tmp/portage/app-office/calligra-2.8.0/temp/ccv1d4Ui.ltrans1.ltrans.o: In function `operator<': /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/temp/ccv1d4Ui.ltrans1.ltrans.o: In function `qMapLessThanKey': /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/temp/ccv1d4Ui.ltrans1.ltrans.o: In function `operator<': /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: undefined reference to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' /var/tmp/portage/app-office/calligra-2.8.0/temp/ccv1d4Ui.ltrans1.ltrans.o:/var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/sheets/Condition.h:170: more undefined references to `Calligra::Sheets::qHash(Calligra::Sheets::Conditions const&)' follow collect2: error: ld returned 1 exit status sheets/CMakeFiles/calligrasheetscommon.dir/build.make:3104: recipe for target 'lib/libcalligrasheetscommon.so.13.0.0' failed trunk revision 208592 I am sorry I do not know how to reduce it.
(In reply to David Kredba from comment #36) > I am sorry I do not know how to reduce it. You don't need to reduce it. Try building without LTO and with -save-temps, and send me the .i output for the file with the unresolved symbol errors.
Created attachment 32363 [details] Unreduced test case from calligra
Hello Markus, Thank you. Without LTO the reference is different, maybe qHash would be the next one error. MakeFiles/kritametadataeditor.dir/kis_meta_data_editor.cc.o: In function `KisMetaDataEditor::KisMetaDataEditor(QWidget*, KisMetaData::Store*)': /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/extensions/metadataeditor/kis_meta_data_editor.cc:79: undefined reference to `QUiLoader::QUiLoader(QObject*)' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/extensions/metadataeditor/kis_meta_data_editor.cc:82: undefined reference to `QUiLoader::load(QIODevice*, QWidget*)' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/extensions/metadataeditor/kis_meta_data_editor.cc:85: undefined reference to `QUiLoader::~QUiLoader()' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/extensions/metadataeditor/kis_meta_data_editor.cc:79: undefined reference to `QUiLoader::~QUiLoader()' collect2: error: ld returned 1 exit status krita/plugins/extensions/metadataeditor/CMakeFiles/kritametadataeditor.dir/build.make:229: recipe for target 'lib/kritametadataeditor.so' failed It wanted to link this way: /usr/bin/x86_64-pc-linux-gnu-g++ -fPIC -flto=4 -fuse-linker-plugin -O2 -ggdb -pipe -march=native -mtune=native -mno-3dnow -mno-sse4.2 -mno-avx -fno-lto -fno-use-linker-plugin -Wnon-virtual-dtor -Wno-long-long -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-exceptions -DQT_NO_EXCEPTIONS -fno-check-new -fno-common -Woverloaded-virtual -fno-threadsafe-statics -fvisibility=hidden -fvisibility-inlines-hidden -march=core2 -msse2 -msse3 -mssse3 -msse4.1 -mno-sse4.2 -mno-sse4a -mno-avx -mno-xop -mno-fma4 -Wabi -fabi-version=0 -ffp-contract=fast -fexceptions -UQT_NO_EXCEPTIONS -Wl,--enable-new-dtags -Wl,--no-undefined -lc -flto=4 -fuse-linker-plugin -Wl,--as-needed -Wl,-O2 -Wl,-flto -O2 -ggdb -pipe -march=native -mtune=native -mno-3dnow -mno-sse4.2 -mno-avx -fno-lto -fno-use-linker-plugin -shared -Wl,-soname,kritametadataeditor.so -o ../../../../lib/kritametadataeditor.so CMakeFiles/kritametadataeditor.dir/kritametadataeditor_automoc.cpp.o CMakeFiles/kritametadataeditor.dir/metadataeditor.cc.o CMakeFiles/kritametadataeditor.dir/kis_entry_editor.cc.o CMakeFiles/kritametadataeditor.dir/kis_meta_data_editor.cc.o CMakeFiles/kritametadataeditor.dir/kis_meta_data_model.cpp.o -L/var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0_build/lib -L/usr/lib64/qt4 ../../../../lib/libkritaui.so.13.0.0 /usr/lib64/qt4/libQtUiTools.a ../../../../lib/libkritaimage.so.13.0.0 ../../../../lib/libkomain.so.13.0.0 /usr/lib64/libkactivities.so.6.2.0 -lGLU -lGL -lSM -lICE -lSM -lICE -lX11 -lXext -lXft -lXau -lXdmcp -lXpm /usr/lib64/qt4/libQtOpenGL.so ../../../../lib/libkowidgets.so.13.0.0 ../../../../lib/libkotext.so.13.0.0 ../../../../lib/libflake.so.13.0.0 ../../../../lib/libpigmentcms.so.13.0.0 ../../../../lib/libkoplugin.so.13.0.0 -lImath -lIlmImf -lIex -lHalf -lIlmThread -Wl,-Bstatic -lVc -Wl,-Bdynamic ../../../../lib/libkundo2.so.13.0.0 ../../../../lib/libkowidgetutils.so.13.0.0 ../../../../lib/libkoodf.so.13.0.0 /usr/lib64/libkio.so.5.12.3 /usr/lib64/qt4/libQtXml.so /usr/lib64/qt4/libQtNetwork.so /usr/lib64/libkdeui.so.5.12.3 /usr/lib64/qt4/libQtGui.so /usr/lib64/qt4/libQtSvg.so /usr/lib64/libkdecore.so.5.12.3 /usr/lib64/qt4/libQtDBus.so /usr/lib64/qt4/libQtCore.so -lpthread -Wl,-rpath,/var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0_build/lib:/usr/lib64/qt4: -Wl,-rpath-link,/var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0_build/lib
David, the Calligra link error from comment 36 and comment 31 are caused by ConditionCommand.cpp.o. With -flto it contains: U _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE Without -flto the undefined symbol is gone. I'm currently reducing this issue.
Created attachment 32364 [details] reduced calligra testcase markus@x4 tmp % g++ -flto -c -O2 test.ii && nm test.o | grep _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE U _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE markus@x4 tmp % g++ -c -O2 test.ii && nm test.o | grep _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE markus@x4 tmp % clang++ -flto -c -O2 test.ii && nm test.o | grep _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE markus@x4 tmp %
This looks like an application issue, when I move: bool operator<(const Conditions& conditions) const { return qHash(*this) < qHash(conditions); } from sheets/Condition.h to sheets/Condition.cpp (where it belongs) Calligra compiles just fine with -flto.
Hello Jason, Thank you. Could you please check uploaded not reduced i file related to my comment #39? As per Markus finding qHash issue is Calligra issue. This is not allowing to build Calligra even without LTO. Thank you in advance.
Hello Markus, I moved it (deleted a three lines) from .h file and placed them to asource file a) beginning of source file after a namespace definition and it failed with: /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' (operand types are 'const Calligra::Sheets::Conditions' and 'const Calligra::Sheets::Conditions') /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' (operand types are 'const Calligra::Sheets::Conditions' and 'const Calligra::Sheets::Conditions') b) before the first occurence of qHash and it failed with: /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' (operand types are 'const Calligra::Sheets::Conditions' and 'const Calligra::Sheets::Conditions') /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' (operand types are 'const Calligra::Sheets::Conditions' and 'const Calligra::Sheets::Conditions') /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' (operand types are 'const Calligra::Sheets::Conditions' and 'const Calligra::Sheets::Conditions') Could you please write me to what line to place it? Thank you in advance.
(In reply to David Kredba from comment #44) > Hello Markus, > I moved it (deleted a three lines) from .h file and placed them to asource > file > a) beginning of source file after a namespace definition and it failed > with: > > /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' > (operand types are 'const Calligra::Sheets::Conditions' and 'const > Calligra::Sheets::Conditions') > /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' > (operand types are 'const Calligra::Sheets::Conditions' and 'const > Calligra::Sheets::Conditions') > > b) before the first occurence of qHash and it failed with: > > /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' > (operand types are 'const Calligra::Sheets::Conditions' and 'const > Calligra::Sheets::Conditions') > /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' > (operand types are 'const Calligra::Sheets::Conditions' and 'const > Calligra::Sheets::Conditions') > /usr/include/qt4/QtCore/qmap.h:107:17: error: no match for 'operator<' > (operand types are 'const Calligra::Sheets::Conditions' and 'const > Calligra::Sheets::Conditions') > > Could you please write me to what line to place it? > > Thank you in advance. You need to keep the declaration in Condition.h: bool operator<(const Conditions& conditions) const; and append the following to Condition.cpp: bool Conditions::operator<(const Conditions& conditions) const { return qHash(*this) < qHash(conditions); } But this is getting way off-topic.
BTW, kdepim that failed to compile (no -flto) compiles just fine with r208586.
(In reply to Markus Trippelsdorf from comment #41) > markus@x4 tmp % g++ -flto -c -O2 test.ii && nm test.o | grep > _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE > U _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE I can't reproduce this with r208621, has it been fixed? I'm taking a look at comment 38.
(In reply to Jason Merrill from comment #47) > (In reply to Markus Trippelsdorf from comment #41) > > markus@x4 tmp % g++ -flto -c -O2 test.ii && nm test.o | grep > > _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE > > U _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE > > I can't reproduce this with r208621, has it been fixed? (r208621:) markus@x4 /tmp % /var/tmp/gcc_test/usr/local/bin/g++ -v Using built-in specs. COLLECT_GCC=/var/tmp/gcc_test/usr/local/bin/g++ COLLECT_LTO_WRAPPER=/var/tmp/gcc_test/usr/local/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.9.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ../gcc/configure --enable-checking=release --disable-bootstrap --disable-libvtv --disable-libitm --disable-libcilkrts --disable-libssp --disable-libgomp --disable-werror --disable-multilib --enable-languages=c,c++ Thread model: posix gcc version 4.9.0 20140317 (experimental) (GCC) markus@x4 /tmp % /var/tmp/gcc_test/usr/local/bin/g++ -flto -c -O2 test.ii && nm test.o | grep _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE U _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE
I am still getting this with revision 208612 without -flto: CMakeFiles/kritametadataeditor.dir/kis_meta_data_editor.cc.o: In function `KisMetaDataEditor::KisMetaDataEditor(QWidget*, KisMetaData::Store*)': /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/extensions/metadataeditor/kis_meta_data_editor.cc:79: undefined reference to `QUiLoader::QUiLoader(QObject*)' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/extensions/metadataeditor/kis_meta_data_editor.cc:82: undefined reference to `QUiLoader::load(QIODevice*, QWidget*)' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/extensions/metadataeditor/kis_meta_data_editor.cc:85: undefined reference to `QUiLoader::~QUiLoader()' /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/extensions/metadataeditor/kis_meta_data_editor.cc:79: undefined reference to `QUiLoader::~QUiLoader()' collect2: error: ld returned 1 exit status And I was not able to follow Markus's instructions about how to get it working with -flto by copying that "qHash 3 row" from .h to .cpp. Thank you.
(In reply to David Kredba from comment #39) > MakeFiles/kritametadataeditor.dir/kis_meta_data_editor.cc.o: In function > `KisMetaDataEditor::KisMetaDataEditor(QWidget*, KisMetaData::Store*)': > /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/ > extensions/metadataeditor/kis_meta_data_editor.cc:79: undefined reference to > `QUiLoader::QUiLoader(QObject*)' > /var/tmp/portage/app-office/calligra-2.8.0/work/calligra-2.8.0/krita/plugins/ > extensions/metadataeditor/kis_meta_data_editor.cc:82: undefined reference to > `QUiLoader::load(QIODevice*, QWidget*)' I don't see how devirt could be causing this; the KisMetDataEditor constructor does indeed create a QUiLoader and call load on it, and neither of those calls are virtual. I think this is a problem with the link command.
(In reply to Markus Trippelsdorf from comment #48) > markus@x4 /tmp % /var/tmp/gcc_test/usr/local/bin/g++ -flto -c -O2 test.ii && > nm test.o | grep _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE > U _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE Strange. # ggcc -c -flto wa.C -O2 -v && nm wa.o ... GNU C++ (GCC) version 4.9.0 20140317 (experimental) (x86_64-unknown-linux-gnu) ... 0000000000000001 C __gnu_lto_slim 0000000000000001 C __gnu_lto_v1 It seems GCC is defaulting to fat LTO objects for you, but not for me; I guess that's because my system linker supports the LTO plugin. But even compiling with -ffat-lto-objects doesn't reproduce the problem; with that option nm shows 0000000000000001 C __gnu_lto_v1 U _ZN1BIiE14const_iteratorneES1_ U _ZN8Calligra6Sheets1G5m_fn1Ev 0000000000000000 T _ZN8Calligra6Sheets1H5m_fn1Ev U _ZNK8Calligra6Sheets1H5m_fn2Ev U _ZNK8Calligra6Sheets1H5m_fn3Ev And -fdump-ipa-devirt shows that we aren't speculatively devirtualizing a call to ~J because it's an artificial destructor, so it seems to have been fixed by r208241. What does -fdump-ipa-devirt say for you?
(In reply to Jason Merrill from comment #51) > (In reply to Markus Trippelsdorf from comment #48) > > markus@x4 /tmp % /var/tmp/gcc_test/usr/local/bin/g++ -flto -c -O2 test.ii && > > nm test.o | grep _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE > > U _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE > > Strange. > > # ggcc -c -flto wa.C -O2 -v && nm wa.o > ... > GNU C++ (GCC) version 4.9.0 20140317 (experimental) > (x86_64-unknown-linux-gnu) > ... > 0000000000000001 C __gnu_lto_slim > 0000000000000001 C __gnu_lto_v1 > > It seems GCC is defaulting to fat LTO objects for you, but not for me; I > guess that's because my system linker supports the LTO plugin. > > But even compiling with -ffat-lto-objects doesn't reproduce the problem; > with that option nm shows > > 0000000000000001 C __gnu_lto_v1 > U _ZN1BIiE14const_iteratorneES1_ > U _ZN8Calligra6Sheets1G5m_fn1Ev > 0000000000000000 T _ZN8Calligra6Sheets1H5m_fn1Ev > U _ZNK8Calligra6Sheets1H5m_fn2Ev > U _ZNK8Calligra6Sheets1H5m_fn3Ev > > And -fdump-ipa-devirt shows that we aren't speculatively devirtualizing a > call to ~J because it's an artificial destructor, so it seems to have been > fixed by r208241. What does -fdump-ipa-devirt say for you? Sorry, I've forgot to mention that my system binutils use the linker plugin by default. So you have to use the gcc wrapper (gcc-nm) to read the lto symbols, like: gcc -c -flto wa.C -O2 -v && gcc-nm wa.o
(In reply to Markus Trippelsdorf from comment #41) > markus@x4 tmp % g++ -flto -c -O2 test.ii && nm test.o | grep > _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE > U _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE > markus@x4 tmp % g++ -c -O2 test.ii && nm test.o | grep > _ZN8Calligra6Sheets5qHashERKNS0_10ConditionsE OK. The reason you're seeing this in gcc-nm output for test.o is that with -flto, in compute_ltrans_boundary we decide to keep any possible targets for late devirtualization. This smaller testcase shows the same thing: void f(); struct A { virtual void g(); }; struct B: A { virtual void g() { f(); } }; void h(A* ap) { ap->g(); } With -flto, this refers to f because we keep B::g around until link time. But then it is discarded at link time if it isn't actually used, so the reference to f goes away. I guess that in the case of libcalligrasheetscommon we do end up needing the definition of whatever function. In any case, I agree with you that this is a bug in Calligra; headers shouldn't contain calls to hidden functions. So I'm inclined to close the bug again.
Agreed.
Author: jason Date: Wed Mar 26 16:50:26 2014 New Revision: 208845 URL: http://gcc.gnu.org/viewcvs?rev=208845&root=gcc&view=rev Log: PR c++/60566 PR c++/58678 * class.c (build_vtbl_initializer): Handle abstract dtors here. * search.c (get_pure_virtuals): Not here. Added: trunk/gcc/testsuite/g++.dg/abi/thunk6.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/class.c trunk/gcc/cp/search.c trunk/gcc/ipa-devirt.c trunk/gcc/testsuite/g++.dg/ipa/devirt-21.C trunk/gcc/testsuite/g++.dg/ipa/devirt-23.C
Author: jakub Date: Fri Mar 28 17:17:56 2014 New Revision: 208907 URL: http://gcc.gnu.org/viewcvs?rev=208907&root=gcc&view=rev Log: PR c++/58678 * g++.dg/abi/thunk6.C: Scan assembler for _ZTv0_n32_N1CD1Ev only for lp64 targets and scan for _ZTv0_n16_N1CD1Ev for ilp32 targets. Modified: trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/abi/thunk6.C
I got it again with trunk revision 209048: /usr/bin/x86_64-pc-linux-gnu-g++ -fPIC -flto=4 -fuse-linker-plugin -O2 -ggdb -pipe -march=core2 -mtune=core2 -mno-3dnow -mno-sse4.2 -mno-avx -mno-xop -mno-fma4 -mno-sse4a -Wnon-virtual-dtor -Wno-long-long -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-exceptions -DQT_NO_EXCEPTIONS -fno-check-new -fno-common -Woverloaded-virtual -fno-threadsafe-statics -fvisibility=hidden -fvisibility-inlines-hidden -Wl,--enable-new-dtags -Wl,--no-undefined -lc -flto=4 -fuse-linker-plugin -Wl,--as-needed -Wl,-O2 -Wl,-flto -O2 -ggdb -pipe -march=core2 -mtune=core2 -mno-3dnow -mno-sse4.2 -mno-avx -mno-xop -mno-fma4 -mno-sse4a -shared -Wl,-soname,phonon.so -o lib/phonon.so CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart0.cpp.o CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart1.cpp.o CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart2.cpp.o CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart3.cpp.o CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart4.cpp.o CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart5.cpp.o CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart6.cpp.o CMakeFiles/python_module_PyKDE4_phonon.dir/sip/phonon/sipphononpart7.cpp.o -lpython3.2 -lphonon /usr/lib64/qt4/libQtDBus.so /usr/lib64/qt4/libQtCore.so -lpthread /usr/lib64/qt4/libQtGui.so -Wl,-rpath,/usr/lib64/qt4: /tmp/ccpIV11w.ltrans24.ltrans.o: In function `__base_dtor ': /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' /usr/include/phonon/backendcapabilities.h:57: undefined reference to `vtable for Phonon::BackendCapabilities::Notifier' collect2: error: ld returned 1 exit status And it is sipphononpart5.cpp.o again. I use Markus's binutils patch (now trunk binutils got it too! :-) ) and the only patch more to revision 209048 is the one from Martin Jambor (Simple enhancements to dumping in ipa.c and ipa-cp.c). It fails with python-3.2 only, python 2.7 and 3.3 version looks to be fine. Without LTO it compiles fine. Both binutils' nm and gcc-nm returns: no symbols for /usr/lib64/libphonon.so.4.7.1. But mc (Internal viewer of a Midnight Commander) can se them: 00000000000273f0 T Phonon::BackendCapabilities::notifier() List of vtables inside /usr/lib64/libphonon.so.4.7.1: U vtable for __cxxabiv1::__class_type_info U vtable for __cxxabiv1::__si_class_type_info U vtable for __cxxabiv1::__vmi_class_type_info 000000000026d580 V vtable for Phonon::SeekSlider 000000000026dd80 V vtable for Phonon::AudioOutput 000000000026dc00 V vtable for Phonon::MediaObject 000000000026e0c0 V vtable for Phonon::PulseStream 000000000026cb40 V vtable for Phonon::VideoPlayer 000000000026ce00 V vtable for Phonon::VideoWidget 000000000026c380 V vtable for Phonon::EffectWidget 000000000026c1c0 V vtable for Phonon::GlobalConfig 000000000026e180 V vtable for Phonon::PulseSupport 000000000026d340 V vtable for Phonon::VolumeSlider 000000000026e000 V vtable for Phonon::AudioDataOutput 000000000026c900 V vtable for Phonon::MediaController 000000000026d880 V vtable for Phonon::StreamInterface 000000000026d8c0 V vtable for Phonon::MediaNodePrivate 000000000026db40 V vtable for Phonon::VolumeFaderEffect 000000000026e280 V vtable for Phonon::MediaSourcePrivate 000000000026df00 V vtable for Phonon::AbstractAudioOutput 000000000026e2c0 V vtable for Phonon::AbstractMediaStream 000000000026c780 V vtable for Phonon::AbstractMediaStreamPrivate 000000000026dcc0 V vtable for Phonon::Effect 000000000026dea0 V vtable for Phonon::MediaNode Objdump -t see no symbols, -T see symbols. I rebuild phonon by the same compiler/binutils as pykde4. Could you kindly please check if you are affected too? Thank you in advance.
A gentoo user wrote me that pykde still fails with the same error when build with -flto. And indeed both the testcase from comment0 and from comment 13 still fail with -flto: markus@x4 /tmp % cat test.ii class A { public: virtual ~A(); }; class B : A { virtual int m_fn1(); }; void fn1() { delete reinterpret_cast<B*>(1); } markus@x4 /tmp % cat test2.ii class Part { public: virtual ~Part(); }; class A : Part {}; void fn1() { A *a; delete a; } markus@x4 /tmp % g++ -Wl,--no-undefined -shared -fPIC -flto -O2 test.ii /tmp/ccvkKVlc.ltrans0.ltrans.o:ccvkKVlc.ltrans0.o:function B::~B(): error: undefined reference to 'vtable for B' /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: the vtable symbol may be undefined because the class is missing its key function /tmp/ccvkKVlc.ltrans0.ltrans.o:ccvkKVlc.ltrans0.o:function B::~B(): error: undefined reference to 'A::~A()' /tmp/ccvkKVlc.ltrans0.ltrans.o:ccvkKVlc.ltrans0.o:function B::~B(): error: undefined reference to 'vtable for B' /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: the vtable symbol may be undefined because the class is missing its key function /tmp/ccvkKVlc.ltrans0.ltrans.o:ccvkKVlc.ltrans0.o:function fn1(): error: undefined reference to 'vtable for B' /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/../../../../x86_64-pc-linux-gnu/bin/ld: the vtable symbol may be undefined because the class is missing its key function /tmp/ccvkKVlc.ltrans0.ltrans.o:ccvkKVlc.ltrans0.o:function fn1(): error: undefined reference to 'A::~A()' /tmp/ccvkKVlc.ltrans0.ltrans.o:ccvkKVlc.ltrans0.o:function B::~B(): error: undefined reference to 'A::~A()' collect2: error: ld returned 1 exit status markus@x4 /tmp % g++ -Wl,--no-undefined -shared -fPIC -flto -O2 test2.ii /tmp/ccY0KXU2.ltrans0.ltrans.o:ccY0KXU2.ltrans0.o:function A::~A(): error: undefined reference to 'Part::~Part()' /tmp/ccY0KXU2.ltrans0.ltrans.o:ccY0KXU2.ltrans0.o:function A::~A(): error: undefined reference to 'Part::~Part()' /tmp/ccY0KXU2.ltrans0.ltrans.o:ccY0KXU2.ltrans0.o:typeinfo for A: error: undefined reference to 'typeinfo for Part' collect2: error: ld returned 1 exit status markus@x4 /tmp % g++ -Wl,--no-undefined -shared -fPIC -O2 test.ii markus@x4 /tmp % g++ -Wl,--no-undefined -shared -fPIC -O2 test2.ii markus@x4 /tmp %
(In reply to Markus Trippelsdorf from comment #58) These are breaking with -flto because make_decl_local clears DECL_COMDAT, so the check I added to ipa_devirt doesn't trigger. Honza, can we just remove that from make_decl_local? It seems harmless to me to leave the flag set.
(In reply to Jason Merrill from comment #59) > (In reply to Markus Trippelsdorf from comment #58) > > These are breaking with -flto because make_decl_local clears DECL_COMDAT, so > the check I added to ipa_devirt doesn't trigger. Honza, can we just remove > that from make_decl_local? It seems harmless to me to leave the flag set. For 4.9 this may trigger the assert in gcc/ipa.c: 983 gcc_assert ((!DECL_WEAK (node->decl) 984 && !DECL_COMDAT (node->decl)) 985 || TREE_PUBLIC (node->decl) 986 || node->weakref 987 || DECL_EXTERNAL (node->decl));
Yes, for 4.9 probably better to remove the DECL_COMDAT check from ipa_visibility; there's really no need for it, as all artificial virtuals are implicitly inline and thus would always have DECL_COMDAT set if not for IPA clearing it.
Created attachment 33417 [details] Patch #5 Like so. This patch fixes the bug in both 4.9 and trunk, but only when the linker plugin isn't used. If the linker plugin is used, the resolution file tells LTO to emit ~B even though it isn't used.
Hmm, I've tested the following with 4.9 branch: diff --git a/gcc/ipa.c b/gcc/ipa.c index ebaa82dbfe41..b55b8ccab4ac 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -980,11 +980,6 @@ function_and_variable_visibility (bool whole_program) #endif symtab_dissolve_same_comdat_group_list (node); } - gcc_assert ((!DECL_WEAK (node->decl) - && !DECL_COMDAT (node->decl)) - || TREE_PUBLIC (node->decl) - || node->weakref - || DECL_EXTERNAL (node->decl)); if (cgraph_externally_visible_p (node, whole_program)) { gcc_assert (!node->global.inlined_to); diff --git a/gcc/symtab.c b/gcc/symtab.c index 288821d58ab9..cc2ee0f662b4 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -961,7 +961,6 @@ symtab_make_decl_local (tree decl) if (DECL_ONE_ONLY (decl) || DECL_COMDAT (decl)) { DECL_SECTION_NAME (decl) = 0; - DECL_COMDAT (decl) = 0; } DECL_COMDAT_GROUP (decl) = 0; DECL_WEAK (decl) = 0; and it fixes all issues. I've successfully build pykde4, kdelibs and Firefox.
(In reply to Markus Trippelsdorf from comment #63) I expect my patch will also fix it for you, then.
Honza, does Jason's patch from comment 62 look good to you?
Author: jason Date: Thu Sep 11 12:11:47 2014 New Revision: 215167 URL: https://gcc.gnu.org/viewcvs?rev=215167&root=gcc&view=rev Log: PR c++/58678 * ipa-devirt.c (ipa_devirt): Don't check DECL_COMDAT. Added: branches/gcc-4_9-branch/gcc/testsuite/g++.dg/ipa/devirt-28a.C Modified: branches/gcc-4_9-branch/gcc/ChangeLog branches/gcc-4_9-branch/gcc/ipa-devirt.c
Author: jason Date: Thu Sep 11 12:12:28 2014 New Revision: 215168 URL: https://gcc.gnu.org/viewcvs?rev=215168&root=gcc&view=rev Log: PR c++/58678 * ipa-devirt.c (ipa_devirt): Don't check DECL_COMDAT. Added: trunk/gcc/testsuite/g++.dg/ipa/devirt-28a.C Modified: trunk/gcc/ChangeLog trunk/gcc/ipa-devirt.c
LTO case should be fixed now.