diff mbox

[PATCHv2] do not throw in std::make_exception_ptr

Message ID 20160822172935.GV20016@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Aug. 22, 2016, 5:29 p.m. UTC
On 21/08/16 15:20 +0300, Gleb Natapov wrote:
>Jonathan,
>
>Is this version OK with you?

I've committed the attached version, which just adds some whitespace
and fixes the testsuite_abi.cc test.

Thanks very much for the improvement to the code.

Comments

Ryan Burn Oct. 21, 2016, 3:53 a.m. UTC | #1
Are exception classes required to support emplace new construction
like that? With this change, Intel's TBB library no longer compiles
because its exception class declares it's own new operator (see
https://github.com/wjakob/tbb/blob/master/include/tbb/tbb_exception.h):


class tbb_exception : public std::exception
{
    /** No operator new is provided because the TBB usage model assumes dynamic
         creation of the TBB exception objects only by means of applying move()
         operation on an exception thrown out of TBB scheduler. **/
    void* operator new ( size_t );
....


On Mon, Aug 22, 2016 at 1:29 PM, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 21/08/16 15:20 +0300, Gleb Natapov wrote:
>>
>> Jonathan,
>>
>> Is this version OK with you?
>
>
> I've committed the attached version, which just adds some whitespace
> and fixes the testsuite_abi.cc test.
>
> Thanks very much for the improvement to the code.
>
diff mbox

Patch

commit f80c0cc401fc34b424662286bedc559d0e2bb243
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Aug 22 18:03:39 2016 +0100

    libstdc++/68297 avoid throw/catch in make_exception_ptr
    
    2016-08-22  Gleb Natapov  <gleb@scylladb.com>
    
