On Tue, Nov 17, 2015 at 1:09 AM, Markus Trippelsdorf <mar...@trippelsdorf.de> wrote: > On 2015.11.16 at 14:18 -0800, Steven Noonan wrote: >> Hi folks, >> >> (I'm not subscribed to the list, so please CC me on all responses.) >> >> This is using GCC 5.2 on Linux x86_64. On a project at work I've found >> that one of our shared libraries refuses to link because of some >> symbol references it shouldn't be making. If I add "-fno-devirtualize >> -fno-devirtualize-speculatively" to the compile flags, the issue goes >> away and everything links/runs fine. The issue does *not* appear on >> GCC 4.8 (which is used by our current production toolchain). >> >> First of all, does anyone have any ideas off the top of their head why >> devirtualization would break like this? >> >> Second, I'm looking for any ideas on how to gather meaningful data to >> submit a useful bug report for this issue. The best idea I've come up >> with so far is to preprocess one of the sources with the incorrect >> references and use 'delta' to reduce it to a minimal preprocessed >> source file that references one of these incorrect symbols. >> Unfortunately this is a sluggish process because such a minimal test >> case would need to compile correctly to an object file -- so "delta" >> is reducing it very slowly. So far I'm down from 11MB preprocessed >> source to 1.1MB preprocessed source after running delta a few times. > > These undefined references are normally user errors. For example, when > you define an inline function, you need to link with the symbols it > uses. > > markus@x4 /tmp % cat main.ii > struct A { > void foo(); > }; > struct B { > A v; > virtual void bar() { v.foo(); } > }; > struct C { > B *w; > void Test() { > if (!w) > return; > while (1) > w->bar(); > } > }; > C a; > int main() { a.Test(); } > > markus@x4 /tmp % g++ -fno-devirtualize -O2 -Wl,--no-undefined main.ii > markus@x4 /tmp % g++ -O2 -Wl,--no-undefined main.ii > /tmp/ccEvh2dL.o:main.ii:function B::bar(): error: undefined reference to > 'A::foo()' > /tmp/ccEvh2dL.o:main.ii:function main: error: undefined reference to > 'A::foo()' > collect2: error: ld returned 1 exit status > > Instead of using delta you could try creduce instead. It is normally > much quicker: > > https://github.com/csmith-project/creduce >
creduce did make a much smaller test case, and it's actually sort of readable. I'm not sure that I selected for the right criteria in my test script though. It appears to exhibit the negative behavior we're observing at least. --- namespace panorama { class A { public: virtual int *AccessIUIStyle() = 0; }; class CUIPanel : A { int *AccessIUIStyle() { return AccessStyle(); } int *AccessStyle() const; }; class B { float GetSplitterPosition(); A *m_pIUIPanel; }; } using namespace panorama; float B::GetSplitterPosition() { m_pIUIPanel->AccessIUIStyle(); return 0.0f; } --- The test case is very different from the code it came from (e.g. Access*Style functions weren't returning int pointers before, and the results were actually used at the GetSplitterPosition call site). But I only selected for the undefined symbols in the 'nm' output. Might need to refine the test script a bit more, but I would need to really think about how... Bad: $ gcc -O3 -c debugger1.ii; nm debugger1.o 0000000000000000 T _ZN8panorama1B19GetSplitterPositionEv 0000000000000000 W _ZN8panorama8CUIPanel14AccessIUIStyleEv U _ZNK8panorama8CUIPanel11AccessStyleEv Good: $ gcc -O3 -fno-devirtualize -fno-devirtualize-speculatively -c debugger1.ii; nm debugger1.o 0000000000000000 T _ZN8panorama1B19GetSplitterPositionEv $ clang -O3 -c debugger1.ii; nm debugger1.o 0000000000000000 T _ZN8panorama1B19GetSplitterPositionEv $ gcc --version gcc (GCC) 5.2.0 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ clang --version clang version 3.7.0 (tags/RELEASE_370/final) Target: x86_64-unknown-linux-gnu Thread model: posix