[Bug libstdc++/85183] New: [8 Regression] std::variant move assignment mishandles move-only types
rs2740 at gmail dot com
gcc-bugzilla@gcc.gnu.org
Tue Apr 3 22:10:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85183
Bug ID: 85183
Summary: [8 Regression] std::variant move assignment mishandles
move-only types
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Keywords: rejects-valid
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: rs2740 at gmail dot com
Target Milestone: ---
Repro:
#include <variant>
struct moveonly {
moveonly() noexcept { }
moveonly(moveonly&&) noexcept { }
moveonly& operator=(moveonly&&) noexcept { return *this; }
~moveonly() { }
};
void test() {
std::variant<moveonly> m1, m2;
m1 = std::move(m2);
}
Compiles with 7. Breaks with 8:
In file included from prog.cc:1:
/opt/wandbox/gcc-head/include/c++/8.0.1/variant: In instantiation of 'void
std::__detail::__variant::__erased_assign(void*, void*) [with _Lhs = moveonly&;
_Rhs = const moveonly&]':
/opt/wandbox/gcc-head/include/c++/8.0.1/variant:607:27: required from
'std::__detail::__variant::_Move_assign_base<<anonymous>, _Types>&
std::__detail::__variant::_Move_assign_base<<anonymous>,
_Types>::operator=(std::__detail::__variant::_Move_assign_base<<anonymous>,
_Types>&&) [with bool <anonymous> = false; _Types = {moveonly}]'
/opt/wandbox/gcc-head/include/c++/8.0.1/variant:648:12: required from here
/opt/wandbox/gcc-head/include/c++/8.0.1/variant:258:42: error: use of deleted
function 'constexpr moveonly& moveonly::operator=(const moveonly&)'
__variant::__ref_cast<_Lhs>(__lhs) = __variant::__ref_cast<_Rhs>(__rhs);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:3:8: note: 'constexpr moveonly& moveonly::operator=(const moveonly&)'
is implicitly declared as deleted because 'moveonly' declares a move
constructor or move assignment operator
struct moveonly {
^~~~~~~~
In file included from prog.cc:1:
/opt/wandbox/gcc-head/include/c++/8.0.1/variant: In instantiation of 'void
std::__detail::__variant::__erased_ctor(void*, void*) [with _Lhs = moveonly&;
_Rhs = const moveonly&]':
/opt/wandbox/gcc-head/include/c++/8.0.1/variant:468:30: required from
'std::__detail::__variant::_Copy_ctor_base<<anonymous>,
_Types>::_Copy_ctor_base(const
std::__detail::__variant::_Copy_ctor_base<<anonymous>, _Types>&) [with bool
<anonymous> = false; _Types = {moveonly}]'
/opt/wandbox/gcc-head/include/c++/8.0.1/variant:509:7: required from
'std::__detail::__variant::_Move_assign_base<<anonymous>, _Types>&
std::__detail::__variant::_Move_assign_base<<anonymous>,
_Types>::operator=(std::__detail::__variant::_Move_assign_base<<anonymous>,
_Types>&&) [with bool <anonymous> = false; _Types = {moveonly}]'
/opt/wandbox/gcc-head/include/c++/8.0.1/variant:648:12: required from here
/opt/wandbox/gcc-head/include/c++/8.0.1/variant:246:7: error: use of deleted
function 'constexpr moveonly::moveonly(const moveonly&)'
::new (__lhs) _Type(__variant::__ref_cast<_Rhs>(__rhs));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:3:8: note: 'constexpr moveonly::moveonly(const moveonly&)' is
implicitly declared as deleted because 'moveonly' declares a move constructor
or move assignment operator
struct moveonly {
----
There are two bugs in the move assignment operator of _Move_assign_base primary
template, presumably caused by copy-paste:
* in the matching index case, it uses __erased_assign<_Types&, const _Types&>
when it should be using __erased_assign<_Types&, _Types&&>.
* in the mismatched index case, it copies __rhs to create __tmp
(`_Move_assign_base __tmp(__rhs);`) when it should have moved from it.
More information about the Gcc-bugs
mailing list