Re: Attention ROOT users: bug in GCC

From: Matthew D. Langston (langston@SLAC.stanford.edu)
Date: Sun Oct 26 1997 - 01:51:24 MEST


Hello Pasha and Fons,

  I'd like to reiterate that this is not a bug in gcc/g++.  Please see
the original thread discussing this problem in the RootTalk Digest at
http://root.cern.ch/root/roottalk/0991.html.

  Pasha originally reported that declaring a function as virtual in a
class definition resulted in the gcc/g++ compiler discarding the
definitions of methods defined inline within the class definition. 
Below I have included a slightly simplified example that demonstrates
Pasha's original problem.

** begin test.cc example **
class A
{
   public:

      int f() { return 1; }
      virtual int vg();
};

int
main()
{
   A a;
   int b = a.f();
}
** end test.cc example **

  Pasha was concerned that he didn't see the definition of `A::f()' in
test.o when he compiled test.cc using the command `g++ -c test.cc':

langston@seto$ g++ -c test.cc
langston@seto$ nm -C test.o
0000002c W A::A(void)
         U A virtual table
         U A::f(void)
00000000 t gcc2_compiled.
00000000 T main

  Pasha is certainly correct that `test.o' does not contain the assembly
code for `A::f()' (as evidenced in the output of `nm -C test.o' above by
the `U' to the left of the symbol `A::f(void)').  However, this is
because `test.o' *should not* contain the definition of *any* member
functions of `class A' (unless optimization is turned on - see
http://root.cern.ch/root/roottalk/0995.html for why this is so).

  The reason that `test.o' does not contain the definition for `A::f()'
is because `class A' is an incomplete type since `A::vg()' is
undefined.  Had `A::vg()' been defined in `test.cc' (go ahead and try
this yourself) then `class A' would have been completely defined and the
compiler would have emitted all of the assembly code concerning `class
A' into `test.o'.

  This reason that g++ behaves in this way is a good thing, otherwise
some information will be duplicated in each object file that includes
the class definition of `class A' (backup copies of inline member
functions, compiler generated constructors, debugging information, the
internal tables that implement virtual functions, etc.).
 
  This is a common problem for C++ compilers (not just g++).  The method
that the GNU C developers chose to solve this problem was to emit the
definitions of inline member function in the same translation unit where
the classes vtable is emitted.  According to the GNU C manual:  "...if a
class has any non-inline virtual functions, the vtable will be emitted
in the translation unit containing the first one of those.".

  Therefore, in our `test.cc' example, the definition of `A::f()' will
be emitted in the same translation unit where `A::vg()' is defined. 
Since Pasha never defined the virtual member function is his original
example, the definition for `A::f()' was silently discarded.

  In the "old" days of g++ (specifically the 2.6.x series), the GNU C
developers gave us the `interface' and `implementation' pragmas to help
us solve the problem of duplicating compiler generated class information
in multiple `.o' files (these pragmas are what Pasha referred to in his
response below).  These pragmas aren't used that much anymore, and
certainly not in the common case as exemplified by our `test.cc' example
above.  Although one *could* use the `#pragma interface/implementation'
method to solve this common problem, `pramgas' are generally considered
evil and not to be used unless absolutely necessary - at best, pragmas
are non-portable.  Rather than duplicating that information here, I'll
refer the interested reader to the section `C++ Interface' in the GNU C
manual.

--
Matthew D. Langston
Stanford Linear Accelerator Center
langston@SLAC.Stanford.EDU
(650)926-3279


Pasha Murat wrote:
> 
> Fons Rademakers writes:
>  > Hi Pasha,
>  >
>  >    what is the status of this g++ bug? I use g++ all the time in
>  > -g and -O mode without problems. Does the bug persist when you
>  > remove the (redundant) inline keyword? I never use "inline" for
>  > implicit inline functions (maybe thereby avoiding this problem
>  > which shows only in that case).
>  >
>  > Cheers, Fons.
>  >
> --------------------------------------------------------------------------------
>         Hi Fons,
> 
> It doesn't matter whether or not word "inline" is present - problem still
> persists. Jarek Grebieszkow (a lot of thanks to him!) posted to ROOTTALK a
> workaround. I just repeat what he said once again: if each include file
> starts from
> 
> #ifdef __GNUG_
> #pragma interface
> #endif
> 
> and each source file starts from
> 
> #ifdef __GNUG_
> #pragma implementation
> #endif
> 
> GCC does not "forget" about the inlines in the presence of "virtual" declarations.
> (ifdef jackets used here not to confuse other compilers, essential is the presence
> of pragma's). This solved all my problems. It would also be very interesting to
> figure out why this problem doesn't affect ROOT core distribution.
> 
>                                                         Regards, Pasha



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:26:21 MET