Bug ID | 1187254 |
---|---|
Summary | Clang 9 missing EBO for indirect bases causes miscompilations |
Classification | openSUSE |
Product | openSUSE Tumbleweed |
Version | Current |
Hardware | Other |
OS | Other |
Status | NEW |
Severity | Normal |
Priority | P5 - None |
Component | Development |
Assignee | screening-team-bugs@suse.de |
Reporter | aaronpuchert@alice-dsl.net |
QA Contact | qa-bugs@suse.de |
Found By | --- |
Blocker | --- |
After the update to GCC 11, there were numerous test failures in llvm9. Easiest to debug seemed to be that in unittests/Support/SupportTests --gtest_filter=Parallel.* Where the constructor std::thread::thread calls _M_start_thread, we can observe that on both ends of the call the structure looks different. That's not because anyone changed it, but because the constructor (compiled by Clang 9) thinks a std::unique_ptr<std::thread::_State> is 16 bytes big, whereas _M_start_thread (compiled by GCC 11) thinks it's only 8 bytes: #1 std::thread::thread<[...]>([...]&&) at /usr/include/c++/11/bits/std_thread.h:143 (gdb) p sizeof(_State_ptr) $32 = 16 (gdb) down #0 std::thread::_M_start_thread at [...]/libstdc++-v3/src/c++11/thread.cc:136 (gdb) p sizeof(_State_ptr) $33 = 8 Oops. Drilling down a bit, we find that both compilers agree on the base classes of std::_Tuple_impl<0, std::thread::_State*, std::default_delete<std::thread::_State> >, but not on the class itself. Clang 9: std::_Tuple_impl<0, ...>: 16 byte std::_Tuple_impl<1, std::default_delete<std::thread::_State>> : 1 byte std::_Head_base<0, std::thread::_State*, false>: 8 byte GCC 11: std::_Tuple_impl<0, ...>: 8 byte std::_Tuple_impl<1, std::default_delete<std::thread::_State>> : 1 byte std::_Head_base<0, std::thread::_State*, false>: 8 byte Clang 12 agrees with GCC 11, which is why we're not seeing a problem there. The difference can also be seen in the types emitted into the IR: --- clang9.ll +++ clang12.ll @@ -1,9 +1,9 @@ %"class.std::unique_ptr" = type { %"struct.std::__uniq_ptr_data" } %"struct.std::__uniq_ptr_data" = type { %"class.std::__uniq_ptr_impl" } %"class.std::__uniq_ptr_impl" = type { %"class.std::tuple" } %"class.std::tuple" = type { %"struct.std::_Tuple_impl" } - %"struct.std::_Tuple_impl" = type { %"struct.std::_Tuple_impl.0", %"struct.std::_Head_base.1" } - %"struct.std::_Tuple_impl.0" = type { %"struct.std::_Head_base" } - %"struct.std::_Head_base" = type { %"struct.std::default_delete" } - %"struct.std::default_delete" = type { i8 } + %"struct.std::_Tuple_impl" = type { %"struct.std::_Head_base.1" } + %"struct.std::_Tuple_impl.0" = type { i8 } + %"struct.std::default_delete" = type { i8 } + %"struct.std::_Head_base" = type { i8 } %"struct.std::_Head_base.1" = type { i32* } I've ordered and indented the types for readability. The difference is that Clang 9 nests the empty types, whereas Clang 12 emits an { i8 } for empty types and omits them when not needed. So Clang 9 doesn't do EBO for indirect bases. Clang 10 doesn't seem to have any issues either, so presumably I can just bisect this and cherry-pick whatever fixes it.