forked from boostorg/exception
Committing changes merged from trunk, most notably optional non-intrusive exception_ptr support for MSVC.
[SVN r70974]
This commit is contained in:
11
build/Jamfile.v2
Normal file
11
build/Jamfile.v2
Normal file
@ -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 ;
|
44
include/boost/exception/detail/clone_current_exception.hpp
Normal file
44
include/boost/exception/detail/clone_current_exception.hpp
Normal file
@ -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
|
@ -20,6 +20,7 @@
|
|||||||
#include <boost/exception/info.hpp>
|
#include <boost/exception/info.hpp>
|
||||||
#include <boost/exception/diagnostic_information.hpp>
|
#include <boost/exception/diagnostic_information.hpp>
|
||||||
#include <boost/exception/detail/type_info.hpp>
|
#include <boost/exception/detail/type_info.hpp>
|
||||||
|
#include <boost/exception/detail/clone_current_exception.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <new>
|
#include <new>
|
||||||
@ -28,10 +29,42 @@
|
|||||||
namespace
|
namespace
|
||||||
boost
|
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();
|
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>
|
template <class T>
|
||||||
inline
|
inline
|
||||||
exception_ptr
|
exception_ptr
|
||||||
@ -67,35 +100,49 @@ boost
|
|||||||
boost::exception,
|
boost::exception,
|
||||||
std::bad_alloc
|
std::bad_alloc
|
||||||
{
|
{
|
||||||
|
~bad_alloc_() throw() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int Dummy>
|
struct
|
||||||
exception_ptr
|
bad_exception_:
|
||||||
get_bad_alloc()
|
boost::exception,
|
||||||
|
std::bad_exception
|
||||||
{
|
{
|
||||||
bad_alloc_ ba;
|
~bad_exception_() throw() { }
|
||||||
exception_detail::clone_impl<bad_alloc_> c(ba);
|
};
|
||||||
|
|
||||||
|
template <class Exception>
|
||||||
|
exception_ptr
|
||||||
|
get_static_exception_object()
|
||||||
|
{
|
||||||
|
Exception ba;
|
||||||
|
exception_detail::clone_impl<Exception> c(ba);
|
||||||
c <<
|
c <<
|
||||||
throw_function(BOOST_CURRENT_FUNCTION) <<
|
throw_function(BOOST_CURRENT_FUNCTION) <<
|
||||||
throw_file(__FILE__) <<
|
throw_file(__FILE__) <<
|
||||||
throw_line(__LINE__);
|
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;
|
return ep;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int Dummy>
|
template <class Exception>
|
||||||
struct
|
struct
|
||||||
exception_ptr_bad_alloc
|
exception_ptr_static_exception_object
|
||||||
{
|
{
|
||||||
static exception_ptr const e;
|
static exception_ptr const e;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int Dummy>
|
template <class Exception>
|
||||||
exception_ptr const
|
exception_ptr const
|
||||||
exception_ptr_bad_alloc<Dummy>::
|
exception_ptr_static_exception_object<Exception>::
|
||||||
e = get_bad_alloc<Dummy>();
|
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
|
class
|
||||||
unknown_exception:
|
unknown_exception:
|
||||||
public boost::exception,
|
public boost::exception,
|
||||||
@ -135,6 +182,11 @@ boost
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||||
|
# pragma GCC visibility pop
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
exception_detail
|
exception_detail
|
||||||
@ -244,6 +296,34 @@ boost
|
|||||||
exception_ptr
|
exception_ptr
|
||||||
current_exception_impl()
|
current_exception_impl()
|
||||||
{
|
{
|
||||||
|
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
|
try
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
@ -251,7 +331,7 @@ boost
|
|||||||
catch(
|
catch(
|
||||||
exception_detail::clone_base & e )
|
exception_detail::clone_base & e )
|
||||||
{
|
{
|
||||||
return exception_ptr(e.clone());
|
return exception_ptr(shared_ptr<exception_detail::clone_base const>(e.clone()));
|
||||||
}
|
}
|
||||||
catch(
|
catch(
|
||||||
std::domain_error & e )
|
std::domain_error & e )
|
||||||
@ -342,13 +422,14 @@ boost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
exception_ptr
|
exception_ptr
|
||||||
current_exception()
|
current_exception()
|
||||||
{
|
{
|
||||||
exception_ptr ret;
|
exception_ptr ret;
|
||||||
BOOST_ASSERT(!ret);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ret=exception_detail::current_exception_impl();
|
ret=exception_detail::current_exception_impl();
|
||||||
@ -356,36 +437,24 @@ boost
|
|||||||
catch(
|
catch(
|
||||||
std::bad_alloc & )
|
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(
|
catch(
|
||||||
... )
|
... )
|
||||||
{
|
{
|
||||||
try
|
ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_exception_>::e;
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(ret);
|
BOOST_ASSERT(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_ATTRIBUTE_NORETURN
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
rethrow_exception( exception_ptr const & p )
|
rethrow_exception( exception_ptr const & p )
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(p);
|
BOOST_ASSERT(p);
|
||||||
p->rethrow();
|
p.ptr_->rethrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
@ -53,11 +53,11 @@ boost
|
|||||||
struct
|
struct
|
||||||
type_info_
|
type_info_
|
||||||
{
|
{
|
||||||
detail::sp_typeinfo const & type_;
|
detail::sp_typeinfo const * type_;
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
type_info_( detail::sp_typeinfo const & type ):
|
type_info_( detail::sp_typeinfo const & type ):
|
||||||
type_(type)
|
type_(&type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ boost
|
|||||||
bool
|
bool
|
||||||
operator<( type_info_ const & a, type_info_ const & b )
|
operator<( type_info_ const & a, type_info_ const & b )
|
||||||
{
|
{
|
||||||
return 0!=(a.type_.before(b.type_));
|
return 0!=(a.type_->before(*b.type_));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ boost
|
|||||||
}
|
}
|
||||||
#ifndef BOOST_NO_RTTI
|
#ifndef BOOST_NO_RTTI
|
||||||
tmp << std::string("Dynamic exception type: ") <<
|
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
|
#endif
|
||||||
if( with_what && se )
|
if( with_what && se )
|
||||||
tmp << "std::exception::what: " << wh << '\n';
|
tmp << "std::exception::what: " << wh << '\n';
|
||||||
|
@ -9,10 +9,9 @@
|
|||||||
namespace
|
namespace
|
||||||
boost
|
boost
|
||||||
{
|
{
|
||||||
namespace exception_detail { class clone_base; };
|
namespace exception_detail { class clone_base; }
|
||||||
template <class Tag,class T> class error_info;
|
template <class Tag,class T> class error_info;
|
||||||
template <class T> class shared_ptr;
|
class exception_ptr;
|
||||||
typedef shared_ptr<exception_detail::clone_base const> exception_ptr;
|
|
||||||
typedef error_info<struct errinfo_nested_exception_,exception_ptr> errinfo_nested_exception;
|
typedef error_info<struct errinfo_nested_exception_,exception_ptr> errinfo_nested_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +189,11 @@ boost
|
|||||||
E const & set_info( E const &, throw_line const & );
|
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
|
class
|
||||||
exception
|
exception
|
||||||
{
|
{
|
||||||
@ -250,6 +255,11 @@ boost
|
|||||||
mutable char const * throw_file_;
|
mutable char const * throw_file_;
|
||||||
mutable int throw_line_;
|
mutable int throw_line_;
|
||||||
};
|
};
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||||
|
# pragma GCC visibility pop
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
inline
|
inline
|
||||||
exception::
|
exception::
|
||||||
@ -334,7 +344,7 @@ boost
|
|||||||
struct
|
struct
|
||||||
enable_error_info_return_type
|
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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
295
src/clone_current_exception_msvc.cpp
Normal file
295
src/clone_current_exception_msvc.cpp
Normal file
@ -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
|
@ -7,7 +7,13 @@
|
|||||||
|
|
||||||
import testing ;
|
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
|
#to_string
|
||||||
|
|
||||||
@ -37,6 +43,7 @@ run current_exception_cast_test.cpp ;
|
|||||||
run no_exceptions_test.cpp : : : <exception-handling>off ;
|
run no_exceptions_test.cpp : : : <exception-handling>off ;
|
||||||
run errinfos_test.cpp ;
|
run errinfos_test.cpp ;
|
||||||
run exception_ptr_test.cpp /boost//thread : : : <threading>multi ;
|
run exception_ptr_test.cpp /boost//thread : : : <threading>multi ;
|
||||||
|
|
||||||
compile-fail exception_fail.cpp ;
|
compile-fail exception_fail.cpp ;
|
||||||
compile-fail throw_exception_fail.cpp ;
|
compile-fail throw_exception_fail.cpp ;
|
||||||
compile-fail error_info_const_fail.cpp ;
|
compile-fail error_info_const_fail.cpp ;
|
||||||
|
@ -146,6 +146,10 @@ test_std_exception()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
catch(
|
catch(
|
||||||
|
T & )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch(
|
||||||
... )
|
... )
|
||||||
{
|
{
|
||||||
BOOST_TEST(false);
|
BOOST_TEST(false);
|
||||||
@ -176,7 +180,7 @@ test_std_exception_what()
|
|||||||
catch(
|
catch(
|
||||||
T & x )
|
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::exception_ptr p = boost::current_exception();
|
||||||
BOOST_TEST(!(p==boost::exception_ptr()));
|
BOOST_TEST(!(p==boost::exception_ptr()));
|
||||||
BOOST_TEST(p!=boost::exception_ptr());
|
BOOST_TEST(p!=boost::exception_ptr());
|
||||||
@ -189,7 +193,7 @@ test_std_exception_what()
|
|||||||
catch(
|
catch(
|
||||||
T & x )
|
T & x )
|
||||||
{
|
{
|
||||||
BOOST_TEST(std::string("what")==x.what());
|
BOOST_TEST(std::string(x.what()).find("what")!=std::string::npos);
|
||||||
}
|
}
|
||||||
catch(
|
catch(
|
||||||
... )
|
... )
|
||||||
@ -216,6 +220,10 @@ test_std_exception_what()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
catch(
|
catch(
|
||||||
|
T & )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch(
|
||||||
... )
|
... )
|
||||||
{
|
{
|
||||||
BOOST_TEST(false);
|
BOOST_TEST(false);
|
||||||
@ -385,6 +393,11 @@ main()
|
|||||||
BOOST_TEST(false);
|
BOOST_TEST(false);
|
||||||
}
|
}
|
||||||
catch(
|
catch(
|
||||||
|
derives_std_exception & )
|
||||||
|
{
|
||||||
|
//Yay! Non-intrusive cloning supported!
|
||||||
|
}
|
||||||
|
catch(
|
||||||
boost::unknown_exception & e )
|
boost::unknown_exception & e )
|
||||||
{
|
{
|
||||||
#ifndef BOOST_NO_RTTI
|
#ifndef BOOST_NO_RTTI
|
||||||
@ -434,6 +447,14 @@ main()
|
|||||||
BOOST_TEST(false);
|
BOOST_TEST(false);
|
||||||
}
|
}
|
||||||
catch(
|
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::unknown_exception & x )
|
||||||
{
|
{
|
||||||
BOOST_TEST(boost::get_error_info<my_info>(x));
|
BOOST_TEST(boost::get_error_info<my_info>(x));
|
||||||
@ -495,6 +516,14 @@ main()
|
|||||||
BOOST_TEST(false);
|
BOOST_TEST(false);
|
||||||
}
|
}
|
||||||
catch(
|
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::unknown_exception & x )
|
||||||
{
|
{
|
||||||
BOOST_TEST(boost::get_error_info<my_info>(x));
|
BOOST_TEST(boost::get_error_info<my_info>(x));
|
||||||
|
@ -6,15 +6,37 @@
|
|||||||
#include <boost/exception_ptr.hpp>
|
#include <boost/exception_ptr.hpp>
|
||||||
#include <boost/exception/get_error_info.hpp>
|
#include <boost/exception/get_error_info.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/detail/atomic_count.hpp>
|
||||||
#include <boost/detail/lightweight_test.hpp>
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
|
||||||
typedef boost::error_info<struct tag_answer,int> answer;
|
typedef boost::error_info<struct tag_answer,int> answer;
|
||||||
|
|
||||||
|
boost::detail::atomic_count exc_count(0);
|
||||||
|
|
||||||
struct
|
struct
|
||||||
err:
|
err:
|
||||||
virtual boost::exception,
|
virtual boost::exception,
|
||||||
virtual std::exception
|
virtual std::exception
|
||||||
{
|
{
|
||||||
|
err()
|
||||||
|
{
|
||||||
|
++exc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
err( err const & )
|
||||||
|
{
|
||||||
|
++exc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual
|
||||||
|
~err() throw()
|
||||||
|
{
|
||||||
|
--exc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
err & operator=( err const & );
|
||||||
};
|
};
|
||||||
|
|
||||||
class
|
class
|
||||||
@ -116,7 +138,9 @@ simple_test()
|
|||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
BOOST_TEST(++exc_count==1);
|
||||||
simple_test();
|
simple_test();
|
||||||
thread_test();
|
thread_test();
|
||||||
|
BOOST_TEST(!--exc_count);
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/detail/atomic_count.hpp>
|
||||||
#include <boost/detail/lightweight_test.hpp>
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -66,7 +67,34 @@ join( thread_handle & t )
|
|||||||
rethrow_exception(t.err_);
|
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;
|
typedef boost::error_info<struct answer_,int> answer;
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -93,6 +121,7 @@ check( boost::shared_ptr<thread_handle> const & t )
|
|||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
BOOST_TEST(++exc_count==1);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::vector< boost::shared_ptr<thread_handle> > threads;
|
std::vector< boost::shared_ptr<thread_handle> > threads;
|
||||||
@ -109,4 +138,5 @@ main()
|
|||||||
boost::current_exception_diagnostic_information() << std::endl;
|
boost::current_exception_diagnostic_information() << std::endl;
|
||||||
return 42;
|
return 42;
|
||||||
}
|
}
|
||||||
|
BOOST_TEST(!--exc_count);
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,15 @@ main()
|
|||||||
BOOST_TEST(false);
|
BOOST_TEST(false);
|
||||||
}
|
}
|
||||||
catch(
|
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);
|
BOOST_TEST(false);
|
||||||
@ -101,6 +110,11 @@ main()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
catch(
|
catch(
|
||||||
|
std::exception & )
|
||||||
|
{
|
||||||
|
//Yay! Non-intrusive cloning supported!
|
||||||
|
}
|
||||||
|
catch(
|
||||||
... )
|
... )
|
||||||
{
|
{
|
||||||
BOOST_TEST(false);
|
BOOST_TEST(false);
|
||||||
@ -114,6 +128,11 @@ main()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
catch(
|
catch(
|
||||||
|
std::exception & )
|
||||||
|
{
|
||||||
|
//Yay! Non-intrusive cloning supported!
|
||||||
|
}
|
||||||
|
catch(
|
||||||
... )
|
... )
|
||||||
{
|
{
|
||||||
BOOST_TEST(false);
|
BOOST_TEST(false);
|
||||||
|
Reference in New Issue
Block a user