mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			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
This commit is contained in:
		
							parent
							
								
									b7d7c92f24
								
							
						
					
					
						commit
						0ec78a9369
					
				|  | @ -1,5 +1,15 @@ | |||
| 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; | ||||
|  |  | |||
|  | @ -0,0 +1,55 @@ | |||
| // 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(); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	 Jonathan Wakely
						Jonathan Wakely