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>
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(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 
32 namespace
33 boost
34     {
35     namespace
36     exception_detail
37         {
38         template <class T>
39         class
40         refcount_ptr
41             {
42             public:
43 
refcount_ptr()44             refcount_ptr():
45                 px_(0)
46                 {
47                 }
48 
~refcount_ptr()49             ~refcount_ptr()
50                 {
51                 release();
52                 }
53 
refcount_ptr(refcount_ptr const & x)54             refcount_ptr( refcount_ptr const & x ):
55                 px_(x.px_)
56                 {
57                 add_ref();
58                 }
59 
60             refcount_ptr &
operator =(refcount_ptr const & x)61             operator=( refcount_ptr const & x )
62                 {
63                 adopt(x.px_);
64                 return *this;
65                 }
66 
67             void
adopt(T * px)68             adopt( T * px )
69                 {
70                 release();
71                 px_=px;
72                 add_ref();
73                 }
74 
75             T *
get() const76             get() const
77                 {
78                 return px_;
79                 }
80 
81             private:
82 
83             T * px_;
84 
85             void
add_ref()86             add_ref()
87                 {
88                 if( px_ )
89                     px_->add_ref();
90                 }
91 
92             void
release()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
error_info(value_type v)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
error_info(value_type v)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
error_info(value_type v)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 
~error_info_containerboost::exception_detail::error_info_container174             ~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 
exception()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.
exception(exception const & x)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::
~exception()296     ~exception() BOOST_NOEXCEPT_OR_NOTHROW
297         {
298         }
299 
300     namespace
301     exception_detail
302         {
303         template <class E>
304         E const &
set_info(E const & x,throw_function const & y)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 &
set_info(E const & x,throw_file const & y)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 &
set_info(E const & x,throw_line const & y)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
error_info_injectorboost::exception_detail::error_info_injector341             error_info_injector( T const & x ):
342                 T(x)
343                 {
344                 }
345 
~error_info_injectorboost::exception_detail::error_info_injector346             ~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
enable_error_info(T const & x)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
~clone_base()407             ~clone_base() BOOST_NOEXCEPT_OR_NOTHROW
408                 {
409                 }
410             };
411 
412         inline
413         void
copy_boost_exception(exception * a,exception const * b)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
copy_boost_exception(void *,void const *)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 { };
clone_impl(clone_impl const & x,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
clone_impl(T const & x)448             clone_impl( T const & x ):
449                 T(x)
450                 {
451                 copy_boost_exception(this,&x);
452                 }
453 
~clone_impl()454             ~clone_impl() BOOST_NOEXCEPT_OR_NOTHROW
455                 {
456                 }
457 
458             private:
459 
460             clone_base const *
clone() const461             clone() const
462                 {
463                 return new clone_impl(*this,clone_tag());
464                 }
465 
466             void
rethrow() const467             rethrow() const
468                 {
469                 throw*this;
470                 }
471             };
472         }
473 
474     template <class T>
475     inline
476     exception_detail::clone_impl<T>
enable_current_exception(T const & x)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