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