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>
15namespace boost { namespace exception_detail { using std::shared_ptr; } }
16#else
17namespace boost { template <class T> class shared_ptr; }
18namespace 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
34namespace
35boost
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(px: 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;
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 ~error_info_container() BOOST_NOEXCEPT_OR_NOTHROW
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
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 exception():
261 throw_function_(0),
262 throw_file_(0),
263 throw_line_(-1),
264 throw_column_(-1)
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.
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 ~exception() BOOST_NOEXCEPT_OR_NOTHROW
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 }
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 ~clone_base() BOOST_NOEXCEPT_OR_NOTHROW
485 {
486 }
487 };
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_;
499 a->throw_column_ = b->throw_column_;
500 a->data_ = data;
501 }
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
570

source code of boost/libs/throw_exception/include/boost/exception/exception.hpp