Commit 73ebece3 by Jonathan Wakely Committed by Jonathan Wakely

PR libstdc++/83658 fix exception-safety in std::any::emplace

	PR libstdc++/83658
	* include/std/any (any::__do_emplace): Only set _M_manager after
	constructing the contained object.
	* testsuite/20_util/any/misc/any_cast_neg.cc: Adjust dg-error line.
	* testsuite/20_util/any/modifiers/83658.cc: New test.

From-SVN: r257141
parent 27837e0c
2018-01-29 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/83658
* include/std/any (any::__do_emplace): Only set _M_manager after
constructing the contained object.
* testsuite/20_util/any/misc/any_cast_neg.cc: Adjust dg-error line.
* testsuite/20_util/any/modifiers/83658.cc: New test.
2018-01-25 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/81076
......
......@@ -70,7 +70,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* @brief A type-safe container of any type.
*
*
* An @c any object's state is either empty or it stores a contained object
* of CopyConstructible type.
*/
......@@ -114,8 +114,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void __do_emplace(_Args&&... __args)
{
reset();
_M_manager = &_Mgr::_S_manage;
_Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
_M_manager = &_Mgr::_S_manage;
}
/// Emplace with an object created from @p __il and @p __args as
......@@ -125,8 +125,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void __do_emplace(initializer_list<_Up> __il, _Args&&... __args)
{
reset();
_M_manager = &_Mgr::_S_manage;
_Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
_M_manager = &_Mgr::_S_manage;
}
public:
......@@ -272,8 +272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Decay<_ValueType>, _Args&&...>::type
emplace(_Args&&... __args)
{
__do_emplace<_Decay<_ValueType>>
(std::forward<_Args>(__args)...);
__do_emplace<_Decay<_ValueType>>(std::forward<_Args>(__args)...);
any::_Arg __arg;
this->_M_manager(any::_Op_access, this, &__arg);
return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
......@@ -288,8 +287,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Args&&...>::type
emplace(initializer_list<_Up> __il, _Args&&... __args)
{
__do_emplace<_Decay<_ValueType>, _Up>
(__il, std::forward<_Args>(__args)...);
__do_emplace<_Decay<_ValueType>, _Up>(__il,
std::forward<_Args>(__args)...);
any::_Arg __arg;
this->_M_manager(any::_Op_access, this, &__arg);
return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
......@@ -624,7 +623,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// @}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
......
......@@ -26,5 +26,5 @@ void test01()
using std::any_cast;
const any y(1);
any_cast<int&>(y); // { dg-error "invalid static_cast" "" { target { *-*-* } } 461 }
any_cast<int&>(y); // { dg-error "invalid static_cast" "" { target { *-*-* } } 460 }
}
// 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 <any>
#include <new>
#include <testsuite_hooks.h>
struct E : std::bad_alloc { };
struct X
{
X() = default;
X(std::initializer_list<int>) { }
// Prevents small-object optimization:
X(const X&) noexcept(false) { }
static void* operator new(std::size_t) { throw E{}; }
static void operator delete(void*, std::size_t) noexcept { }
};
void
test01()
{
std::any a;
try
{
a.emplace<X>();
VERIFY(false);
}
catch (const E&)
{
VERIFY( !a.has_value() );
}
}
void
test02()
{
std::any a;
try
{
a.emplace<X>(std::initializer_list<int>{});
VERIFY(false);
}
catch (const E&)
{
VERIFY( !a.has_value() );
}
}
int
main()
{
test01();
test02();
}
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