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

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