[Bug c++/38828] New: g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear
I'm compiling the attached source and inspecting symbols in it: g++-4.3 -v -save-temps -Wall -Wextra -O2 -fno-inline-small-functions mylib.cpp -c -o mylib.o nm mylib.o | c++filt | grep 'serialize<' With -O2 -fno-inline-small-functions (as above), nm gives (as expected): W void boost::serialization::serialize(boost::archive::xml_iarchive&, A&, unsigned int) W void boost::serialization::serialize(boost::archive::xml_iarchive&, B&, unsigned int) W void boost::serialization::serialize(boost::archive::xml_oarchive&, A&, unsigned int) W void boost::serialization::serialize(boost::archive::xml_oarchive&, B&, unsigned int) With just -O2, some symbols are missing: W void boost::serialization::serialize(boost::archive::xml_iarchive&, B&, unsigned int) W void boost::serialization::serialize(boost::archive::xml_oarchive&, B&, unsigned int) The disappearing functions are explicit template instantiations, that are not marked static, or inline. With g++-4.1 and g++-4.2, no symbols are missing. The g++ output follows. Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu11' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu Thread model: posix gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu11) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-O2' '-c' '-o' 'mylib.o' '-shared-libgcc' '-mtune=generic' /usr/lib/gcc/i486-linux-gnu/4.3.2/cc1plus -E -quiet -v -D_GNU_SOURCE mylib.cpp -D_FORTIFY_SOURCE=2 -mtune=generic -Wall -Wextra -O2 -fpch-preprocess -o mylib.ii ignoring nonexistent directory "/usr/local/include/i486-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../i486-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/4.3 /usr/include/c++/4.3/i486-linux-gnu /usr/include/c++/4.3/backward /usr/local/include /usr/lib/gcc/i486-linux-gnu/4.3.2/include /usr/lib/gcc/i486-linux-gnu/4.3.2/include-fixed /usr/include/i486-linux-gnu /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-O2' '-c' '-o' 'mylib.o' '-shared-libgcc' '-mtune=generic' /usr/lib/gcc/i486-linux-gnu/4.3.2/cc1plus -fpreprocessed mylib.ii -quiet -dumpbase mylib.cpp -mtune=generic -auxbase-strip mylib.o -O2 -Wall -Wextra -version -fstack-protector -o mylib.s GNU C++ (Ubuntu 4.3.2-1ubuntu11) version 4.3.2 (i486-linux-gnu) compiled by GNU C version 4.3.2, GMP version 4.2.2, MPFR version 2.3.2. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: dc8f858cacda993dd8f70837f0d9565d COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-O2' '-c' '-o' 'mylib.o' '-shared-libgcc' '-mtune=generic' as -V -Qy -o mylib.o mylib.s GNU assembler version 2.18.93 (i486-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.18.93.20081009 COMPILER_PATH=/usr/lib/gcc/i486-linux-gnu/4.3.2/:/usr/lib/gcc/i486-linux-gnu/4.3.2/:/usr/lib/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.3.2/:/usr/lib/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.3.2/:/usr/lib/gcc/i486-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/i486-linux-gnu/4.3.2/:/usr/lib/gcc/i486-linux-gnu/4.3.2/:/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-O2' '-c' '-o' 'mylib.o' '-shared-libgcc' '-mtune=generic' -- Summary: g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear Product: gcc Version: 4.3.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: ronan dot lehy at probayes dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38828
[Bug c++/38828] g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear
--- Comment #1 from ronan dot lehy at probayes dot com 2009-01-13 16:35 --- Created an attachment (id=17088) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17088&action=view) Preprocessed source -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38828
[Bug c++/38828] g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear
--- Comment #2 from ronan dot lehy at probayes dot com 2009-01-13 16:39 --- (In reply to comment #1) > Created an attachment (id=17088) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17088&action=view) I had to trim a bit the source to be make the preprocessed source fit into 1000 ko. With it, the expected nm output (-O2 -fno-inline-small-functions) is: W void boost::serialization::serialize(boost::archive::xml_iarchive&, A&, unsigned int) W void boost::serialization::serialize(boost::archive::xml_iarchive&, B&, unsigned int) And the one with missing symbols (-O2) is: W void boost::serialization::serialize(boost::archive::xml_iarchive&, B&, unsigned int) -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38828
[Bug c++/38828] g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear
--- Comment #3 from ronan dot lehy at probayes dot com 2009-01-13 16:42 --- Created an attachment (id=17089) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17089&action=view) Original source (#includes Boost headers). -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38828
[Bug c++/38828] g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear
--- Comment #6 from ronan dot lehy at probayes dot com 2009-01-14 09:11 --- Thanks a lot for considering this report! (In reply to comment #5) > Also since it is not explicitly instatinated, the template does not need to be > in the object file really. I believe this is instantiated with Archive = boost_xml_iarchive by the BOOST_EXPORT macro. (In reply to comment #5) > serialize with an empty body is a pure function so it will be can > be optimized away without any effects. I don't see the issue here really. But this function (as instantiated with Archive = boost_xml_iarchive by BOOST_EXPORT) can be called from other .o files. Actually, it is, and linking the .o files together into a shared library then fails. > Can you give a better example of why do you think this is wrong besides a nm > testcase? I could show you how mylib1.o and mylib2.o fail to link into libmylib.so, since serialize(boost_xml_iarchive&, A&, unsigned int) is referenced by mylib2.o, and should be defined in mylib1.o, but is not. Do you want that ? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38828
[Bug c++/38828] g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear
--- Comment #7 from ronan dot lehy at probayes dot com 2009-01-14 09:14 --- (In reply to comment #6) > I believe this is instantiated with Archive = boost_xml_iarchive by the > BOOST_EXPORT macro. I mean BOOST_CLASS_EXPORT(), of course, sorry. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38828
[Bug c++/38828] g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear
--- Comment #8 from ronan dot lehy at probayes dot com 2009-01-15 15:13 --- If I add simple explicit instantiations in place or in addition to the BOOST_CLASS_EXPORT() calls, all symbols are correctly exposed in all cases : namespace boost { namespace serialization { template void serialize(boost::archive::xml_iarchive &, A &, unsigned int); template void serialize(boost::archive::xml_iarchive &, B &, unsigned int); } } Therefore, there may be a problem related to the way BOOST_CLASS_EXPORT() instantiates serialize<>(). BOOST_CLASS_EXPORT(A) expands to: namespace boost { namespace archive { namespace detail { template<> const guid_initializer< A > guid_initializer< A >::instance("A"); template std::pair< const export_generator< A, boost::archive::detail::known_archive_types::type> *, const guid_initializer< A > *> export_archives_invoke< A, boost::archive::detail::known_archive_types::type> (A &, boost::archive::detail::known_archive_types::type &); } } }; -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38828
[Bug c++/38828] g++ 4.3.2: -O2 without -fno-inline-small-functions makes some template instantiations disappear
--- Comment #9 from ronan dot lehy at probayes dot com 2009-01-15 16:12 --- Following the twisted maze that is BOOST_CLASS_EXPORT() leads me to think that it is (very) roughly equivalent to this: void dummy(boost::archive::xml_iarchive & ar, A & a, B & b) { boost::serialization::serialize(ar, a, 0); boost::serialization::serialize(ar, b, 0); } Indeed, replacing my BOOST_CLASS_EXPORT() calls with this, I get the same effect ("disappearing" symbols with -O2). At this point, my question is: is triggering template instantiations in this way supposed to be equivalent to explicit instantiations (as in comment #8) with respect to symbols exposed to the outside? If the answer is no, thank you very much for your help and sorry for the trouble. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38828