I looked at the codegen of this before and after the patch, and it does the right thing. Variant's tests run on Linux-x64. OK for trunk?
2019-03-25 Ville Voutilainen <ville.voutilai...@gmail.com> PR libstdc++/89816 Fix based on a suggestion by Antony Polukhin. * include/std/variant (__variant_construct): Capture a pointer to the storage and visit just one variant.
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index a5b8fa8..0984e13 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -426,18 +426,18 @@ namespace __variant void __variant_construct(_Tp&& __lhs, _Up&& __rhs) { __lhs._M_index = __rhs._M_index; - __do_visit([](auto&& __this_mem, auto&& __rhs_mem) mutable + void* __storage = std::addressof(__lhs._M_u); + __do_visit([__storage](auto&& __rhs_mem) mutable -> __detail::__variant::__variant_cookie { - using _Type = remove_reference_t<decltype(__this_mem)>; + using _Type = remove_reference_t<decltype(__rhs_mem)>; if constexpr (is_same_v<__remove_cvref_t<decltype(__rhs_mem)>, remove_cv_t<_Type>> && !is_same_v<_Type, __variant_cookie>) - ::new ((void*)std::addressof(__this_mem)) + ::new (__storage) _Type(std::forward<decltype(__rhs_mem)>(__rhs_mem)); return {}; - }, __variant_cast<_Types...>(__lhs), - __variant_cast<_Types...>(std::forward<decltype(__rhs)>(__rhs))); + }, __variant_cast<_Types...>(std::forward<decltype(__rhs)>(__rhs))); } // The following are (Copy|Move) (ctor|assign) layers for forwarding