aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2018-01-29 12:33:32 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2018-01-29 12:33:32 +0000
commit73ebece382667f8b2d999676ba77bfd66eb2d9cd (patch)
treea079e590c2a734aab467f5fcf75a53220fff903a
parent27837e0c35badaa19b418d460c0cf69012bc9f07 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--libstdc++-v3/include/std/any15
-rw-r--r--libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/any/modifiers/83658.cc74
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();
+}