Created attachment 159107 [details] dynamic_cast testcase (shell archive) dynamic_cast returns 0 when the (apparently same) type is known in the different runtime modules. The attached test (just run "make all run" with BSD make or bmake on Linux) returns: Parent::something() = 1 Child::something() = 2 library dynamic_cast<Child *>(Parent *) = 0x0 library dynamic_cast<Child *>(Child *) = 0x0 local dynamic_cast<Child *>(Parent *) = 0x0 local dynamic_cast<Child *>(Child *) = 0x7fffffffe580 When using libstdc++.so.6 from gcc48 or newer: Parent::something() = 1 Child::something() = 2 library dynamic_cast<Child *>(Parent *) = (nil) library dynamic_cast<Child *>(Child *) = 0x7fffaea254c0 local dynamic_cast<Child *>(Parent *) = (nil) local dynamic_cast<Child *>(Child *) = 0x7fffaea254c0
Original bug report: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=201784
Original bug report: https://github.com/marekjm/viuavm/issues/70
This is a known issue (I can't find the closed bug report for it at the moment). If you don't link with -Wl,-export-dynamic, then the RTTI symbols will not be merged. This then means that the pointer comparison in libcxxrt will fail. The work-around that libsupc++ implements replaces the pointer comparison with string comparison. This adds a noticeable performance hit in all dynamic_casts. We decided not to impose a performance hit on all C++ programs just to benefit people who can pass different linker flags to avoid a bug.
Thanks, I was searching for it in the Bugzilla and could not find one. The rationale seems very reasonable to me. By the way I have just discovered -Wl,--dynamic-list-cpp-typeinfo which also does the job.
I wonder if we should modify the clang driver so that it always passes --dynamic-list-cpp-typeinfo by default when linking C++. Are there any down sides to this?
By the way, our <bsd.lib.mk> always uses ${CC} when linking shared library (and it's silenced with @). Is this okay for C++ libs?
Hmm, possibly for the specific case of the base system, where we explicitly pass -lc++ and so on. It's generally a very bad idea though.
(In reply to Marcin Cieślak from comment #6) > By the way, our <bsd.lib.mk> always uses ${CC} when linking shared library > (and it's silenced with @). Is this okay for C++ libs? Not if you specify the lib using LIB_CXX, like in the libatf-c++ Makefile: LIB_CXX= atf-c++ We used to do a 'deep' comparison of the typeinfo earlier, but only in head from r256642 onwards, and we eventually reverted it in r278010. As Jörg Sonnenberger noted in a private mail conversation: "... there are three different problematic situations: (1) A type is used in the main program and it is linked without -rdynamic. (2) A type is used by two different DSOs and both are loaded with RTLD_LOCAL. (3) Two independent types of the same name are defined in two different DSOs. The hack makes the first two work to a degree and fails misserable on the last. IMO (2) and (3) should be considered the same and (1) is just a bug." (N.B.: with 'the hack' he meant doing the deep comparison.)
oh, ok. LIB_CXX is not there on my oldish -CURRENT, it got in there in March 2015.