diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2018-01-29 12:33:32 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2018-01-29 12:33:32 +0000 |
commit | 73ebece382667f8b2d999676ba77bfd66eb2d9cd (patch) | |
tree | a079e590c2a734aab467f5fcf75a53220fff903a | |
parent | 27837e0c35badaa19b418d460c0cf69012bc9f07 (diff) | |
download | gcc-73ebece382667f8b2d999676ba77bfd66eb2d9cd.zip gcc-73ebece382667f8b2d999676ba77bfd66eb2d9cd.tar.gz gcc-73ebece382667f8b2d999676ba77bfd66eb2d9cd.tar.bz2 |
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
-rw-r--r-- | libstdc++-v3/ChangeLog | 8 | ||||
-rw-r--r-- | libstdc++-v3/include/std/any | 15 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/any/modifiers/83658.cc | 74 |
4 files changed, 90 insertions, 9 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c856221..b54b34c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +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 diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index 5fb8df7..466b7ca 100644 --- a/libstdc++-v3/include/std/any +++ b/libstdc++-v3/include/std/any @@ -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 diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc index 21f145eb..50a9a67 100644 --- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc @@ -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 } } diff --git a/libstdc++-v3/testsuite/20_util/any/modifiers/83658.cc b/libstdc++-v3/testsuite/20_util/any/modifiers/83658.cc new file mode 100644 index 0000000..7c5acc6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/modifiers/83658.cc @@ -0,0 +1,74 @@ +// 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(); +} |