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