Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r70974 - in branches/release: boost/exception boost/exception/detail libs/exception/build libs/exception/src libs/exception/test
From: emil_at_[hidden]
Date: 2011-04-04 17:19:50


Author: emildotchevski
Date: 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
New Revision: 70974
URL: http://svn.boost.org/trac/boost/changeset/70974

Log:
Committing changes merged from trunk, most notably optional non-intrusive exception_ptr support for MSVC.
Added:
   branches/release/boost/exception/detail/clone_current_exception.hpp (contents, props changed)
   branches/release/libs/exception/build/
   branches/release/libs/exception/build/Jamfile.v2 (contents, props changed)
   branches/release/libs/exception/src/
   branches/release/libs/exception/src/clone_current_exception_msvc.cpp (contents, props changed)
Text files modified:
   branches/release/boost/exception/detail/exception_ptr.hpp | 313 ++++++++++++++++++++++++---------------
   branches/release/boost/exception/detail/type_info.hpp | 6
   branches/release/boost/exception/diagnostic_information.hpp | 2
   branches/release/boost/exception/errinfo_nested_exception.hpp | 5
   branches/release/boost/exception/exception.hpp | 12 +
   branches/release/libs/exception/test/Jamfile.v2 | 9 +
   branches/release/libs/exception/test/cloning_test.cpp | 33 +++
   branches/release/libs/exception/test/copy_exception_test.cpp | 24 +++
   branches/release/libs/exception/test/exception_ptr_test.cpp | 32 +++
   branches/release/libs/exception/test/unknown_exception_test.cpp | 19 ++
   10 files changed, 321 insertions(+), 134 deletions(-)

Added: branches/release/boost/exception/detail/clone_current_exception.hpp
==============================================================================
--- (empty file)
+++ branches/release/boost/exception/detail/clone_current_exception.hpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -0,0 +1,44 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the Boost Software License, Version 1.0. (See accompanying
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef UUID_81522C0EB56511DFAB613DB0DFD72085
+#define UUID_81522C0EB56511DFAB613DB0DFD72085
+
+#ifdef BOOST_NO_EXCEPTIONS
+#error This header requires exception handling to be enabled.
+#endif
+
+namespace
+boost
+ {
+ namespace
+ exception_detail
+ {
+ namespace
+ clone_current_exception_result
+ {
+ int const success=0;
+ int const bad_alloc=1;
+ int const bad_exception=2;
+ int const not_supported=3;
+ }
+
+ class clone_base;
+ int clone_current_exception_msvc_x86( clone_base const * & cloned );
+
+ inline
+ int
+ clone_current_exception( clone_base const * & cloned )
+ {
+#if defined(BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR) && defined(_MSC_VER) && defined(_M_IX86) && !defined(_M_X64)
+ return clone_current_exception_msvc_x86(cloned);
+#else
+ return clone_current_exception_result::not_supported;
+#endif
+ }
+ }
+ }
+
+#endif

Modified: branches/release/boost/exception/detail/exception_ptr.hpp
==============================================================================
--- branches/release/boost/exception/detail/exception_ptr.hpp (original)
+++ branches/release/boost/exception/detail/exception_ptr.hpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -20,6 +20,7 @@
 #include <boost/exception/info.hpp>
 #include <boost/exception/diagnostic_information.hpp>
 #include <boost/exception/detail/type_info.hpp>
+#include <boost/exception/detail/clone_current_exception.hpp>
 #include <boost/shared_ptr.hpp>
 #include <stdexcept>
 #include <new>
@@ -28,10 +29,42 @@
 namespace
 boost
     {
- typedef shared_ptr<exception_detail::clone_base const> exception_ptr;
-
+ class exception_ptr;
+ BOOST_ATTRIBUTE_NORETURN void rethrow_exception( exception_ptr const & );
     exception_ptr current_exception();
 
+ class
+ exception_ptr
+ {
+ typedef boost::shared_ptr<exception_detail::clone_base const> impl;
+ impl ptr_;
+ friend void rethrow_exception( exception_ptr const & );
+ typedef exception_detail::clone_base const * (impl::*unspecified_bool_type)() const;
+ public:
+ exception_ptr()
+ {
+ }
+ explicit
+ exception_ptr( impl const & ptr ):
+ ptr_(ptr)
+ {
+ }
+ bool
+ operator==( exception_ptr const & other ) const
+ {
+ return ptr_==other.ptr_;
+ }
+ bool
+ operator!=( exception_ptr const & other ) const
+ {
+ return ptr_!=other.ptr_;
+ }
+ operator unspecified_bool_type() const
+ {
+ return ptr_?&impl::get:0;
+ }
+ };
+
     template <class T>
     inline
     exception_ptr
@@ -67,35 +100,49 @@
             boost::exception,
             std::bad_alloc
                 {
+ ~bad_alloc_() throw() { }
                 };
 
- template <int Dummy>
+ struct
+ bad_exception_:
+ boost::exception,
+ std::bad_exception
+ {
+ ~bad_exception_() throw() { }
+ };
+
+ template <class Exception>
         exception_ptr
- get_bad_alloc()
+ get_static_exception_object()
             {
- bad_alloc_ ba;
- exception_detail::clone_impl<bad_alloc_> c(ba);
+ Exception ba;
+ exception_detail::clone_impl<Exception> c(ba);
             c <<
                 throw_function(BOOST_CURRENT_FUNCTION) <<
                 throw_file(__FILE__) <<
                 throw_line(__LINE__);
- static exception_ptr ep(new exception_detail::clone_impl<bad_alloc_>(c));
+ static exception_ptr ep(shared_ptr<exception_detail::clone_base const>(new exception_detail::clone_impl<Exception>(c)));
             return ep;
             }
 
- template <int Dummy>
+ template <class Exception>
         struct
- exception_ptr_bad_alloc
+ exception_ptr_static_exception_object
             {
             static exception_ptr const e;
             };
 
- template <int Dummy>
+ template <class Exception>
         exception_ptr const
- exception_ptr_bad_alloc<Dummy>::
- e = get_bad_alloc<Dummy>();
+ exception_ptr_static_exception_object<Exception>::
+ e = get_static_exception_object<Exception>();
         }
 
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility push (default)
+# endif
+#endif
     class
     unknown_exception:
         public boost::exception,
@@ -135,6 +182,11 @@
 #endif
             }
         };
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility pop
+# endif
+#endif
 
     namespace
     exception_detail
