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

Reply via email to