This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [c++0x] nested_exception
Here's a prototype implementation of std::nested_exception with some
basic tests.
The spec isn't finalised (see n2619 and LWG issue 819) so I'm not
looking to check this in, just sharing it in case anyone has comments,
improvements or spots any bugs.
I used static_cast<Ex&&> instead of std::move, because std::move would
have meant including <bits/move.h> from libsupc++
Jon
Index: libsupc++/Makefile.am
===================================================================
--- libsupc++/Makefile.am (revision 147071)
+++ libsupc++/Makefile.am (working copy)
@@ -33,7 +33,7 @@ noinst_LTLIBRARIES = libsupc++convenienc
headers = \
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
- initializer_list exception_ptr.h
+ initializer_list exception_ptr.h nested_exception.h
if GLIBCXX_HOSTED
c_sources = \
Index: libsupc++/Makefile.in
===================================================================
--- libsupc++/Makefile.in (revision 147071)
+++ libsupc++/Makefile.in (working copy)
@@ -367,7 +367,7 @@ toolexeclib_LTLIBRARIES = libsupc++.la
noinst_LTLIBRARIES = libsupc++convenience.la
headers = \
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
- initializer_list exception_ptr.h
+ initializer_list exception_ptr.h nested_exception.h
@GLIBCXX_HOSTED_TRUE@c_sources = \
@GLIBCXX_HOSTED_TRUE@ cp-demangle.c
Index: libsupc++/exception
===================================================================
--- libsupc++/exception (revision 147071)
+++ libsupc++/exception (working copy)
@@ -146,6 +146,7 @@ _GLIBCXX_END_NAMESPACE
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) \
&& defined(_GLIBCXX_ATOMIC_BUILTINS_4))
#include <exception_ptr.h>
+#include <nested_exception.h>
#endif
#endif
Index: libsupc++/nested_exception.h
===================================================================
--- libsupc++/nested_exception.h (revision 0)
+++ libsupc++/nested_exception.h (revision 0)
@@ -0,0 +1,176 @@
+// Nested Exception support header (nested_exception class) for -*- C++ -*-
+
+// Copyright (C) 2009 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file nested_exception.h
+ * This is an internal header file, included by other headers and the
+ * implementation. You should not attempt to use it directly.
+ */
+
+#ifndef _GLIBCXX_NESTED_EXCEPTION_H
+#define _GLIBCXX_NESTED_EXCEPTION_H 1
+
+#pragma GCC visibility push(default)
+
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+# include <c++0x_warning.h>
+#else
+
+#include <bits/c++config.h>
+
+#if !defined(_GLIBCXX_ATOMIC_BUILTINS_4)
+# error This platform does not support exception propagation.
+#endif
+
+extern "C++" {
+
+namespace std
+{
+ /**
+ * @addtogroup exceptions
+ * @{
+ */
+
+ /// nested_exception
+ class nested_exception
+ {
+ public:
+ nested_exception() throw() : _M_ptr(current_exception()) { }
+
+ nested_exception(const nested_exception&) throw() = default;
+
+ nested_exception& operator=(const nested_exception&) throw() = default;
+
+ virtual ~nested_exception() = default;
+
+ void
+ rethrow_nested() const __attribute__ ((__noreturn__))
+ { rethrow_exception(_M_ptr); }
+
+ exception_ptr
+ nested_ptr() const
+ { return _M_ptr; }
+
+ private:
+ exception_ptr _M_ptr;
+ };
+
+ template<typename _Except>
+ struct _Nested_exception : public _Except, public nested_exception
+ {
+ explicit
+ _Nested_exception(_Except&& __ex)
+ : _Except(static_cast<_Except&&>(__ex))
+ { }
+ };
+
+ template<typename _Ex>
+ struct __get_nested_helper
+ {
+ static const nested_exception*
+ _S_get(const _Ex& __ex)
+ {
+ return dynamic_cast<const nested_exception*>(&__ex);
+ }
+ };
+
+ template<typename _Ex>
+ struct __get_nested_helper<_Ex*>
+ {
+ static const nested_exception*
+ _S_get(const _Ex* __ex)
+ {
+ return dynamic_cast<const nested_exception*>(__ex);
+ }
+ };
+
+ template<typename _Ex>
+ const nested_exception*
+ __get_nested_exception(const _Ex& __ex)
+ {
+ return __get_nested_helper<_Ex>::_S_get(__ex);
+ }
+
+ template<typename _Ex>
+ void
+ __throw_with_nested(_Ex&&, const nested_exception* = 0) __attribute__ ((__noreturn__));
+
+ template<typename _Ex>
+ void
+ __throw_with_nested(_Ex&&, ...) __attribute__ ((__noreturn__));
+
+ // This function should never be called, but is needed to avoid a warning
+ // about ambiguous base classes when instantiating throw_with_nested<_Ex>()
+ // with a type that has an accessible nested_exception base.
+ template<typename _Ex>
+ void
+ __throw_with_nested(_Ex&& __ex, const nested_exception* = 0)
+ {
+ throw __ex;
+ }
+
+ template<typename _Ex>
+ inline void
+ __throw_with_nested(_Ex&& __ex, ...)
+ {
+ throw _Nested_exception<_Ex>(static_cast<_Ex&&>(__ex));
+ }
+
+ template<typename _Ex>
+ void
+ throw_with_nested(_Ex __ex) __attribute__ ((__noreturn__));
+
+ template<typename _Ex>
+ inline void
+ throw_with_nested(_Ex __ex)
+ {
+ if (__get_nested_exception(__ex))
+ throw __ex;
+ __throw_with_nested(static_cast<_Ex&&>(__ex), &__ex);
+ }
+
+ template<typename _Ex>
+ void
+ rethrow_if_nested(const _Ex& __ex)
+ {
+ if (const nested_exception* __nested = __get_nested_exception(__ex))
+ __nested->rethrow_nested();
+ }
+
+ // see n2619
+ void
+ rethrow_if_nested(const nested_exception& __ex)
+ {
+ __ex.rethrow_nested();
+ }
+
+ // @} group exceptions
+} // namespace std
+
+} // extern "C++"
+
+#endif // __GXX_EXPERIMENTAL_CXX0X__
+
+#pragma GCC visibility pop
+
+#endif // _GLIBCXX_NESTED_EXCEPTION_H
Index: testsuite/18_support/nested_exception/rethrow_nested.cc
===================================================================
--- testsuite/18_support/nested_exception/rethrow_nested.cc (revision 0)
+++ testsuite/18_support/nested_exception/rethrow_nested.cc (revision 0)
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2009 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/>.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = false;
+
+ try
+ {
+ try
+ {
+ throw 42;
+ }
+ catch (...)
+ {
+ std::nested_exception e;
+ e.rethrow_nested();
+ }
+ }
+ catch(const int& i)
+ {
+ test = true;
+ VERIFY( i == 42 );
+ }
+
+ VERIFY( test );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/18_support/nested_exception/throw_with_nested.cc
===================================================================
--- testsuite/18_support/nested_exception/throw_with_nested.cc (revision 0)
+++ testsuite/18_support/nested_exception/throw_with_nested.cc (revision 0)
@@ -0,0 +1,79 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2009 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/>.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+struct derived : std::nested_exception { };
+
+struct not_derived { virtual ~not_derived() = default; };
+
+void test01()
+{
+ bool test __attribute__((unused)) = false;
+
+ try
+ {
+ std::throw_with_nested(derived());
+ }
+ catch (const std::nested_exception& e)
+ {
+ VERIFY( !e.nested_ptr() );
+ try
+ {
+ throw;
+ }
+ catch (const derived&)
+ {
+ test = true;
+ }
+ }
+ VERIFY( test );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = false;
+
+ try
+ {
+ std::throw_with_nested(not_derived());
+ }
+ catch (const std::nested_exception& e)
+ {
+ VERIFY( !e.nested_ptr() );
+ try
+ {
+ throw;
+ }
+ catch (const not_derived&)
+ {
+ test = true;
+ }
+ }
+ VERIFY( test );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/18_support/nested_exception/cons.cc
===================================================================
--- testsuite/18_support/nested_exception/cons.cc (revision 0)
+++ testsuite/18_support/nested_exception/cons.cc (revision 0)
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2009 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/>.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::nested_exception e;
+
+ VERIFY( !e.nested_ptr() );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ try
+ {
+ throw 42;
+ }
+ catch (...)
+ {
+ std::nested_exception e;
+ VERIFY( e.nested_ptr() == std::current_exception() );
+ }
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/18_support/nested_exception/nested_ptr.cc
===================================================================
--- testsuite/18_support/nested_exception/nested_ptr.cc (revision 0)
+++ testsuite/18_support/nested_exception/nested_ptr.cc (revision 0)
@@ -0,0 +1,71 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2009 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/>.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ try
+ {
+ throw std::nested_exception();
+ }
+ catch (const std::nested_exception& e)
+ {
+ VERIFY( !e.nested_ptr() );
+ }
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ try
+ {
+ throw 42;
+ }
+ catch (...)
+ {
+ try
+ {
+ throw std::nested_exception();
+ }
+ catch (const std::nested_exception& e)
+ {
+ try
+ {
+ std::rethrow_exception( e.nested_ptr() );
+ }
+ catch(const int& i)
+ {
+ VERIFY( i == 42 );
+ }
+ }
+ }
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/18_support/nested_exception/rethrow_if_nested.cc
===================================================================
--- testsuite/18_support/nested_exception/rethrow_if_nested.cc (revision 0)
+++ testsuite/18_support/nested_exception/rethrow_if_nested.cc (revision 0)
@@ -0,0 +1,110 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2009 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/>.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+struct derived : std::nested_exception { };
+
+struct base { virtual ~base() = default; };
+
+struct derived2 : base, std::nested_exception { };
+
+void test01()
+{
+ bool test __attribute__((unused)) = false;
+
+ try
+ {
+ throw 42;
+ }
+ catch (...)
+ {
+ derived d;
+ try
+ {
+ std::rethrow_if_nested(d);
+ }
+ catch (const int& i)
+ {
+ test = true;
+ VERIFY( i == 42 );
+ }
+ }
+
+ VERIFY( test );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = false;
+
+ try
+ {
+ throw base();
+ }
+ catch (const base& b)
+ {
+ std::rethrow_if_nested(b);
+ test = true;
+ }
+
+ VERIFY( test );
+}
+
+void test03()
+{
+ bool test __attribute__((unused)) = false;
+
+ try
+ {
+ throw 42;
+ }
+ catch (...)
+ {
+ try
+ {
+ throw derived2();
+ }
+ catch (const base& b)
+ {
+ try
+ {
+ std::rethrow_if_nested(b);
+ }
+ catch (const int& i)
+ {
+ VERIFY( i == 42 );
+ test = true;
+ }
+ }
+ }
+
+ VERIFY( test );
+}
+
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ return 0;
+}