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