* GCC 8.3.0, -flto and violation of C++ One Definition Rule @ 2021-12-29 11:44 Tom Kacvinsky 2021-12-29 12:55 ` Xi Ruoyao 2021-12-29 15:38 ` Jonathan Wakely 0 siblings, 2 replies; 9+ messages in thread From: Tom Kacvinsky @ 2021-12-29 11:44 UTC (permalink / raw) To: gcc-help 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. 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, but that was just based on symbol names from gcc-nm output. I suspect there is more to this since the object files have LTO information now, and that is what I'd like to examine. Any hints on how to move forward with diagnosing LTO link errors? Thanks, Tom ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GCC 8.3.0, -flto and violation of C++ One Definition Rule 2021-12-29 11:44 GCC 8.3.0, -flto and violation of C++ One Definition Rule Tom Kacvinsky @ 2021-12-29 12:55 ` Xi Ruoyao 2021-12-29 13:34 ` Tom Kacvinsky 2021-12-29 15:38 ` Jonathan Wakely 1 sibling, 1 reply; 9+ messages in thread From: Xi Ruoyao @ 2021-12-29 12:55 UTC (permalink / raw) To: Tom Kacvinsky, gcc-help On Wed, 2021-12-29 at 06:44 -0500, Tom Kacvinsky via Gcc-help 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. No, it's violated all the time. -Wodr only works with LTO because it's impossible to detect ODR volations (across multiple TUs) just by linking normal (non-LTO) object files. > 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, but that was just based on symbol names from > gcc-nm output. Generally you can't find ODR violations this way. ODR violation does not mean multiple definitions of a symbol. For example: // in 1.cpp enum A { a = 1, }; // in 2.cpp enum A { a = 2, }; If you link the objects compiled from these TUs together, you will violate ODR. But these TUs won't produce any symbols for A or A::a at all. > I suspect there is more to this since the object files > have LTO information now, and that is what I'd like to examine. > > Any hints on how to move forward with diagnosing LTO link errors? With GCC-11, the diagnostic shows the exact location of ODR violation, like: > t-1.cc:1:6: warning: type 'A' violates the C++ One Definition Rule [-Wodr] > 1 | enum A > | ^ > t-2.cc:3:6: note: an enum with different value name is defined in another translation unit > 3 | enum A > | ^ > t-1.cc:3:9: note: name 'a' is defined to 1 while another translation unit defines it as 2 > 3 | a = 1, > | ^ > t-2.cc:5:9: note: mismatching definition > 5 | a = 2, > | ^ > I'm not sure how GCC 8 behaves. -- Xi Ruoyao <xry111@mengyan1223.wang> School of Aerospace Science and Technology, Xidian University ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GCC 8.3.0, -flto and violation of C++ One Definition Rule 2021-12-29 12:55 ` Xi Ruoyao @ 2021-12-29 13:34 ` Tom Kacvinsky 0 siblings, 0 replies; 9+ messages in thread From: Tom Kacvinsky @ 2021-12-29 13:34 UTC (permalink / raw) To: Xi Ruoyao; +Cc: gcc-help On Wed, Dec 29, 2021 at 7:55 AM Xi Ruoyao <xry111@mengyan1223.wang> wrote: > > On Wed, 2021-12-29 at 06:44 -0500, Tom Kacvinsky via Gcc-help 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. > > No, it's violated all the time. -Wodr only works with LTO because it's > impossible to detect ODR volations (across multiple TUs) just by linking > normal (non-LTO) object files. > > > 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, but that was just based on symbol names from > > gcc-nm output. > > Generally you can't find ODR violations this way. ODR violation does > not mean multiple definitions of a symbol. For example: > > // in 1.cpp > > enum A > { > a = 1, > }; > > // in 2.cpp > > enum A > { > a = 2, > }; > > If you link the objects compiled from these TUs together, you will > violate ODR. But these TUs won't produce any symbols for A or A::a at > all. > > > I suspect there is more to this since the object files > > have LTO information now, and that is what I'd like to examine. > > > > Any hints on how to move forward with diagnosing LTO link errors? > > With GCC-11, the diagnostic shows the exact location of ODR violation, > like: > > > t-1.cc:1:6: warning: type 'A' violates the C++ One Definition Rule [-Wodr] > > 1 | enum A > > | ^ > > t-2.cc:3:6: note: an enum with different value name is defined in another translation unit > > 3 | enum A > > | ^ > > t-1.cc:3:9: note: name 'a' is defined to 1 while another translation unit defines it as 2 > > 3 | a = 1, > > | ^ > > t-2.cc:5:9: note: mismatching definition > > 5 | a = 2, > > | ^ > > > > I'm not sure how GCC 8 behaves. > that's the problem. It is _not_ defined in another translation unit. Only defined in one C++ file ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GCC 8.3.0, -flto and violation of C++ One Definition Rule 2021-12-29 11:44 GCC 8.3.0, -flto and violation of C++ One Definition Rule Tom Kacvinsky 2021-12-29 12:55 ` Xi Ruoyao @ 2021-12-29 15:38 ` Jonathan Wakely 2021-12-29 16:15 ` Tom Kacvinsky 1 sibling, 1 reply; 9+ messages in thread From: Jonathan Wakely @ 2021-12-29 15:38 UTC (permalink / raw) To: Tom Kacvinsky; +Cc: gcc-help 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. but that was just based on symbol names from > gcc-nm output. I suspect there is more to this since the object files > have LTO information now, and that is what I'd like to examine. > > Any hints on how to move forward with diagnosing LTO link errors? > > Thanks, > > Tom > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GCC 8.3.0, -flto and violation of C++ One Definition Rule 2021-12-29 15:38 ` Jonathan Wakely @ 2021-12-29 16:15 ` Tom Kacvinsky 2021-12-29 17:01 ` Jonathan Wakely 0 siblings, 1 reply; 9+ messages in thread From: Tom Kacvinsky @ 2021-12-29 16:15 UTC (permalink / raw) To: Jonathan Wakely; +Cc: gcc-help 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] 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 ^ /home/tkacvins/libfoo/include/foo.h:21:8: error: type ‘struct C_Function_Table’ violates the C++ One Definition Rule [-Werror=odr] struct C_Function_Table ^ /home/tkacvins/project/libfoo/include/gen_foo.h:14: note: a different type is defined in another translation unit struct C_Function_Table /home/tkacvins/libfoo/include/foo.h:25:52: note: the first difference of corresponding definitions is field ‘create_quick_script_for_c’ int is_whitebox); ^ /home/tkacvins/project/libfoo/include/gen_foo.h:16: note: a field with different name is defined in another translation unit void (*create_quick_script_for_ada)(const char* param0, const char* param1, const char* param2, int param3); /home/home/tkacvins/project/libbar/include/Bar.h:82: error: ‘a2e_guard’ violates the C++ One Definition Rule [-Werror=odr] void a2e_guard(bool enabled); /home/home/tkacvins/project/libbar/src/src/Bar.cpp:333: note: implicit this pointer type mismatch void Bar::a2e_guard(bool enabled){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:333: note: ‘a2e_guard’ was previously declared here void Bar::a2e_guard(bool enabled){ /home/home/tkacvins/project/libbar/include/Bar.h:73:36: error: ‘instance’ violates the C++ One Definition Rule [-Werror=odr] static Bar * instance(); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:329: note: return value type mismatch Bar * Bar::instance(){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:329: note: ‘instance’ was previously declared here Bar * Bar::instance(){ /home/home/tkacvins/project/libbar/include/Bar.h:172:21: error: ‘get_source_file_name’ violates the C++ One Definition Rule [-Werror=odr] std::string get_source_file_name(int source_file_index); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:1901: note: implicit this pointer type mismatch std::string Bar::get_source_file_name(int source_file_index){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:1901: note: ‘get_source_file_name’ was previously declared here std::string Bar::get_source_file_name(int source_file_index){ /home/home/tkacvins/project/libbar/include/Bar.h:79:14: error: ‘get_enable_commits’ violates the C++ One Definition Rule [-Werror=odr] bool get_enable_commits(); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:447: note: implicit this pointer type mismatch bool Bar::get_enable_commits(){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:447: note: ‘get_enable_commits’ was previously declared here bool Bar::get_enable_commits(){ /home/home/tkacvins/project/libbar/include/Bar.h:78:14: error: ‘set_enable_commits’ violates the C++ One Definition Rule [-Werror=odr] void set_enable_commits(bool enabled); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:443: note: implicit this pointer type mismatch void Bar::set_enable_commits(bool enabled){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:443: note: ‘set_enable_commits’ was previously declared here void Bar::set_enable_commits(bool enabled){ /home/home/tkacvins/project/libbar/include/Bar.h:77:14: error: ‘commit’ violates the C++ One Definition Rule [-Werror=odr] void commit(); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:432: note: implicit this pointer type mismatch void Bar::commit(){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:432: note: ‘commit’ was previously declared here void Bar::commit(){ /home/home/tkacvins/project/libbar/include/Bar.h:92:14: error: ‘ada_clean_slots’ violates the C++ One Definition Rule [-Werror=odr] void ada_clean_slots (int parent_id, int max_index); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:963: note: implicit this pointer type mismatch void Bar::ada_clean_slots(int parent_id, int max_index){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:963: note: ‘ada_clean_slots’ was previously declared here void Bar::ada_clean_slots(int parent_id, int max_index){ /home/home/tkacvins/project/libbar/include/Bar.h:91:14: error: ‘ada_add_slot’ violates the C++ One Definition Rule [-Werror=odr] void ada_add_slot (int parent_id, int testcase_id, int index, int iterations, const char* delay, int print); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:951: note: implicit this pointer type mismatch void Bar::ada_add_slot(int parent_id, int testcase_id, int index, int iterations, const char * delay, int print) { /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:951: note: ‘ada_add_slot’ was previously declared here void Bar::ada_add_slot(int parent_id, int testcase_id, int index, int iterations, const char * delay, int print) { /home/home/tkacvins/project/libbar/include/Bar.h:90:14: error: ‘delete_testcase_results’ violates the C++ One Definition Rule [-Werror=odr] void delete_testcase_results (int unique_id ); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:486: note: implicit this pointer type mismatch void Bar::delete_testcase_results(int unique_id){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:486: note: ‘delete_testcase_results’ was previously declared here void Bar::delete_testcase_results(int unique_id){ /home/home/tkacvins/project/libbar/include/Bar.h:89:14: error: ‘delete_testcase’ violates the C++ One Definition Rule [-Werror=odr] void delete_testcase (int unique_id ); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:477: note: implicit this pointer type mismatch void Bar::delete_testcase(int unique_id){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:477: note: ‘delete_testcase’ was previously declared here void Bar::delete_testcase(int unique_id){ /home/home/tkacvins/project/libbar/include/Bar.h:88:14: error: ‘replace_testcase’ violates the C++ One Definition Rule [-Werror=odr] void replace_testcase (int uut_id, int subprogram_id, int testcase_index); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:676: note: implicit this pointer type mismatch void Bar::replace_testcase(int uutID, int subprogID, int tcID){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:676: note: ‘replace_testcase’ was previously declared here void Bar::replace_testcase(int uutID, int subprogID, int tcID){ /home/home/tkacvins/project/libbar/include/Bar.h:58:9: error: ‘__dt_comp ’ violates the C++ One Definition Rule [-Werror=odr] ~Bar(); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:295: note: implicit this pointer type mismatch Bar::~Bar() { /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:295: note: ‘__dt_comp ’ was previously declared here Bar::~Bar() { /home/home/tkacvins/project/libbar/include/Bar.h:80:14: error: ‘flush’ violates the C++ One Definition Rule [-Werror=odr] void flush(); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:421: note: implicit this pointer type mismatch void Bar::flush(){ /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:421: note: ‘flush’ was previously declared here void Bar::flush(){ /home/home/tkacvins/project/libbar/include/Bar.h:57:9: error: ‘__ct_comp ’ violates the C++ One Definition Rule [-Werror=odr] Bar(const char* path, bool force_create=false); ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:231: note: implicit this pointer type mismatch Bar::Bar(const char* path, bool force_create) { /home/home/tkacvins/project/libbar/include/Bar.h:38:7: note: type ‘struct Bar’ itself violates the C++ One Definition Rule class Bar { ^ /home/home/tkacvins/project/libbar/src/src/Bar.cpp:231: note: ‘__ct_comp ’ was previously declared here Bar::Bar(const char* path, bool force_create) { ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GCC 8.3.0, -flto and violation of C++ One Definition Rule 2021-12-29 16:15 ` Tom Kacvinsky @ 2021-12-29 17:01 ` Jonathan Wakely 2021-12-29 17:04 ` Jonathan Wakely 0 siblings, 1 reply; 9+ messages in thread From: Jonathan Wakely @ 2021-12-29 17:01 UTC (permalink / raw) To: Tom Kacvinsky; +Cc: gcc-help 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. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GCC 8.3.0, -flto and violation of C++ One Definition Rule 2021-12-29 17:01 ` Jonathan Wakely @ 2021-12-29 17:04 ` Jonathan Wakely 2021-12-29 18:18 ` Tom Kacvinsky 0 siblings, 1 reply; 9+ messages in thread From: Jonathan Wakely @ 2021-12-29 17:04 UTC (permalink / raw) To: Tom Kacvinsky; +Cc: gcc-help 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. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GCC 8.3.0, -flto and violation of C++ One Definition Rule 2021-12-29 17:04 ` Jonathan Wakely @ 2021-12-29 18:18 ` Tom Kacvinsky 2021-12-29 19:36 ` Jonathan Wakely 0 siblings, 1 reply; 9+ messages in thread From: Tom Kacvinsky @ 2021-12-29 18:18 UTC (permalink / raw) To: Jonathan Wakely; +Cc: gcc-help 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. We did this because of a conflict between Qt having an "#undef slots" but Python's object.h using slots in a struct definition. I worked around that, but I can try your suggestion - it just might work around the issue with having to play the #undef game before including the header that pulls in boost/python.hpp Thanks for the help with this, it is much appreciated! Tom ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GCC 8.3.0, -flto and violation of C++ One Definition Rule 2021-12-29 18:18 ` Tom Kacvinsky @ 2021-12-29 19:36 ` Jonathan Wakely 0 siblings, 0 replies; 9+ messages in thread From: Jonathan Wakely @ 2021-12-29 19:36 UTC (permalink / raw) To: Tom Kacvinsky; +Cc: gcc-help 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). ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2021-12-29 19:36 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-12-29 11:44 GCC 8.3.0, -flto and violation of C++ One Definition Rule Tom Kacvinsky 2021-12-29 12:55 ` Xi Ruoyao 2021-12-29 13:34 ` Tom Kacvinsky 2021-12-29 15:38 ` Jonathan Wakely 2021-12-29 16:15 ` Tom Kacvinsky 2021-12-29 17:01 ` Jonathan Wakely 2021-12-29 17:04 ` Jonathan Wakely 2021-12-29 18:18 ` Tom Kacvinsky 2021-12-29 19:36 ` Jonathan Wakely
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).