]>
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 | ||
f67539c2 TL |
6 | #ifndef BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593 |
7 | #define BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593 | |
92f5a8d4 | 8 | |
1e59de90 | 9 | #include <boost/assert/source_location.hpp> |
92f5a8d4 | 10 | #include <boost/config.hpp> |
1e59de90 | 11 | #include <exception> |
7c673cae | 12 | |
b32b8144 FG |
13 | #ifdef BOOST_EXCEPTION_MINI_BOOST |
14 | #include <memory> | |
15 | namespace boost { namespace exception_detail { using std::shared_ptr; } } | |
16 | #else | |
92f5a8d4 | 17 | namespace boost { template <class T> class shared_ptr; } |
b32b8144 FG |
18 | namespace boost { namespace exception_detail { using boost::shared_ptr; } } |
19 | #endif | |
20 | ||
f67539c2 TL |
21 | #if !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) |
22 | #if __GNUC__*100+__GNUC_MINOR__>301 | |
92f5a8d4 TL |
23 | #pragma GCC system_header |
24 | #endif | |
f67539c2 TL |
25 | #ifdef __clang__ |
26 | #pragma clang system_header | |
27 | #endif | |
28 | #ifdef _MSC_VER | |
92f5a8d4 TL |
29 | #pragma warning(push,1) |
30 | #pragma warning(disable: 4265) | |
31 | #endif | |
f67539c2 | 32 | #endif |
92f5a8d4 | 33 | |
7c673cae FG |
34 | namespace |
35 | boost | |
36 | { | |
37 | namespace | |
38 | exception_detail | |
39 | { | |
40 | template <class T> | |
41 | class | |
42 | refcount_ptr | |
43 | { | |
44 | public: | |
45 | ||
46 | refcount_ptr(): | |
47 | px_(0) | |
48 | { | |
49 | } | |
50 | ||
51 | ~refcount_ptr() | |
52 | { | |
53 | release(); | |
54 | } | |
55 | ||
56 | refcount_ptr( refcount_ptr const & x ): | |
57 | px_(x.px_) | |
58 | { | |
59 | add_ref(); | |
60 | } | |
61 | ||
62 | refcount_ptr & | |
63 | operator=( refcount_ptr const & x ) | |
64 | { | |
65 | adopt(x.px_); | |
66 | return *this; | |
67 | } | |
68 | ||
69 | void | |
70 | adopt( T * px ) | |
71 | { | |
72 | release(); | |
73 | px_=px; | |
74 | add_ref(); | |
75 | } | |
76 | ||
77 | T * | |
78 | get() const | |
79 | { | |
80 | return px_; | |
81 | } | |
82 | ||
83 | private: | |
84 | ||
85 | T * px_; | |
86 | ||
87 | void | |
88 | add_ref() | |
89 | { | |
90 | if( px_ ) | |
91 | px_->add_ref(); | |
92 | } | |
93 | ||
94 | void | |
95 | release() | |
96 | { | |
97 | if( px_ && px_->release() ) | |
98 | px_=0; | |
99 | } | |
100 | }; | |
101 | } | |
102 | ||
103 | //////////////////////////////////////////////////////////////////////// | |
104 | ||
105 | template <class Tag,class T> | |
106 | class error_info; | |
107 | ||
108 | typedef error_info<struct throw_function_,char const *> throw_function; | |
109 | typedef error_info<struct throw_file_,char const *> throw_file; | |
110 | typedef error_info<struct throw_line_,int> throw_line; | |
1e59de90 | 111 | typedef error_info<struct throw_column_,int> throw_column; |
7c673cae FG |
112 | |
113 | template <> | |
114 | class | |
115 | error_info<throw_function_,char const *> | |
116 | { | |
117 | public: | |
118 | typedef char const * value_type; | |
119 | value_type v_; | |
120 | explicit | |
121 | error_info( value_type v ): | |
122 | v_(v) | |
123 | { | |
124 | } | |
125 | }; | |
126 | ||
127 | template <> | |
128 | class | |
129 | error_info<throw_file_,char const *> | |
130 | { | |
131 | public: | |
132 | typedef char const * value_type; | |
133 | value_type v_; | |
134 | explicit | |
135 | error_info( value_type v ): | |
136 | v_(v) | |
137 | { | |
138 | } | |
139 | }; | |
140 | ||
141 | template <> | |
142 | class | |
143 | error_info<throw_line_,int> | |
144 | { | |
145 | public: | |
146 | typedef int value_type; | |
147 | value_type v_; | |
148 | explicit | |
149 | error_info( value_type v ): | |
150 | v_(v) | |
151 | { | |
152 | } | |
153 | }; | |
154 | ||
1e59de90 TL |
155 | template <> |
156 | class | |
157 | error_info<throw_column_,int> | |
158 | { | |
159 | public: | |
160 | typedef int value_type; | |
161 | value_type v_; | |
162 | explicit | |
163 | error_info( value_type v ): | |
164 | v_(v) | |
165 | { | |
166 | } | |
167 | }; | |
168 | ||
92f5a8d4 TL |
169 | class |
170 | BOOST_SYMBOL_VISIBLE | |
171 | exception; | |
7c673cae | 172 | |
7c673cae FG |
173 | namespace |
174 | exception_detail | |
175 | { | |
176 | class error_info_base; | |
177 | struct type_info_; | |
178 | ||
179 | struct | |
180 | error_info_container | |
181 | { | |
182 | virtual char const * diagnostic_information( char const * ) const = 0; | |
183 | virtual shared_ptr<error_info_base> get( type_info_ const & ) const = 0; | |
184 | virtual void set( shared_ptr<error_info_base> const &, type_info_ const & ) = 0; | |
185 | virtual void add_ref() const = 0; | |
186 | virtual bool release() const = 0; | |
187 | virtual refcount_ptr<exception_detail::error_info_container> clone() const = 0; | |
188 | ||
189 | protected: | |
190 | ||
92f5a8d4 | 191 | ~error_info_container() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
192 | { |
193 | } | |
194 | }; | |
195 | ||
196 | template <class> | |
197 | struct get_info; | |
198 | ||
199 | template <> | |
200 | struct get_info<throw_function>; | |
201 | ||
202 | template <> | |
203 | struct get_info<throw_file>; | |
204 | ||
205 | template <> | |
206 | struct get_info<throw_line>; | |
207 | ||
1e59de90 TL |
208 | template <> |
209 | struct get_info<throw_column>; | |
210 | ||
7c673cae FG |
211 | template <class> |
212 | struct set_info_rv; | |
213 | ||
214 | template <> | |
215 | struct set_info_rv<throw_function>; | |
216 | ||
217 | template <> | |
218 | struct set_info_rv<throw_file>; | |
219 | ||
220 | template <> | |
221 | struct set_info_rv<throw_line>; | |
222 | ||
1e59de90 TL |
223 | template <> |
224 | struct set_info_rv<throw_column>; | |
225 | ||
7c673cae FG |
226 | char const * get_diagnostic_information( exception const &, char const * ); |
227 | ||
228 | void copy_boost_exception( exception *, exception const * ); | |
229 | ||
230 | template <class E,class Tag,class T> | |
231 | E const & set_info( E const &, error_info<Tag,T> const & ); | |
232 | ||
233 | template <class E> | |
234 | E const & set_info( E const &, throw_function const & ); | |
235 | ||
236 | template <class E> | |
237 | E const & set_info( E const &, throw_file const & ); | |
238 | ||
239 | template <class E> | |
240 | E const & set_info( E const &, throw_line const & ); | |
1e59de90 TL |
241 | |
242 | template <class E> | |
243 | E const & set_info( E const &, throw_column const & ); | |
244 | ||
245 | boost::source_location get_exception_throw_location( exception const & ); | |
7c673cae FG |
246 | } |
247 | ||
7c673cae | 248 | class |
92f5a8d4 | 249 | BOOST_SYMBOL_VISIBLE |
7c673cae FG |
250 | exception |
251 | { | |
252 | //<N3757> | |
253 | public: | |
254 | template <class Tag> void set( typename Tag::type const & ); | |
255 | template <class Tag> typename Tag::type const * get() const; | |
256 | //</N3757> | |
257 | ||
258 | protected: | |
259 | ||
260 | exception(): | |
261 | throw_function_(0), | |
262 | throw_file_(0), | |
1e59de90 TL |
263 | throw_line_(-1), |
264 | throw_column_(-1) | |
7c673cae FG |
265 | { |
266 | } | |
267 | ||
268 | #ifdef __HP_aCC | |
269 | //On HP aCC, this protected copy constructor prevents throwing boost::exception. | |
270 | //On all other platforms, the same effect is achieved by the pure virtual destructor. | |
92f5a8d4 | 271 | exception( exception const & x ) BOOST_NOEXCEPT_OR_NOTHROW: |
7c673cae FG |
272 | data_(x.data_), |
273 | throw_function_(x.throw_function_), | |
274 | throw_file_(x.throw_file_), | |
1e59de90 TL |
275 | throw_line_(x.throw_line_), |
276 | throw_column_(x.throw_column_) | |
7c673cae FG |
277 | { |
278 | } | |
279 | #endif | |
280 | ||
92f5a8d4 | 281 | virtual ~exception() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
282 | #ifndef __HP_aCC |
283 | = 0 //Workaround for HP aCC, =0 incorrectly leads to link errors. | |
284 | #endif | |
285 | ; | |
286 | ||
287 | #if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310) | |
288 | public: | |
289 | #else | |
290 | private: | |
291 | ||
292 | template <class E> | |
293 | friend E const & exception_detail::set_info( E const &, throw_function const & ); | |
294 | ||
295 | template <class E> | |
296 | friend E const & exception_detail::set_info( E const &, throw_file const & ); | |
297 | ||
298 | template <class E> | |
299 | friend E const & exception_detail::set_info( E const &, throw_line const & ); | |
300 | ||
1e59de90 TL |
301 | template <class E> |
302 | friend E const & exception_detail::set_info( E const &, throw_column const & ); | |
303 | ||
7c673cae FG |
304 | template <class E,class Tag,class T> |
305 | friend E const & exception_detail::set_info( E const &, error_info<Tag,T> const & ); | |
306 | ||
307 | friend char const * exception_detail::get_diagnostic_information( exception const &, char const * ); | |
308 | ||
1e59de90 TL |
309 | friend boost::source_location exception_detail::get_exception_throw_location( exception const & ); |
310 | ||
7c673cae FG |
311 | template <class> |
312 | friend struct exception_detail::get_info; | |
313 | friend struct exception_detail::get_info<throw_function>; | |
314 | friend struct exception_detail::get_info<throw_file>; | |
315 | friend struct exception_detail::get_info<throw_line>; | |
1e59de90 | 316 | friend struct exception_detail::get_info<throw_column>; |
7c673cae FG |
317 | template <class> |
318 | friend struct exception_detail::set_info_rv; | |
319 | friend struct exception_detail::set_info_rv<throw_function>; | |
320 | friend struct exception_detail::set_info_rv<throw_file>; | |
321 | friend struct exception_detail::set_info_rv<throw_line>; | |
1e59de90 | 322 | friend struct exception_detail::set_info_rv<throw_column>; |
7c673cae FG |
323 | friend void exception_detail::copy_boost_exception( exception *, exception const * ); |
324 | #endif | |
325 | mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_; | |
326 | mutable char const * throw_function_; | |
327 | mutable char const * throw_file_; | |
328 | mutable int throw_line_; | |
1e59de90 | 329 | mutable int throw_column_; |
7c673cae | 330 | }; |
7c673cae FG |
331 | |
332 | inline | |
333 | exception:: | |
92f5a8d4 | 334 | ~exception() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
335 | { |
336 | } | |
337 | ||
338 | namespace | |
339 | exception_detail | |
340 | { | |
341 | template <class E> | |
342 | E const & | |
343 | set_info( E const & x, throw_function const & y ) | |
344 | { | |
345 | x.throw_function_=y.v_; | |
346 | return x; | |
347 | } | |
348 | ||
349 | template <class E> | |
350 | E const & | |
351 | set_info( E const & x, throw_file const & y ) | |
352 | { | |
353 | x.throw_file_=y.v_; | |
354 | return x; | |
355 | } | |
356 | ||
357 | template <class E> | |
358 | E const & | |
359 | set_info( E const & x, throw_line const & y ) | |
360 | { | |
361 | x.throw_line_=y.v_; | |
362 | return x; | |
363 | } | |
1e59de90 TL |
364 | |
365 | template <class E> | |
366 | E const & | |
367 | set_info( E const & x, throw_column const & y ) | |
368 | { | |
369 | x.throw_column_=y.v_; | |
370 | return x; | |
371 | } | |
372 | ||
373 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
374 | ||
375 | template <> | |
376 | struct | |
377 | set_info_rv<throw_column> | |
378 | { | |
379 | template <class E> | |
380 | static | |
381 | E const & | |
382 | set( E const & x, throw_column && y ) | |
383 | { | |
384 | x.throw_column_=y.v_; | |
385 | return x; | |
386 | } | |
387 | }; | |
388 | ||
389 | #endif | |
390 | ||
391 | inline boost::source_location get_exception_throw_location( exception const & x ) | |
392 | { | |
393 | return boost::source_location( | |
394 | x.throw_file_? x.throw_file_: "", | |
395 | x.throw_line_ >= 0? x.throw_line_: 0, | |
396 | x.throw_function_? x.throw_function_: "", | |
397 | x.throw_column_ >= 0? x.throw_column_: 0 | |
398 | ); | |
399 | } | |
7c673cae FG |
400 | } |
401 | ||
402 | //////////////////////////////////////////////////////////////////////// | |
403 | ||
404 | namespace | |
405 | exception_detail | |
406 | { | |
7c673cae FG |
407 | template <class T> |
408 | struct | |
92f5a8d4 | 409 | BOOST_SYMBOL_VISIBLE |
7c673cae FG |
410 | error_info_injector: |
411 | public T, | |
412 | public exception | |
413 | { | |
414 | explicit | |
415 | error_info_injector( T const & x ): | |
416 | T(x) | |
417 | { | |
418 | } | |
419 | ||
92f5a8d4 | 420 | ~error_info_injector() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
421 | { |
422 | } | |
423 | }; | |
7c673cae FG |
424 | |
425 | struct large_size { char c[256]; }; | |
426 | large_size dispatch_boost_exception( exception const * ); | |
427 | ||
428 | struct small_size { }; | |
429 | small_size dispatch_boost_exception( void const * ); | |
430 | ||
431 | template <class,int> | |
432 | struct enable_error_info_helper; | |
433 | ||
434 | template <class T> | |
435 | struct | |
436 | enable_error_info_helper<T,sizeof(large_size)> | |
437 | { | |
438 | typedef T type; | |
439 | }; | |
440 | ||
441 | template <class T> | |
442 | struct | |
443 | enable_error_info_helper<T,sizeof(small_size)> | |
444 | { | |
445 | typedef error_info_injector<T> type; | |
446 | }; | |
447 | ||
448 | template <class T> | |
449 | struct | |
450 | enable_error_info_return_type | |
451 | { | |
452 | typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception(static_cast<T *>(0)))>::type type; | |
453 | }; | |
454 | } | |
455 | ||
456 | template <class T> | |
457 | inline | |
458 | typename | |
459 | exception_detail::enable_error_info_return_type<T>::type | |
460 | enable_error_info( T const & x ) | |
461 | { | |
462 | typedef typename exception_detail::enable_error_info_return_type<T>::type rt; | |
463 | return rt(x); | |
464 | } | |
465 | ||
466 | //////////////////////////////////////////////////////////////////////// | |
1e59de90 TL |
467 | #if defined(BOOST_NO_EXCEPTIONS) |
468 | BOOST_NORETURN void throw_exception(std::exception const & e); // user defined | |
469 | #endif | |
7c673cae FG |
470 | |
471 | namespace | |
472 | exception_detail | |
473 | { | |
7c673cae | 474 | class |
92f5a8d4 | 475 | BOOST_SYMBOL_VISIBLE |
7c673cae FG |
476 | clone_base |
477 | { | |
478 | public: | |
479 | ||
480 | virtual clone_base const * clone() const = 0; | |
481 | virtual void rethrow() const = 0; | |
482 | ||
483 | virtual | |
92f5a8d4 | 484 | ~clone_base() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
485 | { |
486 | } | |
487 | }; | |
7c673cae FG |
488 | |
489 | inline | |
490 | void | |
491 | copy_boost_exception( exception * a, exception const * b ) | |
492 | { | |
493 | refcount_ptr<error_info_container> data; | |
494 | if( error_info_container * d=b->data_.get() ) | |
495 | data = d->clone(); | |
496 | a->throw_file_ = b->throw_file_; | |
497 | a->throw_line_ = b->throw_line_; | |
498 | a->throw_function_ = b->throw_function_; | |
1e59de90 | 499 | a->throw_column_ = b->throw_column_; |
7c673cae FG |
500 | a->data_ = data; |
501 | } | |
502 | ||
503 | inline | |
504 | void | |
505 | copy_boost_exception( void *, void const * ) | |
506 | { | |
507 | } | |
508 | ||
7c673cae FG |
509 | template <class T> |
510 | class | |
92f5a8d4 | 511 | BOOST_SYMBOL_VISIBLE |
7c673cae FG |
512 | clone_impl: |
513 | public T, | |
514 | public virtual clone_base | |
515 | { | |
516 | struct clone_tag { }; | |
517 | clone_impl( clone_impl const & x, clone_tag ): | |
518 | T(x) | |
519 | { | |
520 | copy_boost_exception(this,&x); | |
521 | } | |
522 | ||
523 | public: | |
524 | ||
525 | explicit | |
526 | clone_impl( T const & x ): | |
527 | T(x) | |
528 | { | |
529 | copy_boost_exception(this,&x); | |
530 | } | |
531 | ||
92f5a8d4 | 532 | ~clone_impl() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
533 | { |
534 | } | |
535 | ||
536 | private: | |
537 | ||
538 | clone_base const * | |
539 | clone() const | |
540 | { | |
541 | return new clone_impl(*this,clone_tag()); | |
542 | } | |
543 | ||
544 | void | |
545 | rethrow() const | |
546 | { | |
1e59de90 TL |
547 | #if defined(BOOST_NO_EXCEPTIONS) |
548 | boost::throw_exception(*this); | |
549 | #else | |
7c673cae | 550 | throw*this; |
1e59de90 | 551 | #endif |
7c673cae FG |
552 | } |
553 | }; | |
554 | } | |
7c673cae FG |
555 | |
556 | template <class T> | |
557 | inline | |
558 | exception_detail::clone_impl<T> | |
559 | enable_current_exception( T const & x ) | |
560 | { | |
561 | return exception_detail::clone_impl<T>(x); | |
562 | } | |
563 | } | |
564 | ||
565 | #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) | |
566 | #pragma warning(pop) | |
567 | #endif | |
f67539c2 TL |
568 | |
569 | #endif // #ifndef BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593 |