    	PR libstdc++/68297
    	* config/abi/pre/gnu-versioned-namespace.ver: Export
    	__cxa_init_primary_exception and std::exception_ptr(void*).
    	* config/abi/pre/gnu.ver (CXXABI_1.3.11) : Add new symbol version and
    	export __cxa_init_primary_exception and std::exception_ptr(void*).
    	* include/Makefile.am: Add new headers.
    	* include/Makefile.in: Regenerate.
    	* libsupc++/Makefile.am: Add new headers.
    	* libsupc++/Makefile.in: Regenerate.
    	* libsupc++/cxxabi.h (__cxa_allocate_exception): Move to ...
    	* libsupc++/cxxabi_init_exception.h: New header.
    	(__cxa_init_primary_exception): Declare.
    	* libsupc++/eh_throw.cc (__cxa_init_primary_exception): Define.
    	(__cxa_throw): Use __cxa_init_primary_exception.
    	* libsupc++/exception (std::exception): Move to ...
    	* libsupc++/exception.h: New header.
    	* libsupc++/exception_ptr.h (__exception_ptr::exception_ptr): Add
    	friend declaration.
    	(__exception_ptr::__dest_thunk): New function template.
    	(std::make_exception_ptr) [__cpp_rtti && !_GLIBCXX_HAVE_CDTOR_CALLABI]:
    	Use __cxa_allocate_exception and __cxa_init_primary_exception to
    	create exception_ptr.
    	* libsupc++/typeinfo: Include bits/exception.h instead of exception.
    	* testsuite/util/testsuite_abi.cc: Add CXXABI_1.3.11 version.

diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index 8304dee..65866a3 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -179,6 +179,7 @@  CXXABI_2.0 {
     __cxa_free_exception;
     __cxa_free_dependent_exception;
     __cxa_get_exception_ptr;
+    __cxa_init_primary_exception;
     __cxa_get_globals;
     __cxa_get_globals_fast;
     __cxa_guard_abort;
@@ -205,6 +206,7 @@  CXXABI_2.0 {
     # std::exception_ptr
     _ZNSt15__exception_ptr13exception_ptrC1Ev;
     _ZNSt15__exception_ptr13exception_ptrC2Ev;
+    _ZNSt15__exception_ptr13exception_ptrC1EPv;
     _ZNSt15__exception_ptr13exception_ptrC1ERKS0_;
     _ZNSt15__exception_ptr13exception_ptrC2ERKS0_;
     _ZNSt15__exception_ptr13exception_ptrC1EMS0_FvvE;
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index b7f54e2..f51c6f9 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2164,6 +2164,13 @@  CXXABI_1.3.10 {
 
 } CXXABI_1.3.9;
 
+CXXABI_1.3.11 {
+
+    __cxa_init_primary_exception;
+    _ZNSt15__exception_ptr13exception_ptrC1EPv;
+
+} CXXABI_1.3.10;
+
 # Symbols in the support library (libsupc++) supporting transactional memory.
 CXXABI_TM_1 {
 
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 0a10994..9cd18df 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -205,6 +205,8 @@  bits_sup_srcdir = ${glibcxx_srcdir}/libsupc++
 bits_sup_headers = \
 	${bits_sup_srcdir}/atomic_lockfree_defines.h \
 	${bits_sup_srcdir}/cxxabi_forced.h \
+	${bits_sup_srcdir}/cxxabi_init_exception.h \
+	${bits_sup_srcdir}/exception.h \
 	${bits_sup_srcdir}/exception_defines.h \
 	${bits_sup_srcdir}/exception_ptr.h \
 	${bits_sup_srcdir}/hash_bytes.h \
diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am
index b45b5ae..ba4eac1 100644
--- a/libstdc++-v3/libsupc++/Makefile.am
+++ b/libstdc++-v3/libsupc++/Makefile.am
@@ -35,7 +35,7 @@  std_HEADERS = \
 
 bits_HEADERS = \
 	atomic_lockfree_defines.h cxxabi_forced.h \
-	exception_defines.h exception_ptr.h hash_bytes.h nested_exception.h
+	exception_defines.h exception_ptr.h hash_bytes.h nested_exception.h exception.h cxxabi_init_exception.h
 
 headers = $(std_HEADERS) $(bits_HEADERS)
 
diff --git a/libstdc++-v3/libsupc++/cxxabi.h b/libstdc++-v3/libsupc++/cxxabi.h
index 11ff9e5..f4b8f75 100644
--- a/libstdc++-v3/libsupc++/cxxabi.h
+++ b/libstdc++-v3/libsupc++/cxxabi.h
@@ -49,10 +49,7 @@ 
 #include <bits/c++config.h>
 #include <bits/cxxabi_tweaks.h>
 #include <bits/cxxabi_forced.h>
-
-#ifndef _GLIBCXX_CDTOR_CALLABI
-#define _GLIBCXX_CDTOR_CALLABI
-#endif
+#include <bits/cxxabi_init_exception.h>
 
 #ifdef __cplusplus
 namespace __cxxabiv1
@@ -608,10 +605,6 @@  namespace __cxxabiv1
   __cxa_eh_globals*
   __cxa_get_globals_fast() _GLIBCXX_NOTHROW __attribute__ ((__const__));
 
-  // Allocate memory for the primary exception plus the thrown object.
-  void*
-  __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW;
-
   // Free the space allocated for the primary exception.
   void 
   __cxa_free_exception(void*) _GLIBCXX_NOTHROW;
diff --git a/libstdc++-v3/libsupc++/cxxabi_init_exception.h b/libstdc++-v3/libsupc++/cxxabi_init_exception.h
new file mode 100644
index 0000000..9af7625
--- /dev/null
+++ b/libstdc++-v3/libsupc++/cxxabi_init_exception.h
@@ -0,0 +1,77 @@ 
+// ABI Support -*- C++ -*-
+
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC 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.
+//
+// GCC 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 bits/cxxabi_init_exception.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly.
+ */
+
+#ifndef _CXXABI_INIT_EXCEPTION_H
+#define _CXXABI_INIT_EXCEPTION_H 1
+
+#pragma GCC system_header
+
+#pragma GCC visibility push(default)
+
+#include <stddef.h>
+#include <bits/c++config.h>
+
+#ifndef _GLIBCXX_CDTOR_CALLABI
+#define _GLIBCXX_CDTOR_CALLABI
+#define _GLIBCXX_HAVE_CDTOR_CALLABI 0
+#else
+#define _GLIBCXX_HAVE_CDTOR_CALLABI 1
+#endif
+
+#ifdef __cplusplus
+
+namespace std
+{
+  class type_info;
+}
+
+namespace __cxxabiv1
+{
+  struct __cxa_refcounted_exception;
+
+  extern "C"
+    {
+      // Allocate memory for the primary exception plus the thrown object.
+      void*
+      __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW;
+
+      // Initialize exception (this is a GNU extension)
+      __cxa_refcounted_exception*
+      __cxa_init_primary_exception(void *object, std::type_info *tinfo,
+                void (_GLIBCXX_CDTOR_CALLABI *dest) (void *)) _GLIBCXX_NOTHROW;
+
+    }
+} // namespace __cxxabiv1
+
+#endif
+
+#pragma GCC visibility pop
+
+#endif // _CXXABI_INIT_EXCEPTION_H
diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc
index 9aac218..a05f4eb 100644
--- a/libstdc++-v3/libsupc++/eh_throw.cc
+++ b/libstdc++-v3/libsupc++/eh_throw.cc
@@ -55,6 +55,22 @@  __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
 #endif
 }
 
+extern "C" __cxa_refcounted_exception*
+__cxxabiv1::__cxa_init_primary_exception(void *obj, std::type_info *tinfo,
+                                         void (_GLIBCXX_CDTOR_CALLABI *dest) (void *))
+{
+  __cxa_refcounted_exception *header
+    = __get_refcounted_exception_header_from_obj (obj);
+  header->referenceCount = 0;
+  header->exc.exceptionType = tinfo;
+  header->exc.exceptionDestructor = dest;
+  header->exc.unexpectedHandler = std::get_unexpected ();
+  header->exc.terminateHandler = std::get_terminate ();
+  __GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->exc.unwindHeader.exception_class);
+  header->exc.unwindHeader.exception_cleanup = __gxx_exception_cleanup;
+
+  return header;
+}
 
 extern "C" void
 __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
@@ -64,17 +80,10 @@  __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
 
   __cxa_eh_globals *globals = __cxa_get_globals ();
   globals->uncaughtExceptions += 1;
-
   // Definitely a primary.
-  __cxa_refcounted_exception *header
-    = __get_refcounted_exception_header_from_obj (obj);
+  __cxa_refcounted_exception *header =
+    __cxa_init_primary_exception(obj, tinfo, dest);
   header->referenceCount = 1;
-  header->exc.exceptionType = tinfo;
-  header->exc.exceptionDestructor = dest;
-  header->exc.unexpectedHandler = std::get_unexpected ();
-  header->exc.terminateHandler = std::get_terminate ();
-  __GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->exc.unwindHeader.exception_class);
-  header->exc.unwindHeader.exception_cleanup = __gxx_exception_cleanup;
 
