exception.hpp 13 KB

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