GCC 8.3.0, -flto and violation of C++ One Definition Rule

Jonathan Wakely jwakely.gcc@gmail.com
Wed Dec 29 19:36:33 GMT 2021


On Wed, 29 Dec 2021, 18:18 Tom Kacvinsky, <tkacvins@gmail.com> wrote:

> On Wed, Dec 29, 2021 at 12:04 PM Jonathan Wakely <jwakely.gcc@gmail.com>
> wrote:
> >
> > On Wed, 29 Dec 2021 at 17:01, Jonathan Wakely wrote:
> > >
> > > On Wed, 29 Dec 2021 at 16:16, Tom Kacvinsky <tkacvins@gmail.com>
> wrote:
> > > >
> > > > On Wed, Dec 29, 2021 at 10:39 AM Jonathan Wakely <
> jwakely.gcc@gmail.com> wrote:
> > > > >
> > > > >
> > > > >
> > > > > On Wed, 29 Dec 2021, 11:45 Tom Kacvinsky via Gcc-help, <
> gcc-help@gcc.gnu.org> wrote:
> > > > >>
> > > > >> Hi,
> > > > >>
> > > > >> First, using GCC 8.3.0 and binutils 2.37.I am trying to increase
> > > > >> performance of linking our product, so I thought I'd give LTO a
> try.  So
> > > > >> I am compiling all object files with -flto, and passing -flto to
> g++
> > > > >> (which we use as our link driver).  However, what I have found is
> that
> > > > >> some of our code violates the C++ One Definition Rule
> (-Werror=odr). This
> > > > >> only happens when building with LTO - without LTO, the C++ rule is
> > > > >> not violated.
> > > > >
> > > > >
> > > > > As already explained, this is almost certainly wrong. It is more
> likely that the LTO violation is always present, but only detected when
> using LTO.
> > > > >
> > > > >
> > > > >>   The problem exists with LTO using both the BFD and gold
> > > > >> linkers.
> > > > >>
> > > > >> So, my question is, since the LTO object files are now such that
> one
> > > > >> needs to use gcc-nm to examine them (which I know is a wrapper
> around nm,
> > > > >> and passes an option to load the LTO plugin). how can I leverage
> that to
> > > > >> see if there are other translation units that define the class
> that ODR
> > > > >> violation is complaining about?  I did do a fairly thorough
> analysis of
> > > > >> the object files and did not see there the particular class and
> methods
> > > > >> would be multiply defined,
> > > > >
> > > > >
> > > > > It would help if you tell us the actual error/warning you get.
> -Wodr can warn about various different things. It does not warn about
> multiple definitions, it warns about *inconsistent* definitions.
> > > > >
> > > >
> > > > This is long.  Not sure of the attachment fule for this, so I am
> > > > pasting it in email.  Ib obfuscated the actual source file
> > > > names, but this is the general gist of the link error.  I wonder if
> > > > the error is coming from boost::python::api::object.
> > > >
> > > > /home/home/tkacvins/project/libbar/include/Bar.h:38:7: error: type
> > > > ‘struct Bar’ violates the C++ One Definition Rule [-Werror=odr]
> > >
> > > You said it was defined in one C++ file, but it's clearly defined in a
> > > header. So the problem is that the definition is different in
> > > different translation units.
> > >
> > >
> > >
> > > >  class Bar {
> > > >        ^
> > > > /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: a
> > > > different type is defined in another translation unit
> > > >  class Bar {
> > > >        ^
> > > > /home/home/tkacvins/project/libbar/include/Bar.h:40:32: note: the
> > > > first difference of corresponding definitions is field ‘api’
> > > >          boost::python::object* api;
> > > >                                 ^
> > > > /home/home/tkacvins/project/libbar/include/Bar.h:40:32: note: a field
> > > > of same name but different type is defined in another translation
> unit
> > > >          boost::python::object* api;
> > > >                                 ^
> > > > /home/home/tkacvins/project/libbar/include/Bar.h:15:11: note: type
> > > > name ‘boost::python::object’ should match type name
> > > > ‘boost::python::api::object’
> > > >      class object;
> > > >            ^
> > > >
> /home/BUILD64/lib/boost-1.69.0-py39-1/include/boost/python/object_core.hpp:238:9:
> > > > note: the incompatible type is defined here
> > > >    class object : public object_base
> > > >          ^
> > >
> > > As it says, one definition has a member of type
> > > ‘boost::python::object’ and another has a member of type
> > > ‘boost::python::api::object’. I have two guesses how that could
> > > happen: either you're compiling with two different versions of boost
> > > (which seems unlikely because I think boost::python::api::object has
> > > been in that namespace for 20 years), or you are using a forward
> > > declaration of boost::python::object in your own files, instead of
> > > including the correct boost header to define it properly.
> > >
> > > The most likely explanation is that somebody tried to "optimize" the
> > > build by cheating, and not including the right boost header for the
> > > type.
> >
> > Including <boost/python/object_fwd.hpp> would be the correct way to do
> that.
>
> OK, I'll try that.  What we had done is some hackery with boost/python.hpp
> being
> include in the C++ file and not the header (with the header in essence
> "forward
> declaring" the boost namespace.



So exactly what I guessed from the error messages :-)

There is no need to debug the LTO objects, just read the errors.

If you really *must* play games like this, you need to do it correctly.
Declare the type in the correct namespace (as the object_fwd.hpp header
does).


More information about the Gcc-help mailing list