 #ifdef __USING_SJLJ_EXCEPTIONS__
   _Unwind_SjLj_RaiseException (&header->exc.unwindHeader);
diff --git a/libstdc++-v3/libsupc++/exception b/libstdc++-v3/libsupc++/exception
index 63631f6..8be903b 100644
--- a/libstdc++-v3/libsupc++/exception
+++ b/libstdc++-v3/libsupc++/exception
@@ -36,39 +36,12 @@ 
 
 #include <bits/c++config.h>
 #include <bits/atomic_lockfree_defines.h>
+#include <bits/exception.h>
 
 extern "C++" {
 
 namespace std
 {
-  /**
-   * @defgroup exceptions Exceptions
-   * @ingroup diagnostics
-   *
-   * Classes and functions for reporting errors via exception classes.
-   * @{
-   */
-
-  /**
-   *  @brief Base class for all library exceptions.
-   *
-   *  This is the base class for all exceptions thrown by the standard
-   *  library, and by certain language expressions.  You are free to derive
-   *  your own %exception classes, or use a different hierarchy, or to
-   *  throw non-class data (e.g., fundamental types).
-   */
-  class exception
-  {
-  public:
-    exception() _GLIBCXX_USE_NOEXCEPT { }
-    virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
-
-    /** Returns a C-style character string describing the general cause
-     *  of the current error.  */
-    virtual const char*
-    what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
-  };
-
   /** If an %exception is thrown which is not listed in a function's
    *  %exception specification, one of these may be thrown.  */
   class bad_exception : public exception
diff --git a/libstdc++-v3/libsupc++/exception.h b/libstdc++-v3/libsupc++/exception.h
new file mode 100644
index 0000000..09ac4e0
--- /dev/null
+++ b/libstdc++-v3/libsupc++/exception.h
@@ -0,0 +1,78 @@ 
+// Exception Handling support header for -*- C++ -*-
+
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC 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.
+//
+// GCC 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 bits/exception.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly.
+ */
+
+#ifndef __EXCEPTION_H
+#define __EXCEPTION_H 1
+
+#pragma GCC system_header
+
+#pragma GCC visibility push(default)
+
+#include <bits/c++config.h>
+
+extern "C++" {
+
+namespace std
+{
+  /**
+   * @defgroup exceptions Exceptions
+   * @ingroup diagnostics
+   *
+   * Classes and functions for reporting errors via exception classes.
+   * @{
+   */
+
+  /**
+   *  @brief Base class for all library exceptions.
+   *
+   *  This is the base class for all exceptions thrown by the standard
+   *  library, and by certain language expressions.  You are free to derive
+   *  your own %exception classes, or use a different hierarchy, or to
+   *  throw non-class data (e.g., fundamental types).
+   */
+  class exception
+  {
+  public:
+    exception() _GLIBCXX_USE_NOEXCEPT { }
+    virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
+
+    /** Returns a C-style character string describing the general cause
+     *  of the current error.  */
+    virtual const char*
+    what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
+  };
+
+} // namespace std
+
+}
+
+#pragma GCC visibility pop
+
+#endif
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
index 783e539..21e4e8b 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -35,6 +35,9 @@ 
 
 #include <bits/c++config.h>
 #include <bits/exception_defines.h>
+#include <bits/cxxabi_init_exception.h>
+#include <typeinfo>
+#include <new>
 
 #if ATOMIC_INT_LOCK_FREE < 2
 #  error This platform does not support exception propagation.
@@ -63,6 +66,9 @@  namespace std
    */
   exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT;
 
+  template<typename _Ex>
+  exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
+
   /// Throw the object pointed to by the exception_ptr.
   void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
 
@@ -87,6 +93,8 @@  namespace std
 
       friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT;
       friend void std::rethrow_exception(exception_ptr);
+      template<typename _Ex>
+      friend exception_ptr std::make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
 
     public:
       exception_ptr() _GLIBCXX_USE_NOEXCEPT;
@@ -162,8 +170,12 @@  namespace std
     swap(exception_ptr& __lhs, exception_ptr& __rhs)
     { __lhs.swap(__rhs); }
 
-  } // namespace __exception_ptr
+    template<typename _Ex>
+      inline void
+      __dest_thunk(void* x)
+      { static_cast<_Ex*>(x)->~_Ex(); }
 
+  } // namespace __exception_ptr
 
