https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96766
Bug ID: 96766 Summary: std::swap(std::variant, std::variant) triggers undefined behavior sanitizer Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: kndevl at outlook dot com Target Milestone: --- Created attachment 49113 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49113&action=edit preprocessed source This snippet ``` #include <variant> class Foo { }; class Bar { }; using T = std::variant<Foo, Bar>; int main() { T t1 { Foo {} }; T t2 { Bar {} }; std::swap(t1, t2); return 0; } ``` triggers the following warning ``` /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:444:20: runtime error: implicit conversion from type 'std::size_t' (aka 'unsigned long') of value 18446744073709551615 (64-bit, unsigned) to type 'std::__detail::__variant::_Variant_storage<true, Foo, Bar>::__index_type' (aka 'unsigned char') changed the value to 255 (8-bit, unsigned) #0 0x55c00ff464ea in std::__detail::__variant::_Variant_storage<true, Foo, Bar>::_M_reset() /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:444 #1 0x55c00ff476a4 in void std::__detail::__variant::_Move_ctor_base<true, Foo, Bar>::_M_destructive_move<Bar>(unsigned short, Bar&&) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:564 #2 0x55c00ff472fb in auto std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}::operator()<Bar&, std::integral_constant<unsigned long, 1ul> >(Bar&, std::integral_constant<unsigned long, 1ul>) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:1588 #3 0x55c00ff4701e in void std::__invoke_impl<void, std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}, Bar&, std::integral_constant<unsigned long, 1ul> >(std::__invoke_other, std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}&&, Bar&, std::integral_constant<unsigned long, 1ul>&&) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/invoke.h:60 #4 0x55c00ff46e3f in std::__invoke_result<std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}, Bar&, std::integral_constant<unsigned long, 1ul> >::type std::__invoke<std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}, Bar&, std::integral_constant<unsigned long, 1ul> >(std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}&&, (std::__invoke_result&&)...) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/invoke.h:95 #5 0x55c00ff458e3 in std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::__detail::__variant::__variant_idx_cookie (*)(std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}&&, std::variant<Foo, Bar>&)>, std::integer_sequence<unsigned long, 1ul> >::__visit_invoke(std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}, std::variant<Foo, Bar>&) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:1001 #6 0x55c00ff4537c in decltype(auto) std::__do_visit<std::__detail::__variant::__variant_idx_cookie, std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}, std::variant<Foo, Bar>&>(std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}&&, std::variant<Foo, Bar>&) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:1694 #7 0x55c00ff45188 in void std::__detail::__variant::__raw_idx_visit<std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}, std::variant<Foo, Bar>&>(std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&)::{lambda(auto:1&&, auto:2)#1}&&, std::variant<Foo, Bar>&) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:201 #8 0x55c00ff4505a in std::variant<Foo, Bar>::swap(std::variant<Foo, Bar>&) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:1570 #9 0x55c00ff44451 in std::enable_if<(((is_move_constructible_v<Foo, Bar>)&&...))&&(((is_swappable_v<Foo, Bar>)&&...)), void>::type std::swap<Foo, Bar>(std::variant<Foo, Bar>&, std::variant<Foo, Bar>&) /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/variant:1240 #10 0x55c00ff44278 in main ../ubsan.cpp:14 #11 0x7f7f64b19151 in __libc_start_main (/usr/lib/libc.so.6+0x28151) #12 0x55c00ff4414d in _start (/home/user/main/cmake-build-debug-clang/ubsan-test+0x514d) ``` Is this a bug in libstdc++ or clang's sanitizer?