@@ -244,101 +296,131 @@
         exception_ptr
         current_exception_impl()
             {
- try
- {
- throw;
- }
- catch(
- exception_detail::clone_base & e )
- {
- return exception_ptr(e.clone());
- }
- catch(
- std::domain_error & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::invalid_argument & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::length_error & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::out_of_range & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::logic_error & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::range_error & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::overflow_error & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::underflow_error & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::ios_base::failure & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::runtime_error & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::bad_alloc & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
+ exception_detail::clone_base const * e=0;
+ switch(
+ exception_detail::clone_current_exception(e) )
+ {
+ case exception_detail::clone_current_exception_result::
+ success:
+ {
+ BOOST_ASSERT(e!=0);
+ return exception_ptr(shared_ptr<exception_detail::clone_base const>(e));
+ }
+ case exception_detail::clone_current_exception_result::
+ bad_alloc:
+ {
+ BOOST_ASSERT(!e);
+ return exception_detail::exception_ptr_static_exception_object<bad_alloc_>::e;
+ }
+ case exception_detail::clone_current_exception_result::
+ bad_exception:
+ {
+ BOOST_ASSERT(!e);
+ return exception_detail::exception_ptr_static_exception_object<bad_exception_>::e;
+ }
+ default:
+ BOOST_ASSERT(0);
+ case exception_detail::clone_current_exception_result::
+ not_supported:
+ {
+ BOOST_ASSERT(!e);
+ try
+ {
+ throw;
+ }
+ catch(
+ exception_detail::clone_base & e )
+ {
+ return exception_ptr(shared_ptr<exception_detail::clone_base const>(e.clone()));
+ }
+ catch(
+ std::domain_error & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::invalid_argument & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::length_error & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::out_of_range & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::logic_error & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::range_error & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::overflow_error & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::underflow_error & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::ios_base::failure & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::runtime_error & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::bad_alloc & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
 #ifndef BOOST_NO_TYPEID
- catch(
- std::bad_cast & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::bad_typeid & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
+ catch(
+ std::bad_cast & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::bad_typeid & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
 #endif
- catch(
- std::bad_exception & e )
- {
- return exception_detail::current_exception_std_exception(e);
- }
- catch(
- std::exception & e )
- {
- return exception_detail::current_exception_unknown_std_exception(e);
- }
- catch(
- boost::exception & e )
- {
- return exception_detail::current_exception_unknown_boost_exception(e);
- }
- catch(
- ... )
- {
- return exception_detail::current_exception_unknown_exception();
+ catch(
+ std::bad_exception & e )
+ {
+ return exception_detail::current_exception_std_exception(e);
+ }
+ catch(
+ std::exception & e )
+ {
+ return exception_detail::current_exception_unknown_std_exception(e);
+ }
+ catch(
+ boost::exception & e )
+ {
+ return exception_detail::current_exception_unknown_boost_exception(e);
+ }
+ catch(
+ ... )
+ {
+ return exception_detail::current_exception_unknown_exception();
+ }
+ }
                 }
             }
         }
@@ -348,7 +430,6 @@
     current_exception()
         {
         exception_ptr ret;
- BOOST_ASSERT(!ret);
         try
             {
             ret=exception_detail::current_exception_impl();
@@ -356,36 +437,24 @@
         catch(
         std::bad_alloc & )
             {
- ret=exception_detail::exception_ptr_bad_alloc<42>::e;
+ ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_alloc_>::e;
             }
         catch(
         ... )
             {
- try
- {
- ret=exception_detail::current_exception_std_exception(std::bad_exception());
- }
- catch(
- std::bad_alloc & )
- {
- ret=exception_detail::exception_ptr_bad_alloc<42>::e;
- }
- catch(
- ... )
- {
- BOOST_ASSERT(0);
- }
+ ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_exception_>::e;
             }
         BOOST_ASSERT(ret);
         return ret;
         }
 
+ BOOST_ATTRIBUTE_NORETURN
     inline
     void
     rethrow_exception( exception_ptr const & p )
         {
         BOOST_ASSERT(p);
- p->rethrow();
+ p.ptr_->rethrow();
         }
 
     inline

Modified: branches/release/boost/exception/detail/type_info.hpp
==============================================================================
--- branches/release/boost/exception/detail/type_info.hpp (original)
+++ branches/release/boost/exception/detail/type_info.hpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -53,11 +53,11 @@
         struct
         type_info_
             {
- detail::sp_typeinfo const & type_;
+ detail::sp_typeinfo const * type_;
 
             explicit
             type_info_( detail::sp_typeinfo const & type ):
- type_(type)
+ type_(&type)
                 {
                 }
 
@@ -65,7 +65,7 @@
             bool
             operator<( type_info_ const & a, type_info_ const & b )
                 {
- return 0!=(a.type_.before(b.type_));
+ return 0!=(a.type_->before(*b.type_));
                 }
             };
         }

Modified: branches/release/boost/exception/diagnostic_information.hpp
==============================================================================
--- branches/release/boost/exception/diagnostic_information.hpp (original)
+++ branches/release/boost/exception/diagnostic_information.hpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -137,7 +137,7 @@
                 }
 #ifndef BOOST_NO_RTTI
             tmp << std::string("Dynamic exception type: ") <<
- units::detail::demangle((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_.name()) << '\n';
+ units::detail::demangle((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n';
 #endif
             if( with_what && se )
                 tmp << "std::exception::what: " << wh << '\n';

Modified: branches/release/boost/exception/errinfo_nested_exception.hpp
==============================================================================
--- branches/release/boost/exception/errinfo_nested_exception.hpp (original)
+++ branches/release/boost/exception/errinfo_nested_exception.hpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -9,10 +9,9 @@
 namespace
 boost
     {
- namespace exception_detail { class clone_base; };
+ namespace exception_detail { class clone_base; }
     template <class Tag,class T> class error_info;
- template <class T> class shared_ptr;
- typedef shared_ptr<exception_detail::clone_base const> exception_ptr;
+ class exception_ptr;
     typedef error_info<struct errinfo_nested_exception_,exception_ptr> errinfo_nested_exception;
     }
 

Modified: branches/release/boost/exception/exception.hpp
==============================================================================
--- branches/release/boost/exception/exception.hpp (original)
+++ branches/release/boost/exception/exception.hpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -189,6 +189,11 @@
         E const & set_info( E const &, throw_line const & );
         }
 
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility push (default)
+# endif
+#endif
     class
     exception
         {
@@ -250,6 +255,11 @@
         mutable char const * throw_file_;
         mutable int throw_line_;
         };
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility pop
+# endif
+#endif
 
     inline
     exception::
@@ -334,7 +344,7 @@
         struct
         enable_error_info_return_type
             {
- typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception((T*)0))>::type type;
+ typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception(static_cast<T *>(0)))>::type type;
             };
         }
 

Added: branches/release/libs/exception/build/Jamfile.v2
==============================================================================
--- (empty file)
+++ branches/release/libs/exception/build/Jamfile.v2 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -0,0 +1,11 @@
+# Boost Exception Library build Jamfile
+#
+# Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+alias boost_exception ;
+lib boost_exception : ../src/clone_current_exception_msvc.cpp : <toolset>msvc ;
+
+boost-install boost_exception ;

Added: branches/release/libs/exception/src/clone_current_exception_msvc.cpp
==============================================================================
--- (empty file)
+++ branches/release/libs/exception/src/clone_current_exception_msvc.cpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -0,0 +1,295 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the Boost Software License, Version 1.0. (See accompanying
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//This MSVC-specific cpp file implements non-intrusive cloning of exception objects.
+//Based on an exception_ptr implementation by Anthony Williams.
+
+#ifdef BOOST_NO_EXCEPTIONS
+#error This file requires exception handling to be enabled.
+#endif
+
+#if defined(_MSC_VER) && defined(_M_IX86) && !defined(_M_X64)
+
+#include <boost/exception/detail/clone_current_exception.hpp>
+#include <boost/exception/exception.hpp>
+#include <boost/shared_ptr.hpp>
+#ifndef BOOST_NO_RTTI
+#include <typeinfo>
+#endif
+#include <windows.h>
+#include <malloc.h>
+
+namespace
+ {
+ unsigned const exception_maximum_parameters=15;
+ unsigned const exception_noncontinuable=1;
+
+#if _MSC_VER==1310
+ int const exception_info_offset=0x74;
+#elif (_MSC_VER==1400 || _MSC_VER==1500)
+ int const exception_info_offset=0x80;
+#else
+ int const exception_info_offset=-1;
+#endif
+
+ struct
+ exception_record
+ {
+ unsigned long ExceptionCode;
+ unsigned long ExceptionFlags;
+ exception_record * ExceptionRecord;
+ void * ExceptionAddress;
+ unsigned long NumberParameters;
+ ULONG_PTR ExceptionInformation[exception_maximum_parameters];
+ };
+
+ struct
+ exception_pointers
+ {
+ exception_record * ExceptionRecord;
+ void * ContextRecord;
+ };
+
+ unsigned const cpp_exception_code=0xE06D7363;
+ unsigned const cpp_exception_magic_flag=0x19930520;
+ unsigned const cpp_exception_parameter_count=3;
+
+ struct
+ dummy_exception_type
+ {
+ };
+
+ typedef int(dummy_exception_type::*normal_copy_constructor_ptr)(void * src);
+ typedef int(dummy_exception_type::*copy_constructor_with_virtual_base_ptr)(void * src,void * dst);
+ typedef void (dummy_exception_type::*destructor_ptr)();
+
+ union
+ cpp_copy_constructor
+ {
+ normal_copy_constructor_ptr normal_copy_constructor;
+ copy_constructor_with_virtual_base_ptr copy_constructor_with_virtual_base;
+ };
+
+ enum
+ cpp_type_flags
+ {
+ class_is_simple_type=1,
+ class_has_virtual_base=4
+ };
+
+ struct
+ cpp_type_info
+ {
+ unsigned flags;
+#ifndef BOOST_NO_RTTI
+ void const * type_info;
+#else
+ std::type_info * type_info;
+#endif
+ int this_offset;
+ int vbase_descr;
+ int vbase_offset;
+ unsigned long size;
+ cpp_copy_constructor copy_constructor;
+ };
+
+ struct
+ cpp_type_info_table
+ {
+ unsigned count;
+ const cpp_type_info * info[1];
+ };
+
+ struct
+ cpp_exception_type
+ {
+ unsigned flags;
+ destructor_ptr destructor;
+ void(*custom_handler)();
+ cpp_type_info_table const * type_info_table;
+ };
+
+ struct
+ exception_object_deleter
+ {
+ cpp_exception_type const & et_;
+
+ exception_object_deleter( cpp_exception_type const & et ):
+ et_(et)
+ {
+ }
+
+ void
+ operator()( void * obj )
+ {
+ BOOST_ASSERT(obj!=0);
+ dummy_exception_type * dummy_exception_ptr=reinterpret_cast<dummy_exception_type *>(obj);
+ (dummy_exception_ptr->*(et_.destructor))();
+ free(obj);
+ }
+ };
+
+ cpp_type_info const &
+ get_cpp_type_info( cpp_exception_type const & et )
+ {
+ cpp_type_info const * ti = et.type_info_table->info[0];
+ BOOST_ASSERT(ti!=0);
+ return *ti;
+ }
+
+ void
+ copy_msvc_exception( void * dst, void * src, cpp_type_info const & ti )
+ {
+ if( !(ti.flags & class_is_simple_type) && ti.copy_constructor.normal_copy_constructor )
+ {
+ dummy_exception_type * dummy_exception_ptr = reinterpret_cast<dummy_exception_type *>(dst);
+ if( ti.flags & class_has_virtual_base )
+ (dummy_exception_ptr->*(ti.copy_constructor.copy_constructor_with_virtual_base))(src,dst);
+ else
+ (dummy_exception_ptr->*(ti.copy_constructor.normal_copy_constructor))(src);
+ }
+ else
+ memmove(dst,src,ti.size);
+ }
+
+ boost::shared_ptr<void>
+ clone_msvc_exception( void * src, cpp_exception_type const & et )
+ {
+ assert(src!=0);
+ cpp_type_info const & ti=get_cpp_type_info(et);
+ if( void * dst = malloc(ti.size) )
+ {
+ try
+ {
+ copy_msvc_exception(dst,src,ti);
+ }
+ catch(
+ ... )
+ {
+ free(dst);
+ throw;
+ }
+ return boost::shared_ptr<void>(dst,exception_object_deleter(et));
+ }
+ else
+ throw std::bad_alloc();
+ }
+
+ class
+ cloned_exception:
+ public boost::exception_detail::clone_base
+ {
+ cloned_exception( cloned_exception const & );
+ cloned_exception & operator=( cloned_exception const & );
+
+ cpp_exception_type const & et_;
+ boost::shared_ptr<void> exc_;
+
+ public:
+
+ cloned_exception( void * exc, cpp_exception_type const & et ):
+ et_(et),
+ exc_(clone_msvc_exception(exc,et_))
+ {
+ }
+
+ ~cloned_exception() throw()
+ {
+ }
+
+ boost::exception_detail::clone_base const *
+ clone() const
+ {
+ return new cloned_exception(exc_.get(),et_);
+ }
+
+ void
+ rethrow() const
+ {
+ cpp_type_info const & ti=get_cpp_type_info(et_);
+ void * dst = _alloca(ti.size);
+ copy_msvc_exception(dst,exc_.get(),ti);
+ ULONG_PTR args[cpp_exception_parameter_count];
+ args[0]=cpp_exception_magic_flag;
+ args[1]=reinterpret_cast<ULONG_PTR>(dst);
+ args[2]=reinterpret_cast<ULONG_PTR>(&et_);
+ RaiseException(cpp_exception_code,EXCEPTION_NONCONTINUABLE,cpp_exception_parameter_count,args);
+ }
+ };
+
+ bool
+ is_cpp_exception( EXCEPTION_RECORD const * record )
+ {
+ return record &&
+ (record->ExceptionCode==cpp_exception_code) &&
+ (record->NumberParameters==cpp_exception_parameter_count) &&
+ (record->ExceptionInformation[0]==cpp_exception_magic_flag);
+ }
+
+ unsigned long
+ exception_cloning_filter( int & result, boost::exception_detail::clone_base const * & ptr, void * info_ )
+ {
+ BOOST_ASSERT(exception_info_offset>=0);
+ BOOST_ASSERT(info_!=0);
+ EXCEPTION_POINTERS * info=reinterpret_cast<EXCEPTION_POINTERS *>(info_);
+ EXCEPTION_RECORD * record=info->ExceptionRecord;
+ if( is_cpp_exception(record) )
+ {
+ if( !record->ExceptionInformation[2] )
+ record = *reinterpret_cast<EXCEPTION_RECORD * *>(reinterpret_cast<char *>(_errno())+exception_info_offset);
+ if( is_cpp_exception(record) && record->ExceptionInformation[2] )
+ try
+ {
+ ptr = new cloned_exception(
+ reinterpret_cast<void *>(record->ExceptionInformation[1]),
+ *reinterpret_cast<cpp_exception_type const *>(record->ExceptionInformation[2]));
+ result = boost::exception_detail::clone_current_exception_result::success;
+ }
+ catch(
+ std::bad_alloc & )
+ {
+ result = boost::exception_detail::clone_current_exception_result::bad_alloc;
+ }
+ catch(
+ ... )
+ {
+ result = boost::exception_detail::clone_current_exception_result::bad_exception;
+ }
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+ }
+
+namespace
+boost
+ {
+ namespace
+ exception_detail
+ {
+ int
+ clone_current_exception_msvc_x86( clone_base const * & cloned )
+ {
+ BOOST_ASSERT(!cloned);
+ int result = clone_current_exception_result::not_supported;
+ if( exception_info_offset>=0 )
+ {
+ clone_base const * ptr=0;
+ __try
+ {
+ throw;
+ }
+ __except(exception_cloning_filter(result,ptr,GetExceptionInformation()))
+ {
+ }
+ if( result==clone_current_exception_result::success )
+ cloned=ptr;
+ }
+ BOOST_ASSERT(result!=clone_current_exception_result::success || cloned);
+ return result;
+ }
+ }
+ }
+
+#endif

Modified: branches/release/libs/exception/test/Jamfile.v2
==============================================================================
--- branches/release/libs/exception/test/Jamfile.v2 (original)
+++ branches/release/libs/exception/test/Jamfile.v2 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -7,7 +7,13 @@
 
 import testing ;
 
-project : requirements <exception-handling>on ;
+project
+ : requirements
+ <link>static
+ <exception-handling>on
+ <source>/boost//exception
+ <define>BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR
+ ;
 
 #to_string
 
@@ -37,6 +43,7 @@
 run no_exceptions_test.cpp : : : <exception-handling>off ;
 run errinfos_test.cpp ;
 run exception_ptr_test.cpp /boost//thread : : : <threading>multi ;
+
 compile-fail exception_fail.cpp ;
 compile-fail throw_exception_fail.cpp ;
 compile-fail error_info_const_fail.cpp ;

Modified: branches/release/libs/exception/test/cloning_test.cpp
==============================================================================
--- branches/release/libs/exception/test/cloning_test.cpp (original)
+++ branches/release/libs/exception/test/cloning_test.cpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -146,6 +146,10 @@
 #endif
             }
         catch(
+ T & )
+ {
+ }
+ catch(
         ... )
             {
             BOOST_TEST(false);
@@ -176,7 +180,7 @@
         catch(
         T & x )
             {
- BOOST_TEST(std::string("what")==x.what());
+ BOOST_TEST(std::string(x.what()).find("what")!=std::string::npos);
             boost::exception_ptr p = boost::current_exception();
             BOOST_TEST(!(p==boost::exception_ptr()));
             BOOST_TEST(p!=boost::exception_ptr());
@@ -189,7 +193,7 @@
             catch(
             T & x )
                 {
- BOOST_TEST(std::string("what")==x.what());
+ BOOST_TEST(std::string(x.what()).find("what")!=std::string::npos);
                 }
             catch(
             ... )
@@ -216,6 +220,10 @@
 #endif
             }
         catch(
+ T & )
+ {
+ }
+ catch(
         ... )
             {
             BOOST_TEST(false);
@@ -385,6 +393,11 @@
             BOOST_TEST(false);
             }
         catch(
+ derives_std_exception & )
+ {
+ //Yay! Non-intrusive cloning supported!
+ }
+ catch(
         boost::unknown_exception & e )
             {
 #ifndef BOOST_NO_RTTI
@@ -434,6 +447,14 @@
             BOOST_TEST(false);
             }
         catch(
+ derives_std_boost_exception & x )
+ {
+ //Yay! Non-intrusive cloning supported!
+ BOOST_TEST(boost::get_error_info<my_info>(x));
+ if( int const * p=boost::get_error_info<my_info>(x) )
+ BOOST_TEST(*p==42);
+ }
+ catch(
         boost::unknown_exception & x )
             {
             BOOST_TEST(boost::get_error_info<my_info>(x));
@@ -495,6 +516,14 @@
             BOOST_TEST(false);
             }
         catch(
+ derives_boost_exception & x )
+ {
+ //Yay! Non-intrusive cloning supported!
+ BOOST_TEST(boost::get_error_info<my_info>(x));
+ if( int const * p=boost::get_error_info<my_info>(x) )
+ BOOST_TEST(*p==42);
+ }
+ catch(
         boost::unknown_exception & x )
             {
             BOOST_TEST(boost::get_error_info<my_info>(x));

Modified: branches/release/libs/exception/test/copy_exception_test.cpp
==============================================================================
--- branches/release/libs/exception/test/copy_exception_test.cpp (original)
+++ branches/release/libs/exception/test/copy_exception_test.cpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -6,15 +6,37 @@
 #include <boost/exception_ptr.hpp>
 #include <boost/exception/get_error_info.hpp>
 #include <boost/thread.hpp>
+#include <boost/detail/atomic_count.hpp>
 #include <boost/detail/lightweight_test.hpp>
 
 typedef boost::error_info<struct tag_answer,int> answer;
 
+boost::detail::atomic_count exc_count(0);
+
 struct
 err:
     virtual boost::exception,
     virtual std::exception
     {
+ err()
+ {
+ ++exc_count;
+ }
+
+ err( err const & )
+ {
+ ++exc_count;
+ }
+
+ virtual
+ ~err() throw()
+ {
+ --exc_count;
+ }
+
+ private:
+
+ err & operator=( err const & );
     };
 
 class
@@ -116,7 +138,9 @@
 int
 main()
     {
+ BOOST_TEST(++exc_count==1);
     simple_test();
     thread_test();
+ BOOST_TEST(!--exc_count);
     return boost::report_errors();
     }

Modified: branches/release/libs/exception/test/exception_ptr_test.cpp
==============================================================================
--- branches/release/libs/exception/test/exception_ptr_test.cpp (original)
+++ branches/release/libs/exception/test/exception_ptr_test.cpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -10,6 +10,7 @@
 #include <boost/function.hpp>
 #include <boost/bind.hpp>
 #include <boost/thread.hpp>
+#include <boost/detail/atomic_count.hpp>
 #include <boost/detail/lightweight_test.hpp>
 #include <iostream>
 
@@ -66,7 +67,34 @@
         rethrow_exception(t.err_);
     }
 
-struct exc: boost::exception, std::exception { };
+boost::detail::atomic_count exc_count(0);
+
+struct
+exc:
+ virtual boost::exception,
+ virtual std::exception
+ {
+ exc()
+ {
+ ++exc_count;
+ }
+
+ exc( exc const & )
+ {
+ ++exc_count;
+ }
+
+ virtual
+ ~exc() throw()
+ {
+ --exc_count;
+ }
+
+ private:
+
+ exc & operator=( exc const & );
+ };
+
 typedef boost::error_info<struct answer_,int> answer;
 
 void
@@ -93,6 +121,7 @@
 int
 main()
     {
+ BOOST_TEST(++exc_count==1);
     try
         {
         std::vector< boost::shared_ptr<thread_handle> > threads;
@@ -109,4 +138,5 @@
             boost::current_exception_diagnostic_information() << std::endl;
         return 42;
         }
+ BOOST_TEST(!--exc_count);
     }

Modified: branches/release/libs/exception/test/unknown_exception_test.cpp
==============================================================================
--- branches/release/libs/exception/test/unknown_exception_test.cpp (original)
+++ branches/release/libs/exception/test/unknown_exception_test.cpp 2011-04-04 17:19:48 EDT (Mon, 04 Apr 2011)
@@ -62,6 +62,15 @@
                 BOOST_TEST(false);
             }
         catch(
+ boost::exception & x )
+ {
+ //Yay! Non-intrusive cloning supported!
+ if( int const * d=boost::get_error_info<test>(x) )
+ BOOST_TEST( 42==*d );
+ else
+ BOOST_TEST(false);
+ }
+ catch(
         ... )
             {
             BOOST_TEST(false);
@@ -101,6 +110,11 @@
             {
             }
         catch(
+ std::exception & )
+ {
+ //Yay! Non-intrusive cloning supported!
+ }
+ catch(
         ... )
             {
             BOOST_TEST(false);
@@ -114,6 +128,11 @@
             {
             }
         catch(
+ std::exception & )
+ {
+ //Yay! Non-intrusive cloning supported!
+ }
+ catch(
         ... )
             {
             BOOST_TEST(false);


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk