With the attached unreduced testcase I get: markus@x4 /tmp % g++ -flto -O2 foo.ii 2>&1 | grep "VideoBuffers::StartDisplayingFrame" markus@x4 /tmp % g++ -fno-devirtualize-speculatively -O2 foo.ii 2>&1 | grep "VideoBuffers::StartDisplayingFrame" markus@x4 /tmp % g++ -O2 foo.ii 2>&1 | grep "VideoBuffers::StartDisplayingFrame" /tmp/ccEenHoO.o:main.cpp:function VideoOutput::StartDisplayingFrame(): error: undefined reference to 'VideoBuffers::StartDisplayingFrame()' /tmp/ccEenHoO.o:main.cpp:function VideoPerformanceTest::Test(): error: undefined reference to 'VideoBuffers::StartDisplayingFrame()' Creduce came up with the following (invalid) testcase: % cat main.ii struct VideoBuffers { void StartDisplayingFrame (); }; struct B { VideoBuffers vbuffers; virtual void StartDisplay () { vbuffers.StartDisplayingFrame (); } }; struct VideoPerformanceTest { B *Test_vo; void Test () { while (1) Test_vo->StartDisplay (); } }; % g++ -fno-devirtualize-speculatively -O2 -Wl,--no-undefined main.ii % g++ -flto -O2 -Wl,--no-undefined main.ii % g++ -O2 -Wl,--no-undefined main.ii /tmp/ccTlyhda.o:main.ii:function B::StartDisplay(): error: undefined reference to 'VideoBuffers::StartDisplayingFrame()' /tmp/ccTlyhda.o:main.ii:function main: error: undefined reference to 'VideoBuffers::StartDisplayingFrame()'
Created attachment 33888 [details] unreduced testcase
Sorry reduced testcase was cut off. Here it is in its full glory: struct VideoBuffers { void StartDisplayingFrame (); }; struct B { VideoBuffers vbuffers; virtual void StartDisplay () { vbuffers.StartDisplayingFrame (); } }; struct VideoPerformanceTest { B *Test_vo; void Test () { while (1) Test_vo->StartDisplay (); } }; VideoPerformanceTest a; int main () { a.Test (); }
And here's a hopefully valid testcase: markus@x4 tmp % cat main.ii struct VideoBuffers { void StartDisplayingFrame (); }; struct B { VideoBuffers vbuffers; virtual void StartDisplay () { vbuffers.StartDisplayingFrame (); } }; struct VideoPerformanceTest { B *Test_vo; void Test () { if (!Test_vo) return; while (1) Test_vo->StartDisplay (); } }; VideoPerformanceTest a; int main () { a.Test (); }
> struct VideoBuffers > { > void StartDisplayingFrame (); > }; > struct B > { > VideoBuffers vbuffers; > virtual void > StartDisplay () > { > vbuffers.StartDisplayingFrame (); > } So we devirtualize to StartDisplay but that leads to linker failure because StartDisplayingFrame is not linked with the object file. I think this is similar to some earlier testcases we run across in libreoffice and we managed to declare it invalid - if you provide inline function body you need to link the unit with symbols it uses. Honza
(In reply to Jan Hubicka from comment #4) > > struct VideoBuffers > > { > > void StartDisplayingFrame (); > > }; > > struct B > > { > > VideoBuffers vbuffers; > > virtual void > > StartDisplay () > > { > > vbuffers.StartDisplayingFrame (); > > } > So we devirtualize to StartDisplay but that leads to linker failure because > StartDisplayingFrame is not linked with the object file. > > I think this is similar to some earlier testcases we run across in > libreoffice > and we managed to declare it invalid - if you provide inline function body > you > need to link the unit with symbols it uses. OK. That was my fist reaction, too. But it is irritating that it succeeds with -flto.