Commit 0ec78a93 by Jonathan Wakely Committed by Jonathan Wakely

PR libstdc++/86874 fix std::variant::swap regression

	PR libstdc++/86874
	* include/std/variant (_Copy_ctor_base::_M_destructive_move): Define
	here instead of in _Move_assign_base.
	(_Copy_ctor_base<true, _Types...>::_M_destructive_move): Define.
	(_Copy_assign_base::operator=): Use _M_destructive_move when changing
	the contained value to another alternative.
	(_Move_assign_base::operator=): Likewise.
	(_Move_assign_base::_M_destructive_move): Remove.
	* testsuite/20_util/variant/86874.cc: New test.

From-SVN: r263365
parent b7d7c92f
2018-08-07 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/86874
* include/std/variant (_Copy_ctor_base::_M_destructive_move): Define
here instead of in _Move_assign_base.
(_Copy_ctor_base<true, _Types...>::_M_destructive_move): Define.
(_Copy_assign_base::operator=): Use _M_destructive_move when changing
the contained value to another alternative.
(_Move_assign_base::operator=): Likewise.
(_Move_assign_base::_M_destructive_move): Remove.
* testsuite/20_util/variant/86874.cc: New test.
PR libstdc++/86861
* libsupc++/new_opa.cc [_GLIBCXX_HAVE_MEMALIGN] (aligned_alloc):
Replace macro with inline function.
......
......@@ -506,6 +506,20 @@ namespace __variant
}
}
void _M_destructive_move(_Move_ctor_base&& __rhs)
{
this->~_Move_ctor_base();
__try
{
::new (this) _Move_ctor_base(std::move(__rhs));
}
__catch (...)
{
this->_M_index = variant_npos;
__throw_exception_again;
}
}
_Move_ctor_base(const _Move_ctor_base&) = default;
_Move_ctor_base& operator=(const _Move_ctor_base&) = default;
_Move_ctor_base& operator=(_Move_ctor_base&&) = default;
......@@ -516,6 +530,12 @@ namespace __variant
{
using _Base = _Copy_ctor_alias<_Types...>;
using _Base::_Base;
void _M_destructive_move(_Move_ctor_base&& __rhs)
{
this->~_Move_ctor_base();
::new (this) _Move_ctor_base(std::move(__rhs));
}
};
template<typename... _Types>
......@@ -538,22 +558,14 @@ namespace __variant
{
static constexpr void (*_S_vtable[])(void*, void*) =
{ &__erased_assign<_Types&, const _Types&>... };
_S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
_S_vtable[__rhs._M_index](this->_M_storage(),
__rhs._M_storage());
}
}
else
{
_Copy_assign_base __tmp(__rhs);
this->~_Copy_assign_base();
__try
{
::new (this) _Copy_assign_base(std::move(__tmp));
}
__catch (...)
{
this->_M_index = variant_npos;
__throw_exception_again;
}
this->_M_destructive_move(std::move(__tmp));
}
__glibcxx_assert(this->_M_index == __rhs._M_index);
return *this;
......@@ -582,20 +594,6 @@ namespace __variant
using _Base = _Copy_assign_alias<_Types...>;
using _Base::_Base;
void _M_destructive_move(_Move_assign_base&& __rhs)
{
this->~_Move_assign_base();
__try
{
::new (this) _Move_assign_base(std::move(__rhs));
}
__catch (...)
{
this->_M_index = variant_npos;
__throw_exception_again;
}
}
_Move_assign_base&
operator=(_Move_assign_base&& __rhs)
noexcept(_Traits<_Types...>::_S_nothrow_move_assign)
......@@ -613,16 +611,7 @@ namespace __variant
else
{
_Move_assign_base __tmp(std::move(__rhs));
this->~_Move_assign_base();
__try
{
::new (this) _Move_assign_base(std::move(__tmp));
}
__catch (...)
{
this->_M_index = variant_npos;
__throw_exception_again;
}
this->_M_destructive_move(std::move(__tmp));
}
__glibcxx_assert(this->_M_index == __rhs._M_index);
return *this;
......
// Copyright (C) 2018 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++17" }
// { dg-do run { target c++17 } }
#include <variant>
#include <testsuite_hooks.h>
void
test01()
{
std::variant<std::monostate> v1, v2;
std::swap(v1, v2);
}
void
test02()
{
std::variant<int> v1{1}, v2{2};
std::swap(v1, v2);
VERIFY( std::get<0>(v1) == 2 );
VERIFY( std::get<0>(v2) == 1 );
}
void
test03()
{
std::variant<double, int> v1{1}, v2{2.3};
std::swap(v1, v2);
VERIFY( std::get<double>(v1) == 2.3 );
VERIFY( std::get<int>(v2) == 1 );
}
int
main()
{
test01();
test02();
test03();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment