Line data Source code
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 BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593
7 : #define BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593
8 :
9 : #include <boost/assert/source_location.hpp>
10 : #include <boost/config.hpp>
11 : #include <exception>
12 :
13 : #ifdef BOOST_EXCEPTION_MINI_BOOST
14 : #include <memory>
15 : namespace boost { namespace exception_detail { using std::shared_ptr; } }
16 : #else
17 : namespace boost { template <class T> class shared_ptr; }
18 : namespace boost { namespace exception_detail { using boost::shared_ptr; } }
19 : #endif
20 :
21 : #if !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
22 : #if defined(__GNUC__) && __GNUC__*100+__GNUC_MINOR__>301
23 : #pragma GCC system_header
24 : #endif
25 : #ifdef __clang__
26 : #pragma clang system_header
27 : #endif
28 : #ifdef _MSC_VER
29 : #pragma warning(push,1)
30 : #pragma warning(disable: 4265)
31 : #endif
32 : #endif
33 :
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 12 : refcount_ptr():
47 6 : px_(0)
48 6 : {
49 12 : }
50 :
51 12 : ~refcount_ptr()
52 6 : {
53 6 : release();
54 12 : }
55 :
56 0 : refcount_ptr( refcount_ptr const & x ):
57 0 : px_(x.px_)
58 0 : {
59 0 : add_ref();
60 0 : }
61 :
62 : refcount_ptr &
63 0 : operator=( refcount_ptr const & x )
64 : {
65 0 : adopt(x.px_);
66 0 : return *this;
67 : }
68 :
69 : void
70 0 : adopt( T * px )
71 : {
72 0 : release();
73 0 : px_=px;
74 0 : add_ref();
75 0 : }
76 :
77 : T *
78 0 : get() const
79 : {
80 0 : return px_;
81 : }
82 :
83 : private:
84 :
85 : T * px_;
86 :
87 : void
88 0 : add_ref()
89 : {
90 0 : if( px_ )
91 0 : px_->add_ref();
92 0 : }
93 :
94 : void
95 6 : release()
96 : {
97 6 : if( px_ && px_->release() )
98 0 : px_=0;
99 6 : }
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;
111 : typedef error_info<struct throw_column_,int> throw_column;
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 :
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 :
169 : class
170 : BOOST_SYMBOL_VISIBLE
171 : exception;
172 :
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 :
191 0 : ~error_info_container() BOOST_NOEXCEPT_OR_NOTHROW
192 : {
193 0 : }
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 :
208 : template <>
209 : struct get_info<throw_column>;
210 :
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 :
223 : template <>
224 : struct set_info_rv<throw_column>;
225 :
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 & );
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 & );
246 : }
247 :
248 : class
249 : BOOST_SYMBOL_VISIBLE
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 12 : exception():
261 6 : throw_function_(0),
262 6 : throw_file_(0),
263 6 : throw_line_(-1),
264 6 : throw_column_(-1)
265 6 : {
266 6 : }
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.
271 : exception( exception const & x ) BOOST_NOEXCEPT_OR_NOTHROW:
272 : data_(x.data_),
273 : throw_function_(x.throw_function_),
274 : throw_file_(x.throw_file_),
275 : throw_line_(x.throw_line_),
276 : throw_column_(x.throw_column_)
277 : {
278 : }
279 : #endif
280 :
281 : virtual ~exception() BOOST_NOEXCEPT_OR_NOTHROW
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 :
301 : template <class E>
302 : friend E const & exception_detail::set_info( E const &, throw_column const & );
303 :
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 :
309 : friend boost::source_location exception_detail::get_exception_throw_location( exception const & );
310 :
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>;
316 : friend struct exception_detail::get_info<throw_column>;
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>;
322 : friend struct exception_detail::set_info_rv<throw_column>;
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_;
329 : mutable int throw_column_;
330 : };
331 :
332 : inline
333 : exception::
334 6 : ~exception() BOOST_NOEXCEPT_OR_NOTHROW
335 6 : {
336 6 : }
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 : }
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 : }
400 : }
401 :
402 : ////////////////////////////////////////////////////////////////////////
403 :
404 : namespace
405 : exception_detail
406 : {
407 : template <class T>
408 : struct
409 : BOOST_SYMBOL_VISIBLE
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 :
420 : ~error_info_injector() BOOST_NOEXCEPT_OR_NOTHROW
421 : {
422 : }
423 : };
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 : ////////////////////////////////////////////////////////////////////////
467 : #if defined(BOOST_NO_EXCEPTIONS)
468 : BOOST_NORETURN void throw_exception(std::exception const & e); // user defined
469 : #endif
470 :
471 : namespace
472 : exception_detail
473 : {
474 : class
475 : BOOST_SYMBOL_VISIBLE
476 : clone_base
477 : {
478 : public:
479 :
480 : virtual clone_base const * clone() const = 0;
481 : virtual void rethrow() const = 0;
482 :
483 : virtual
484 6 : ~clone_base() BOOST_NOEXCEPT_OR_NOTHROW
485 0 : {
486 6 : }
487 : };
488 :
489 : inline
490 : void
491 0 : copy_boost_exception( exception * a, exception const * b )
492 : {
493 0 : refcount_ptr<error_info_container> data;
494 0 : if( error_info_container * d=b->data_.get() )
495 0 : data = d->clone();
496 0 : a->throw_file_ = b->throw_file_;
497 0 : a->throw_line_ = b->throw_line_;
498 0 : a->throw_function_ = b->throw_function_;
499 0 : a->throw_column_ = b->throw_column_;
500 0 : a->data_ = data;
501 0 : }
502 :
503 : inline
504 : void
505 : copy_boost_exception( void *, void const * )
506 : {
507 : }
508 :
509 : template <class T>
510 : class
511 : BOOST_SYMBOL_VISIBLE
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 :
532 : ~clone_impl() BOOST_NOEXCEPT_OR_NOTHROW
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 : {
547 : #if defined(BOOST_NO_EXCEPTIONS)
548 : boost::throw_exception(*this);
549 : #else
550 : throw*this;
551 : #endif
552 : }
553 : };
554 : }
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
568 :
569 : #endif // #ifndef BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593
|