• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
2 //Copyright (c) 2019 Dario Menendez, Banco Santander
3 
4 //Distributed under the Boost Software License, Version 1.0. (See accompanying
5 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef BOOST_EXCEPTION_618474C2DE1511DEB74A388C56D89593
8 #define BOOST_EXCEPTION_618474C2DE1511DEB74A388C56D89593
9 
10 #include <boost/config.hpp>
11 #ifdef BOOST_NO_EXCEPTIONS
12 #error This header requires exception handling to be enabled.
13 #endif
14 #include <boost/exception/exception.hpp>
15 #include <boost/exception/info.hpp>
16 #include <boost/exception/diagnostic_information.hpp>
17 #include <boost/exception/detail/clone_current_exception.hpp>
18 #include <boost/exception/detail/type_info.hpp>
19 #ifndef BOOST_NO_RTTI
20 #include <boost/core/demangle.hpp>
21 #endif
22 #include <boost/shared_ptr.hpp>
23 #include <stdexcept>
24 #include <new>
25 #include <ios>
26 #include <stdlib.h>
27 
28 #ifndef BOOST_EXCEPTION_ENABLE_WARNINGS
29 #if __GNUC__*100+__GNUC_MINOR__>301
30 #pragma GCC system_header
31 #endif
32 #ifdef __clang__
33 #pragma clang system_header
34 #endif
35 #ifdef _MSC_VER
36 #pragma warning(push,1)
37 #endif
38 #endif
39 
40 namespace
41 boost
42     {
43     class exception_ptr;
44     BOOST_NORETURN void rethrow_exception( exception_ptr const & );
45     exception_ptr current_exception();
46 
47     class
48     exception_ptr
49         {
50         typedef boost::shared_ptr<exception_detail::clone_base const> impl;
51         impl ptr_;
52         friend void rethrow_exception( exception_ptr const & );
53         typedef exception_detail::clone_base const * (impl::*unspecified_bool_type)() const;
54         public:
exception_ptr()55         exception_ptr()
56             {
57             }
58         explicit
exception_ptr(impl const & ptr)59         exception_ptr( impl const & ptr ):
60             ptr_(ptr)
61             {
62             }
63         bool
operator ==(exception_ptr const & other) const64         operator==( exception_ptr const & other ) const
65             {
66             return ptr_==other.ptr_;
67             }
68         bool
operator !=(exception_ptr const & other) const69         operator!=( exception_ptr const & other ) const
70             {
71             return ptr_!=other.ptr_;
72             }
operator unspecified_bool_type() const73         operator unspecified_bool_type() const
74             {
75             return ptr_?&impl::get:0;
76             }
77         };
78 
79     template <class T>
80     inline
81     exception_ptr
copy_exception(T const & e)82     copy_exception( T const & e )
83         {
84         try
85             {
86             throw enable_current_exception(e);
87             }
88         catch(
89         ... )
90             {
91             return current_exception();
92             }
93         }
94 
95 #ifndef BOOST_NO_RTTI
96     typedef error_info<struct tag_original_exception_type,std::type_info const *> original_exception_type;
97 
98     inline
99     std::string
to_string(original_exception_type const & x)100     to_string( original_exception_type const & x )
101         {
102         return core::demangle(x.value()->name());
103         }
104 #endif
105 
106     namespace
107     exception_detail
108         {
109         struct
110         bad_alloc_:
111             boost::exception,
112             std::bad_alloc
113                 {
~bad_alloc_boost::exception_detail::bad_alloc_114                 ~bad_alloc_() BOOST_NOEXCEPT_OR_NOTHROW { }
115                 };
116 
117         struct
118         bad_exception_:
119             boost::exception,
120             std::bad_exception
121                 {
~bad_exception_boost::exception_detail::bad_exception_122                 ~bad_exception_() BOOST_NOEXCEPT_OR_NOTHROW { }
123                 };
124 
125         template <class Exception>
126         exception_ptr
get_static_exception_object()127         get_static_exception_object()
128             {
129             Exception ba;
130             exception_detail::clone_impl<Exception> c(ba);
131 #ifndef BOOST_EXCEPTION_DISABLE
132             c <<
133                 throw_function(BOOST_CURRENT_FUNCTION) <<
134                 throw_file(__FILE__) <<
135                 throw_line(__LINE__);
136 #endif
137             static exception_ptr ep(shared_ptr<exception_detail::clone_base const>(new exception_detail::clone_impl<Exception>(c)));
138             return ep;
139             }
140 
141         template <class Exception>
142         struct
143         exception_ptr_static_exception_object
144             {
145             static exception_ptr const e;
146             };
147 
148         template <class Exception>
149         exception_ptr const
150         exception_ptr_static_exception_object<Exception>::
151         e = get_static_exception_object<Exception>();
152         }
153 
154 #if defined(__GNUC__)
155 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
156 #  pragma GCC visibility push (default)
157 # endif
158 #endif
159     class
160     unknown_exception:
161         public boost::exception,
162         public std::exception
163         {
164         public:
165 
unknown_exception()166         unknown_exception()
167             {
168             }
169 
170         explicit
unknown_exception(std::exception const & e)171         unknown_exception( std::exception const & e )
172             {
173             add_original_type(e);
174             }
175 
176         explicit
unknown_exception(boost::exception const & e)177         unknown_exception( boost::exception const & e ):
178             boost::exception(e)
179             {
180             add_original_type(e);
181             }
182 
~unknown_exception()183         ~unknown_exception() BOOST_NOEXCEPT_OR_NOTHROW
184             {
185             }
186 
187         private:
188 
189         template <class E>
190         void
add_original_type(E const & e)191         add_original_type( E const & e )
192             {
193 #ifndef BOOST_NO_RTTI
194             (*this) << original_exception_type(&typeid(e));
195 #endif
196             }
197         };
198 #if defined(__GNUC__)
199 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
200 #  pragma GCC visibility pop
201 # endif
202 #endif
203 
204     namespace
205     exception_detail
206         {
207         template <class T>
208         class
209         current_exception_std_exception_wrapper:
210             public T,
211             public boost::exception
212             {
213             public:
214 
215             explicit
current_exception_std_exception_wrapper(T const & e1)216             current_exception_std_exception_wrapper( T const & e1 ):
217                 T(e1)
218                 {
219                 add_original_type(e1);
220                 }
221 
current_exception_std_exception_wrapper(T const & e1,boost::exception const & e2)222             current_exception_std_exception_wrapper( T const & e1, boost::exception const & e2 ):
223                 T(e1),
224                 boost::exception(e2)
225                 {
226                 add_original_type(e1);
227                 }
228 
~current_exception_std_exception_wrapper()229             ~current_exception_std_exception_wrapper() BOOST_NOEXCEPT_OR_NOTHROW
230                 {
231                 }
232 
233             private:
234 
235             template <class E>
236             void
add_original_type(E const & e)237             add_original_type( E const & e )
238                 {
239 #ifndef BOOST_NO_RTTI
240                 (*this) << original_exception_type(&typeid(e));
241 #endif
242                 }
243             };
244 
245 #ifdef BOOST_NO_RTTI
246         template <class T>
247         boost::exception const *
get_boost_exception(T const *)248         get_boost_exception( T const * )
249             {
250             try
251                 {
252                 throw;
253                 }
254             catch(
255             boost::exception & x )
256                 {
257                 return &x;
258                 }
259             catch(...)
260                 {
261                 return 0;
262                 }
263             }
264 #else
265         template <class T>
266         boost::exception const *
get_boost_exception(T const * x)267         get_boost_exception( T const * x )
268             {
269             return dynamic_cast<boost::exception const *>(x);
270             }
271 #endif
272 
273         template <class T>
274         inline
275         exception_ptr
current_exception_std_exception(T const & e1)276         current_exception_std_exception( T const & e1 )
277             {
278             if( boost::exception const * e2 = get_boost_exception(&e1) )
279                 return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1,*e2));
280             else
281                 return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1));
282             }
283 
284         inline
285         exception_ptr
current_exception_unknown_exception()286         current_exception_unknown_exception()
287             {
288             return boost::copy_exception(unknown_exception());
289             }
290 
291         inline
292         exception_ptr
current_exception_unknown_boost_exception(boost::exception const & e)293         current_exception_unknown_boost_exception( boost::exception const & e )
294             {
295             return boost::copy_exception(unknown_exception(e));
296             }
297 
298         inline
299         exception_ptr
current_exception_unknown_std_exception(std::exception const & e)300         current_exception_unknown_std_exception( std::exception const & e )
301             {
302             if( boost::exception const * be = get_boost_exception(&e) )
303                 return current_exception_unknown_boost_exception(*be);
304             else
305                 return boost::copy_exception(unknown_exception(e));
306             }
307 
308 #ifndef BOOST_NO_CXX11_HDR_EXCEPTION
309         struct
310         std_exception_ptr_wrapper
311             {
312             std::exception_ptr p;
std_exception_ptr_wrapperboost::exception_detail::std_exception_ptr_wrapper313             explicit std_exception_ptr_wrapper( std::exception_ptr const & ptr ) BOOST_NOEXCEPT:
314                 p(ptr)
315                 {
316                 }
317 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
std_exception_ptr_wrapperboost::exception_detail::std_exception_ptr_wrapper318             explicit std_exception_ptr_wrapper( std::exception_ptr && ptr ) BOOST_NOEXCEPT:
319                 p(static_cast<std::exception_ptr &&>(ptr))
320                 {
321                 }
322 #endif
323             };
324 #endif
325 
326         inline
327         exception_ptr
current_exception_impl()328         current_exception_impl()
329             {
330             exception_detail::clone_base const * e=0;
331             switch(
332             exception_detail::clone_current_exception(e) )
333                 {
334                 case exception_detail::clone_current_exception_result::
335                 success:
336                     {
337                     BOOST_ASSERT(e!=0);
338                     return exception_ptr(shared_ptr<exception_detail::clone_base const>(e));
339                     }
340                 case exception_detail::clone_current_exception_result::
341                 bad_alloc:
342                     {
343                     BOOST_ASSERT(!e);
344                     return exception_detail::exception_ptr_static_exception_object<bad_alloc_>::e;
345                     }
346                 case exception_detail::clone_current_exception_result::
347                 bad_exception:
348                     {
349                     BOOST_ASSERT(!e);
350                     return exception_detail::exception_ptr_static_exception_object<bad_exception_>::e;
351                     }
352                 default:
353                     BOOST_ASSERT(0);
354                 case exception_detail::clone_current_exception_result::
355                 not_supported:
356                     {
357                     BOOST_ASSERT(!e);
358                     try
359                         {
360                         throw;
361                         }
362                     catch(
363                     exception_detail::clone_base & e )
364                         {
365                         return exception_ptr(shared_ptr<exception_detail::clone_base const>(e.clone()));
366                         }
367                     catch(
368                     std::domain_error & e )
369                         {
370                         return exception_detail::current_exception_std_exception(e);
371                         }
372                     catch(
373                     std::invalid_argument & e )
374                         {
375                         return exception_detail::current_exception_std_exception(e);
376                         }
377                     catch(
378                     std::length_error & e )
379                         {
380                         return exception_detail::current_exception_std_exception(e);
381                         }
382                     catch(
383                     std::out_of_range & e )
384                         {
385                         return exception_detail::current_exception_std_exception(e);
386                         }
387                     catch(
388                     std::logic_error & e )
389                         {
390                         return exception_detail::current_exception_std_exception(e);
391                         }
392                     catch(
393                     std::range_error & e )
394                         {
395                         return exception_detail::current_exception_std_exception(e);
396                         }
397                     catch(
398                     std::overflow_error & e )
399                         {
400                         return exception_detail::current_exception_std_exception(e);
401                         }
402                     catch(
403                     std::underflow_error & e )
404                         {
405                         return exception_detail::current_exception_std_exception(e);
406                         }
407                     catch(
408                     std::ios_base::failure & e )
409                         {
410                         return exception_detail::current_exception_std_exception(e);
411                         }
412                     catch(
413                     std::runtime_error & e )
414                         {
415                         return exception_detail::current_exception_std_exception(e);
416                         }
417                     catch(
418                     std::bad_alloc & e )
419                         {
420                         return exception_detail::current_exception_std_exception(e);
421                         }
422         #ifndef BOOST_NO_TYPEID
423                     catch(
424                     std::bad_cast & e )
425                         {
426                         return exception_detail::current_exception_std_exception(e);
427                         }
428                     catch(
429                     std::bad_typeid & e )
430                         {
431                         return exception_detail::current_exception_std_exception(e);
432                         }
433         #endif
434                     catch(
435                     std::bad_exception & e )
436                         {
437                         return exception_detail::current_exception_std_exception(e);
438                         }
439 #ifdef BOOST_NO_CXX11_HDR_EXCEPTION
440                     // this case can be handled losslesly with std::current_exception() (see below)
441                     catch(
442                     std::exception & e )
443                         {
444                         return exception_detail::current_exception_unknown_std_exception(e);
445                         }
446 #endif
447                     catch(
448                     boost::exception & e )
449                         {
450                         return exception_detail::current_exception_unknown_boost_exception(e);
451                         }
452                     catch(
453                     ... )
454                         {
455 #ifndef BOOST_NO_CXX11_HDR_EXCEPTION
456                         try
457                             {
458                             // wrap the std::exception_ptr in a clone-enabled Boost.Exception object
459                             exception_detail::clone_base const & base =
460                                 boost::enable_current_exception(std_exception_ptr_wrapper(std::current_exception()));
461                             return exception_ptr(shared_ptr<exception_detail::clone_base const>(base.clone()));
462                             }
463                         catch(
464                         ...)
465                             {
466                             return exception_detail::current_exception_unknown_exception();
467                             }
468 #else
469                         return exception_detail::current_exception_unknown_exception();
470 #endif
471                         }
472                     }
473                 }
474             }
475         }
476 
477     inline
478     exception_ptr
current_exception()479     current_exception()
480         {
481         exception_ptr ret;
482         try
483             {
484             ret=exception_detail::current_exception_impl();
485             }
486         catch(
487         std::bad_alloc & )
488             {
489             ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_alloc_>::e;
490             }
491         catch(
492         ... )
493             {
494             ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_exception_>::e;
495             }
496         BOOST_ASSERT(ret);
497         return ret;
498         }
499 
500     BOOST_NORETURN
501     inline
502     void
rethrow_exception(exception_ptr const & p)503     rethrow_exception( exception_ptr const & p )
504         {
505         BOOST_ASSERT(p);
506 #ifndef BOOST_NO_CXX11_HDR_EXCEPTION
507         try
508             {
509             p.ptr_->rethrow();
510             }
511         catch(
512         exception_detail::std_exception_ptr_wrapper const & wrp)
513             {
514             // if an std::exception_ptr was wrapped above then rethrow it
515             std::rethrow_exception(wrp.p);
516             }
517 #else
518         p.ptr_->rethrow();
519 #endif
520         BOOST_ASSERT(0);
521         #if defined(UNDER_CE)
522             // some CE platforms don't define ::abort()
523             exit(-1);
524         #else
525             abort();
526         #endif
527         }
528 
529     inline
530     std::string
diagnostic_information(exception_ptr const & p,bool verbose=true)531     diagnostic_information( exception_ptr const & p, bool verbose=true )
532         {
533         if( p )
534             try
535                 {
536                 rethrow_exception(p);
537                 }
538             catch(
539             ... )
540                 {
541                 return current_exception_diagnostic_information(verbose);
542                 }
543         return "<empty>";
544         }
545 
546     inline
547     std::string
to_string(exception_ptr const & p)548     to_string( exception_ptr const & p )
549         {
550         std::string s='\n'+diagnostic_information(p);
551         std::string padding("  ");
552         std::string r;
553         bool f=false;
554         for( std::string::const_iterator i=s.begin(),e=s.end(); i!=e; ++i )
555             {
556             if( f )
557                 r+=padding;
558             char c=*i;
559             r+=c;
560             f=(c=='\n');
561             }
562         return r;
563         }
564     }
565 
566 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
567 #pragma warning(pop)
568 #endif
569 #endif
570