This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Devirtualization causing undefined symbol references at link?


On 2015.11.23 at 11:11 -0800, Steven Noonan wrote:
> On Tue, Nov 17, 2015 at 1:09 AM, Markus Trippelsdorf
> <markus@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;
> }

Yes. It is the same issue that I've pointed out in my example above.
You need to either link with the object file that provides the
_ZNK8panorama8CUIPanel11AccessStyleEv symbol. Or move the definition of 
panorama::CUIPanel::AccessIUIStyle() to the file that defines
panorama::CUIPanel::AccessStyle().

-- 
Markus


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]