   /// Obtain an exception_ptr pointing to a copy of the supplied object.
   template<typename _Ex>
@@ -173,7 +185,16 @@  namespace std
 #if __cpp_exceptions
       try
 	{
-	  throw __ex;
+#if __cpp_rtti && !_GLIBCXX_HAVE_CDTOR_CALLABI
+          void *__e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
+          (void)__cxxabiv1::__cxa_init_primary_exception(__e,
+                                           const_cast<std::type_info*>(&typeid(__ex)),
+                                           __exception_ptr::__dest_thunk<_Ex>);
+          new (__e) _Ex(__ex);
+          return exception_ptr(__e);
+#else
+          throw __ex;
+#endif
 	}
       catch(...)
 	{
diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo
index baedf01..1c5ccc5 100644
--- a/libstdc++-v3/libsupc++/typeinfo
+++ b/libstdc++-v3/libsupc++/typeinfo
@@ -31,7 +31,7 @@ 
 
 #pragma GCC system_header
 
-#include <exception>
+#include <bits/exception.h>
 #if __cplusplus >= 201103L
 #include <bits/hash_bytes.h>
 #endif
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 9001345..5174a7f 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -216,6 +216,7 @@  check_version(symbol& test, bool added)
       known_versions.push_back("CXXABI_1.3.8");
       known_versions.push_back("CXXABI_1.3.9");
       known_versions.push_back("CXXABI_1.3.10");
+      known_versions.push_back("CXXABI_1.3.11");
       known_versions.push_back("CXXABI_TM_1");
       known_versions.push_back("CXXABI_FLOAT128");
     }
@@ -234,7 +235,7 @@  check_version(symbol& test, bool added)
 
       // Check that added symbols are added in the latest pre-release version.
       bool latestp = (test.version_name == "GLIBCXX_3.4.23"
-		     || test.version_name == "CXXABI_1.3.10"
+		     || test.version_name == "CXXABI_1.3.11"
 		     || test.version_name == "CXXABI_FLOAT128"
 		     || test.version_name == "CXXABI_TM_1");
       if (added && !latestp)