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