Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:37:42

0001 #ifndef BOOST_LEAF_EXCEPTION_HPP_INCLUDED
0002 #define BOOST_LEAF_EXCEPTION_HPP_INCLUDED
0003 
0004 // Copyright 2018-2024 Emil Dotchevski and Reverge Studios, Inc.
0005 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #include <boost/leaf/config.hpp>
0009 #include <boost/leaf/error.hpp>
0010 #include <exception>
0011 #include <typeinfo>
0012 
0013 #ifdef BOOST_LEAF_NO_EXCEPTIONS
0014 
0015 namespace boost
0016 {
0017     [[noreturn]] void throw_exception( std::exception const & ); // user defined
0018 }
0019 
0020 namespace boost { namespace leaf {
0021 
0022 namespace detail
0023 {
0024     template <class T>
0025     [[noreturn]] void throw_exception_impl( T && e )
0026     {
0027         ::boost::throw_exception(std::move(e));
0028     }
0029 }
0030 
0031 } }
0032 
0033 #else
0034 
0035 namespace boost { namespace leaf {
0036 
0037 namespace detail
0038 {
0039     template <class T>
0040     [[noreturn]] void throw_exception_impl( T && e )
0041     {
0042         throw std::move(e);
0043     }
0044 }
0045 
0046 } }
0047 
0048 #endif
0049 
0050 ////////////////////////////////////////
0051 
0052 #define BOOST_LEAF_THROW_EXCEPTION ::boost::leaf::detail::throw_with_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::detail::make_exception
0053 
0054 namespace boost { namespace leaf {
0055 
0056 namespace detail
0057 {
0058     struct throw_with_loc
0059     {
0060         char const * const file;
0061         int const line;
0062         char const * const fn;
0063 
0064         template <class Ex>
0065         [[noreturn]] friend void operator+( throw_with_loc loc, Ex && ex )
0066         {
0067             ex.load_source_location_(loc.file, loc.line, loc.fn);
0068             ::boost::leaf::detail::throw_exception_impl(std::move(ex));
0069         }
0070     };
0071 }
0072 
0073 ////////////////////////////////////////
0074 
0075 namespace detail
0076 {
0077     inline void enforce_std_exception( std::exception const & ) noexcept { }
0078 
0079     template <class Ex>
0080     class BOOST_LEAF_SYMBOL_VISIBLE exception:
0081         public Ex,
0082         public exception_base,
0083         public error_id
0084     {
0085         mutable bool clear_current_error_;
0086 
0087         bool is_current_exception() const noexcept
0088         {
0089             return tls::read_uint<detail::tls_tag_id_factory_current_id>() == unsigned(error_id::value());
0090         }
0091 
0092         error_id get_error_id() const noexcept final override
0093         {
0094             clear_current_error_ = false;
0095             return *this;
0096         }
0097 
0098 #if BOOST_LEAF_CFG_DIAGNOSTICS && !defined(BOOST_LEAF_NO_EXCEPTIONS)
0099         void print_type_name(std::ostream & os) const final override
0100         {
0101             detail::demangle_and_print(os, typeid(Ex).name());
0102         }
0103 #endif
0104 
0105     public:
0106 
0107         exception( exception const & other ):
0108             Ex(other),
0109             exception_base(other),
0110             error_id(other),
0111             clear_current_error_(other.clear_current_error_)
0112         {
0113             other.clear_current_error_ = false;
0114         }
0115 
0116         exception( exception && other ) noexcept:
0117             Ex(std::move(other)),
0118             exception_base(std::move(other)),
0119             error_id(std::move(other)),
0120             clear_current_error_(std::move(other.clear_current_error_))
0121         {
0122             other.clear_current_error_ = false;
0123         }
0124 
0125         exception( error_id id, Ex const & ex ) noexcept:
0126             Ex(ex),
0127             error_id(id),
0128             clear_current_error_(true)
0129         {
0130             enforce_std_exception(*this);
0131         }
0132 
0133         exception( error_id id, Ex && ex ) noexcept:
0134             Ex(std::move(ex)),
0135             error_id(id),
0136             clear_current_error_(true)
0137         {
0138             enforce_std_exception(*this);
0139         }
0140 
0141         explicit exception( error_id id ) noexcept:
0142             error_id(id),
0143             clear_current_error_(true)
0144         {
0145             enforce_std_exception(*this);
0146         }
0147 
0148         ~exception() noexcept
0149         {
0150             if( clear_current_error_ && is_current_exception() )
0151                 tls::write_uint<detail::tls_tag_id_factory_current_id>(0);
0152         }
0153     };
0154 
0155     template <class... T>
0156     struct at_least_one_derives_from_std_exception;
0157 
0158     template <>
0159     struct at_least_one_derives_from_std_exception<>: std::false_type { };
0160 
0161     template <class T, class... Rest>
0162     struct at_least_one_derives_from_std_exception<T, Rest...>
0163     {
0164         constexpr static const bool value = std::is_base_of<std::exception,typename std::remove_reference<T>::type>::value || at_least_one_derives_from_std_exception<Rest...>::value;
0165     };
0166 
0167     template <class Ex, class... E>
0168     inline
0169     typename std::enable_if<std::is_base_of<std::exception,typename std::remove_reference<Ex>::type>::value, exception<typename std::remove_reference<Ex>::type>>::type
0170     make_exception( error_id err, Ex && ex, E && ... e ) noexcept
0171     {
0172         static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0173         return exception<typename std::remove_reference<Ex>::type>( err.load(std::forward<E>(e)...), std::forward<Ex>(ex) );
0174     }
0175 
0176     template <class E1, class... E>
0177     inline
0178     typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, exception<std::exception>>::type
0179     make_exception( error_id err, E1 && car, E && ... cdr ) noexcept
0180     {
0181         static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0182         return exception<std::exception>( err.load(std::forward<E1>(car), std::forward<E>(cdr)...) );
0183     }
0184 
0185     inline exception<std::exception> make_exception( error_id err ) noexcept
0186     {
0187         return exception<std::exception>(err);
0188     }
0189 
0190     template <class Ex, class... E>
0191     inline
0192     typename std::enable_if<std::is_base_of<std::exception,typename std::remove_reference<Ex>::type>::value, exception<typename std::remove_reference<Ex>::type>>::type
0193     make_exception( Ex && ex, E && ... e ) noexcept
0194     {
0195         static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0196         return exception<typename std::remove_reference<Ex>::type>( new_error().load(std::forward<E>(e)...), std::forward<Ex>(ex) );
0197     }
0198 
0199     template <class E1, class... E>
0200     inline
0201     typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, exception<std::exception>>::type
0202     make_exception( E1 && car, E && ... cdr ) noexcept
0203     {
0204         static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0205         return exception<std::exception>( new_error().load(std::forward<E1>(car), std::forward<E>(cdr)...) );
0206     }
0207 
0208     inline exception<std::exception> make_exception() noexcept
0209     {
0210         return exception<std::exception>(leaf::new_error());
0211     }
0212 }
0213 
0214 template <class... E>
0215 [[noreturn]] void throw_exception( E && ... e )
0216 {
0217     // Warning: setting a breakpoint here will not intercept exceptions thrown
0218     // via BOOST_LEAF_THROW_EXCEPTION or originating in the few other throw
0219     // points elsewhere in LEAF. To intercept all of those exceptions as well,
0220     // set a breakpoint inside boost::leaf::detail::throw_exception_impl.
0221     detail::throw_exception_impl(detail::make_exception(std::forward<E>(e)...));
0222 }
0223 
0224 ////////////////////////////////////////
0225 
0226 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0227 
0228 template <class T>
0229 class BOOST_LEAF_SYMBOL_VISIBLE result;
0230 
0231 namespace detail
0232 {
0233     inline error_id catch_exceptions_helper( std::exception const &, leaf_detail_mp11::mp_list<> )
0234     {
0235         return leaf::new_error(std::current_exception());
0236     }
0237 
0238     template <class Ex1, class... Ex>
0239     inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<Ex1,Ex...> )
0240     {
0241         if( Ex1 const * p = dynamic_cast<Ex1 const *>(&ex) )
0242             return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ }).load(*p);
0243         else
0244             return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ });
0245     }
0246 
0247     template <class T>
0248     struct deduce_exception_to_result_return_type_impl
0249     {
0250         using type = result<T>;
0251     };
0252 
0253     template <class T>
0254     struct deduce_exception_to_result_return_type_impl<result<T>>
0255     {
0256         using type = result<T>;
0257     };
0258 
0259     template <class T>
0260     using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl<T>::type;
0261 }
0262 
0263 template <class... Ex, class F>
0264 inline
0265 detail::deduce_exception_to_result_return_type<detail::fn_return_type<F>>
0266 exception_to_result( F && f ) noexcept
0267 {
0268     try
0269     {
0270         return std::forward<F>(f)();
0271     }
0272     catch( std::exception const & ex )
0273     {
0274         return detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>());
0275     }
0276     catch(...)
0277     {
0278         return leaf::new_error(std::current_exception());
0279     }
0280 }
0281 
0282 #endif
0283 
0284 } }
0285 
0286 #endif // BOOST_LEAF_EXCEPTION_HPP_INCLUDED