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