]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
f67539c2 TL |
6 | #ifndef BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593 |
7 | #define BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593 | |
92f5a8d4 TL |
8 | |
9 | #include <boost/config.hpp> | |
7c673cae | 10 | |
b32b8144 FG |
11 | #ifdef BOOST_EXCEPTION_MINI_BOOST |
12 | #include <memory> | |
13 | namespace boost { namespace exception_detail { using std::shared_ptr; } } | |
14 | #else | |
92f5a8d4 | 15 | namespace boost { template <class T> class shared_ptr; } |
b32b8144 FG |
16 | namespace boost { namespace exception_detail { using boost::shared_ptr; } } |
17 | #endif | |
18 | ||
f67539c2 TL |
19 | #if !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) |
20 | #if __GNUC__*100+__GNUC_MINOR__>301 | |
92f5a8d4 TL |
21 | #pragma GCC system_header |
22 | #endif | |
f67539c2 TL |
23 | #ifdef __clang__ |
24 | #pragma clang system_header | |
25 | #endif | |
26 | #ifdef _MSC_VER | |
92f5a8d4 TL |
27 | #pragma warning(push,1) |
28 | #pragma warning(disable: 4265) | |
29 | #endif | |
f67539c2 | 30 | #endif |
92f5a8d4 | 31 | |
7c673cae FG |
32 | namespace |
33 | boost | |
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(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 | ||
92f5a8d4 TL |
152 | class |
153 | BOOST_SYMBOL_VISIBLE | |
154 | exception; | |
7c673cae | 155 | |
7c673cae FG |
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 | ||
92f5a8d4 | 174 | ~error_info_container() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
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 | ||
7c673cae | 220 | class |
92f5a8d4 | 221 | BOOST_SYMBOL_VISIBLE |
7c673cae FG |
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. | |
92f5a8d4 | 242 | exception( exception const & x ) BOOST_NOEXCEPT_OR_NOTHROW: |
7c673cae FG |
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 | ||
92f5a8d4 | 251 | virtual ~exception() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
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 | }; | |
7c673cae FG |
293 | |
294 | inline | |
295 | exception:: | |
92f5a8d4 | 296 | ~exception() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
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 | { | |
7c673cae FG |
333 | template <class T> |
334 | struct | |
92f5a8d4 | 335 | BOOST_SYMBOL_VISIBLE |
7c673cae FG |
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 | ||
92f5a8d4 | 346 | ~error_info_injector() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
347 | { |
348 | } | |
349 | }; | |
7c673cae FG |
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 | { | |
7c673cae | 397 | class |
92f5a8d4 | 398 | BOOST_SYMBOL_VISIBLE |
7c673cae FG |
399 | clone_base |
400 | { | |
401 | public: | |
402 | ||
403 | virtual clone_base const * clone() const = 0; | |
404 | virtual void rethrow() const = 0; | |
405 | ||
406 | virtual | |
92f5a8d4 | 407 | ~clone_base() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
408 | { |
409 | } | |
410 | }; | |
7c673cae FG |
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 | ||
7c673cae FG |
431 | template <class T> |
432 | class | |
92f5a8d4 | 433 | BOOST_SYMBOL_VISIBLE |
7c673cae FG |
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 | ||
92f5a8d4 | 454 | ~clone_impl() BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
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 | } | |
7c673cae FG |
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 | |
f67539c2 TL |
486 | |
487 | #endif // #ifndef BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593 |