• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #ifndef BOOST_CONTRACT_DETAIL_INLINED_EXCEPTION_HPP_
3 #define BOOST_CONTRACT_DETAIL_INLINED_EXCEPTION_HPP_
4 
5 // Copyright (C) 2008-2018 Lorenzo Caminiti
6 // Distributed under the Boost Software License, Version 1.0 (see accompanying
7 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
8 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
9 
10 // IMPORTANT: Do NOT use config macros BOOST_CONTRACT_... in this file so lib
11 // .cpp does not need recompiling if config changes (recompile only user code).
12 
13 #include <boost/contract/core/exception.hpp>
14 #include <boost/contract/detail/static_local_var.hpp>
15 #include <boost/contract/detail/declspec.hpp>
16 #include <boost/thread/lock_guard.hpp>
17 #include <boost/thread/mutex.hpp>
18 #include <boost/exception/diagnostic_information.hpp>
19 #include <boost/config.hpp>
20 #include <string>
21 #include <sstream>
22 #include <iostream>
23 #include <exception>
24 
25 namespace boost { namespace contract {
26 
27 BOOST_CONTRACT_DETAIL_DECLINLINE
~exception()28 exception::~exception() BOOST_NOEXCEPT_OR_NOTHROW {}
29 
30 BOOST_CONTRACT_DETAIL_DECLINLINE
bad_virtual_result_cast(char const * from_type_name,char const * to_type_name)31 bad_virtual_result_cast::bad_virtual_result_cast(char const* from_type_name,
32             char const* to_type_name) {
33     std::ostringstream text;
34     text
35         << "incompatible contracted virtual function result type "
36         << "conversion from '" << from_type_name << "' to '"
37         << to_type_name  << "'"
38     ;
39     what_ = text.str();
40 }
41 
42 BOOST_CONTRACT_DETAIL_DECLINLINE
~bad_virtual_result_cast()43 bad_virtual_result_cast::~bad_virtual_result_cast() BOOST_NOEXCEPT_OR_NOTHROW {}
44 
45 BOOST_CONTRACT_DETAIL_DECLINLINE
what() const46 char const* bad_virtual_result_cast::what() const BOOST_NOEXCEPT_OR_NOTHROW {
47     return what_.c_str();
48 }
49 
50 BOOST_CONTRACT_DETAIL_DECLINLINE
assertion_failure(char const * const file,unsigned long const line,char const * const code)51 assertion_failure::assertion_failure(char const* const file,
52         unsigned long const line, char const* const code) :
53     file_(file), line_(line), code_(code)
54 { init(); }
55 
56 BOOST_CONTRACT_DETAIL_DECLINLINE
assertion_failure(char const * const code)57 assertion_failure::assertion_failure(char const* const code) :
58     file_(""), line_(0), code_(code)
59 { init(); }
60 
61 BOOST_CONTRACT_DETAIL_DECLINLINE
~assertion_failure()62 assertion_failure::~assertion_failure() BOOST_NOEXCEPT_OR_NOTHROW {}
63 
64 BOOST_CONTRACT_DETAIL_DECLINLINE
what() const65 char const* assertion_failure::what() const BOOST_NOEXCEPT_OR_NOTHROW {
66     return what_.c_str();
67 }
68 
69 BOOST_CONTRACT_DETAIL_DECLINLINE
file() const70 char const* assertion_failure::file() const { return file_; }
71 
72 BOOST_CONTRACT_DETAIL_DECLINLINE
line() const73 unsigned long assertion_failure::line() const { return line_; }
74 
75 BOOST_CONTRACT_DETAIL_DECLINLINE
code() const76 char const* assertion_failure::code() const { return code_; }
77 
78 BOOST_CONTRACT_DETAIL_DECLINLINE
init()79 void assertion_failure::init() {
80     std::ostringstream text;
81     text << "assertion";
82     if(std::string(code_) != "") text << " \"" << code_ << "\"";
83     text << " failed";
84     if(std::string(file_) != "") {
85         text << ": file \"" << file_ << "\"";
86         if(line_ != 0) text << ", line " << line_;
87     }
88     what_ = text.str();
89 }
90 
91 namespace exception_ {
92     enum failure_key {
93         check_failure_key,
94         pre_failure_key,
95         post_failure_key,
96         except_failure_key,
97         old_failure_key,
98         entry_inv_failure_key,
99         exit_inv_failure_key
100     };
101 
102     template<failure_key Key>
default_handler()103     void default_handler() {
104         std::string k = "";
105         switch(Key) {
106             case check_failure_key: k = "check "; break;
107             case pre_failure_key: k = "precondition "; break;
108             case post_failure_key: k = "postcondition "; break;
109             case except_failure_key: k = "except "; break;
110             case old_failure_key: k = "old copy "; break;
111             case entry_inv_failure_key: k = "entry invariant "; break;
112             case exit_inv_failure_key: k = "exit invariant "; break;
113             // No default (so compiler warning/error on missing enum case).
114         }
115         try { throw; }
116         catch(boost::contract::assertion_failure const& error) {
117             // what = "assertion '...' failed: ...".
118             std::cerr << k << error.what() << std::endl;
119         } catch(...) { // old_failure_key prints this, not above.
120             std::cerr << k << "threw following exception:" << std::endl
121                     << boost::current_exception_diagnostic_information();
122         }
123         std::terminate(); // Default handlers log and call terminate.
124     }
125 
126     template<failure_key Key>
default_from_handler(from)127     void default_from_handler(from) { default_handler<Key>(); }
128 
129     // Check failure.
130 
131     struct check_failure_mutex_tag;
132     typedef boost::contract::detail::static_local_var<check_failure_mutex_tag,
133             boost::mutex> check_failure_mutex;
134 
135     struct check_failure_handler_tag;
136     typedef boost::contract::detail::static_local_var_init<
137         check_failure_handler_tag,
138         failure_handler,
139         void (*)(),
140         &default_handler<check_failure_key>
141     > check_failure_handler;
142 
143     BOOST_CONTRACT_DETAIL_DECLINLINE
set_check_failure_unlocked(failure_handler const & f)144     failure_handler const& set_check_failure_unlocked(failure_handler const& f)
145             BOOST_NOEXCEPT_OR_NOTHROW {
146         check_failure_handler::ref() = f;
147         return f;
148     }
149 
150     BOOST_CONTRACT_DETAIL_DECLINLINE
set_check_failure_locked(failure_handler const & f)151     failure_handler const& set_check_failure_locked(failure_handler const& f)
152             BOOST_NOEXCEPT_OR_NOTHROW {
153         boost::lock_guard<boost::mutex> lock(check_failure_mutex::ref());
154         return set_check_failure_unlocked(f);
155     }
156 
157     BOOST_CONTRACT_DETAIL_DECLINLINE
get_check_failure_unlocked()158     failure_handler get_check_failure_unlocked() BOOST_NOEXCEPT_OR_NOTHROW {
159         return check_failure_handler::ref();
160     }
161 
162     BOOST_CONTRACT_DETAIL_DECLINLINE
get_check_failure_locked()163     failure_handler get_check_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
164         boost::lock_guard<boost::mutex> lock(check_failure_mutex::ref());
165         return get_check_failure_unlocked();
166     }
167 
168     BOOST_CONTRACT_DETAIL_DECLINLINE
check_failure_unlocked()169     void check_failure_unlocked() /* can throw */ {
170         check_failure_handler::ref()();
171     }
172 
173     BOOST_CONTRACT_DETAIL_DECLINLINE
check_failure_locked()174     void check_failure_locked() /* can throw */ {
175         boost::lock_guard<boost::mutex> lock(check_failure_mutex::ref());
176         check_failure_unlocked();
177     }
178 
179     // Precondition failure.
180 
181     struct pre_failure_mutex_tag;
182     typedef boost::contract::detail::static_local_var<pre_failure_mutex_tag,
183             boost::mutex> pre_failure_mutex;
184 
185     struct pre_failure_handler_tag;
186     typedef boost::contract::detail::static_local_var_init<
187         pre_failure_handler_tag,
188         from_failure_handler,
189         void (*)(from),
190         &default_from_handler<pre_failure_key>
191     > pre_failure_handler;
192 
193     BOOST_CONTRACT_DETAIL_DECLINLINE
set_pre_failure_unlocked(from_failure_handler const & f)194     from_failure_handler const& set_pre_failure_unlocked(from_failure_handler
195             const& f) BOOST_NOEXCEPT_OR_NOTHROW {
196         pre_failure_handler::ref() = f;
197         return f;
198     }
199 
200     BOOST_CONTRACT_DETAIL_DECLINLINE
set_pre_failure_locked(from_failure_handler const & f)201     from_failure_handler const& set_pre_failure_locked(from_failure_handler
202             const& f) BOOST_NOEXCEPT_OR_NOTHROW {
203         boost::lock_guard<boost::mutex> lock(pre_failure_mutex::ref());
204         return set_pre_failure_unlocked(f);
205     }
206 
207     BOOST_CONTRACT_DETAIL_DECLINLINE
get_pre_failure_unlocked()208     from_failure_handler get_pre_failure_unlocked() BOOST_NOEXCEPT_OR_NOTHROW {
209         return pre_failure_handler::ref();
210     }
211 
212     BOOST_CONTRACT_DETAIL_DECLINLINE
get_pre_failure_locked()213     from_failure_handler get_pre_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
214         boost::lock_guard<boost::mutex> lock(pre_failure_mutex::ref());
215         return get_pre_failure_unlocked();
216     }
217 
218     BOOST_CONTRACT_DETAIL_DECLINLINE
pre_failure_unlocked(from where)219     void pre_failure_unlocked(from where) /* can throw */ {
220         pre_failure_handler::ref()(where);
221     }
222 
223     BOOST_CONTRACT_DETAIL_DECLINLINE
pre_failure_locked(from where)224     void pre_failure_locked(from where) /* can throw */ {
225         boost::lock_guard<boost::mutex> lock(pre_failure_mutex::ref());
226         pre_failure_unlocked(where);
227     }
228 
229     // Postcondition failure.
230 
231     struct post_failure_mutex_tag;
232     typedef boost::contract::detail::static_local_var<post_failure_mutex_tag,
233             boost::mutex> post_failure_mutex;
234 
235     struct post_failure_handler_tag;
236     typedef boost::contract::detail::static_local_var_init<
237         post_failure_handler_tag,
238         from_failure_handler,
239         void (*)(from),
240         &default_from_handler<post_failure_key>
241     > post_failure_handler;
242 
243     BOOST_CONTRACT_DETAIL_DECLINLINE
set_post_failure_unlocked(from_failure_handler const & f)244     from_failure_handler const& set_post_failure_unlocked(from_failure_handler
245             const& f) BOOST_NOEXCEPT_OR_NOTHROW {
246         post_failure_handler::ref() = f;
247         return f;
248     }
249 
250     BOOST_CONTRACT_DETAIL_DECLINLINE
set_post_failure_locked(from_failure_handler const & f)251     from_failure_handler const& set_post_failure_locked(from_failure_handler
252             const& f) BOOST_NOEXCEPT_OR_NOTHROW {
253         boost::lock_guard<boost::mutex> lock(post_failure_mutex::ref());
254         return set_post_failure_unlocked(f);
255     }
256 
257     BOOST_CONTRACT_DETAIL_DECLINLINE
get_post_failure_unlocked()258     from_failure_handler get_post_failure_unlocked() BOOST_NOEXCEPT_OR_NOTHROW {
259         return post_failure_handler::ref();
260     }
261 
262     BOOST_CONTRACT_DETAIL_DECLINLINE
get_post_failure_locked()263     from_failure_handler get_post_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
264         boost::lock_guard<boost::mutex> lock(post_failure_mutex::ref());
265         return get_post_failure_unlocked();
266     }
267 
268     BOOST_CONTRACT_DETAIL_DECLINLINE
post_failure_unlocked(from where)269     void post_failure_unlocked(from where) /* can throw */ {
270         post_failure_handler::ref()(where);
271     }
272 
273     BOOST_CONTRACT_DETAIL_DECLINLINE
post_failure_locked(from where)274     void post_failure_locked(from where) /* can throw */ {
275         boost::lock_guard<boost::mutex> lock(post_failure_mutex::ref());
276         post_failure_unlocked(where);
277     }
278 
279     // Except failure.
280 
281     struct except_failure_mutex_tag;
282     typedef boost::contract::detail::static_local_var<except_failure_mutex_tag,
283             boost::mutex> except_failure_mutex;
284 
285     struct except_failure_handler_tag;
286     typedef boost::contract::detail::static_local_var_init<
287         except_failure_handler_tag,
288         from_failure_handler,
289         void (*)(from),
290         &default_from_handler<except_failure_key>
291     > except_failure_handler;
292 
293     BOOST_CONTRACT_DETAIL_DECLINLINE
set_except_failure_unlocked(from_failure_handler const & f)294     from_failure_handler const& set_except_failure_unlocked(from_failure_handler
295             const& f) BOOST_NOEXCEPT_OR_NOTHROW {
296         except_failure_handler::ref() = f;
297         return f;
298     }
299 
300     BOOST_CONTRACT_DETAIL_DECLINLINE
set_except_failure_locked(from_failure_handler const & f)301     from_failure_handler const& set_except_failure_locked(from_failure_handler
302             const& f) BOOST_NOEXCEPT_OR_NOTHROW {
303         boost::lock_guard<boost::mutex> lock(except_failure_mutex::ref());
304         return set_except_failure_unlocked(f);
305     }
306 
307     BOOST_CONTRACT_DETAIL_DECLINLINE
get_except_failure_unlocked()308     from_failure_handler get_except_failure_unlocked()
309             BOOST_NOEXCEPT_OR_NOTHROW {
310         return except_failure_handler::ref();
311     }
312 
313     BOOST_CONTRACT_DETAIL_DECLINLINE
get_except_failure_locked()314     from_failure_handler get_except_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
315         boost::lock_guard<boost::mutex> lock(except_failure_mutex::ref());
316         return get_except_failure_unlocked();
317     }
318 
319     BOOST_CONTRACT_DETAIL_DECLINLINE
except_failure_unlocked(from where)320     void except_failure_unlocked(from where) /* can throw */ {
321         except_failure_handler::ref()(where);
322     }
323 
324     BOOST_CONTRACT_DETAIL_DECLINLINE
except_failure_locked(from where)325     void except_failure_locked(from where) /* can throw */ {
326         boost::lock_guard<boost::mutex> lock(except_failure_mutex::ref());
327         except_failure_unlocked(where);
328     }
329 
330     // Old-copy failure.
331 
332     struct old_failure_mutex_tag;
333     typedef boost::contract::detail::static_local_var<old_failure_mutex_tag,
334             boost::mutex> old_failure_mutex;
335 
336     struct old_failure_handler_tag;
337     typedef boost::contract::detail::static_local_var_init<
338         old_failure_handler_tag,
339         from_failure_handler,
340         void (*)(from),
341         &default_from_handler<old_failure_key>
342     > old_failure_handler;
343 
344     BOOST_CONTRACT_DETAIL_DECLINLINE
set_old_failure_unlocked(from_failure_handler const & f)345     from_failure_handler const& set_old_failure_unlocked(from_failure_handler
346             const& f) BOOST_NOEXCEPT_OR_NOTHROW {
347         old_failure_handler::ref() = f;
348         return f;
349     }
350 
351     BOOST_CONTRACT_DETAIL_DECLINLINE
set_old_failure_locked(from_failure_handler const & f)352     from_failure_handler const& set_old_failure_locked(from_failure_handler
353             const& f) BOOST_NOEXCEPT_OR_NOTHROW {
354         boost::lock_guard<boost::mutex> lock(old_failure_mutex::ref());
355         return set_old_failure_unlocked(f);
356     }
357 
358     BOOST_CONTRACT_DETAIL_DECLINLINE
get_old_failure_unlocked()359     from_failure_handler get_old_failure_unlocked() BOOST_NOEXCEPT_OR_NOTHROW {
360         return old_failure_handler::ref();
361     }
362 
363     BOOST_CONTRACT_DETAIL_DECLINLINE
get_old_failure_locked()364     from_failure_handler get_old_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
365         boost::lock_guard<boost::mutex> lock(old_failure_mutex::ref());
366         return get_old_failure_unlocked();
367     }
368 
369     BOOST_CONTRACT_DETAIL_DECLINLINE
old_failure_unlocked(from where)370     void old_failure_unlocked(from where) /* can throw */ {
371         old_failure_handler::ref()(where);
372     }
373 
374     BOOST_CONTRACT_DETAIL_DECLINLINE
old_failure_locked(from where)375     void old_failure_locked(from where) /* can throw */ {
376         boost::lock_guard<boost::mutex> lock(old_failure_mutex::ref());
377         old_failure_unlocked(where);
378     }
379 
380     // Entry invariant failure.
381 
382     struct entry_inv_failure_mutex_tag;
383     typedef boost::contract::detail::static_local_var<
384             entry_inv_failure_mutex_tag, boost::mutex> entry_inv_failure_mutex;
385 
386     struct entry_inv_failure_handler_tag;
387     typedef boost::contract::detail::static_local_var_init<
388         entry_inv_failure_handler_tag,
389         from_failure_handler,
390         void (*)(from),
391         &default_from_handler<entry_inv_failure_key>
392     > entry_inv_failure_handler;
393 
394     BOOST_CONTRACT_DETAIL_DECLINLINE
set_entry_inv_failure_unlocked(from_failure_handler const & f)395     from_failure_handler const& set_entry_inv_failure_unlocked(
396             from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
397         entry_inv_failure_handler::ref() = f;
398         return f;
399     }
400 
401     BOOST_CONTRACT_DETAIL_DECLINLINE
set_entry_inv_failure_locked(from_failure_handler const & f)402     from_failure_handler const& set_entry_inv_failure_locked(
403             from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
404         boost::lock_guard<boost::mutex> lock(entry_inv_failure_mutex::ref());
405         return set_entry_inv_failure_unlocked(f);
406     }
407 
408     BOOST_CONTRACT_DETAIL_DECLINLINE
get_entry_inv_failure_unlocked()409     from_failure_handler get_entry_inv_failure_unlocked()
410             BOOST_NOEXCEPT_OR_NOTHROW {
411         return entry_inv_failure_handler::ref();
412     }
413 
414     BOOST_CONTRACT_DETAIL_DECLINLINE
get_entry_inv_failure_locked()415     from_failure_handler get_entry_inv_failure_locked()
416             BOOST_NOEXCEPT_OR_NOTHROW {
417         boost::lock_guard<boost::mutex> lock(entry_inv_failure_mutex::ref());
418         return get_entry_inv_failure_unlocked();
419     }
420 
421     BOOST_CONTRACT_DETAIL_DECLINLINE
entry_inv_failure_unlocked(from where)422     void entry_inv_failure_unlocked(from where) /* can throw */ {
423         entry_inv_failure_handler::ref()(where);
424     }
425 
426     BOOST_CONTRACT_DETAIL_DECLINLINE
entry_inv_failure_locked(from where)427     void entry_inv_failure_locked(from where) /* can throw */ {
428         boost::lock_guard<boost::mutex> lock(entry_inv_failure_mutex::ref());
429         entry_inv_failure_unlocked(where);
430     }
431 
432     // Exit invariant failure.
433 
434     struct exit_inv_failure_mutex_tag;
435     typedef boost::contract::detail::static_local_var<
436             exit_inv_failure_mutex_tag, boost::mutex> exit_inv_failure_mutex;
437 
438     struct exit_inv_failure_handler_tag;
439     typedef boost::contract::detail::static_local_var_init<
440         exit_inv_failure_handler_tag,
441         from_failure_handler,
442         void (*)(from),
443         &default_from_handler<exit_inv_failure_key>
444     > exit_inv_failure_handler;
445 
446     BOOST_CONTRACT_DETAIL_DECLINLINE
set_exit_inv_failure_unlocked(from_failure_handler const & f)447     from_failure_handler const& set_exit_inv_failure_unlocked(
448             from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
449         exit_inv_failure_handler::ref() = f;
450         return f;
451     }
452 
453     BOOST_CONTRACT_DETAIL_DECLINLINE
set_exit_inv_failure_locked(from_failure_handler const & f)454     from_failure_handler const& set_exit_inv_failure_locked(
455             from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
456         boost::lock_guard<boost::mutex> lock(exit_inv_failure_mutex::ref());
457         return set_exit_inv_failure_unlocked(f);
458     }
459 
460     BOOST_CONTRACT_DETAIL_DECLINLINE
get_exit_inv_failure_unlocked()461     from_failure_handler get_exit_inv_failure_unlocked()
462             BOOST_NOEXCEPT_OR_NOTHROW {
463         return exit_inv_failure_handler::ref();
464     }
465 
466     BOOST_CONTRACT_DETAIL_DECLINLINE
get_exit_inv_failure_locked()467     from_failure_handler get_exit_inv_failure_locked()
468             BOOST_NOEXCEPT_OR_NOTHROW {
469         boost::lock_guard<boost::mutex> lock(exit_inv_failure_mutex::ref());
470         return get_exit_inv_failure_unlocked();
471     }
472 
473     BOOST_CONTRACT_DETAIL_DECLINLINE
exit_inv_failure_unlocked(from where)474     void exit_inv_failure_unlocked(from where) /* can throw */ {
475         exit_inv_failure_handler::ref()(where);
476     }
477 
478     BOOST_CONTRACT_DETAIL_DECLINLINE
exit_inv_failure_locked(from where)479     void exit_inv_failure_locked(from where) /* can throw */ {
480         boost::lock_guard<boost::mutex> lock(exit_inv_failure_mutex::ref());
481         exit_inv_failure_unlocked(where);
482     }
483 }
484 
485 from_failure_handler const& set_entry_invariant_failure(
486         from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
487 
488 from_failure_handler const& set_exit_invariant_failure(
489         from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
490 
491 BOOST_CONTRACT_DETAIL_DECLINLINE
set_invariant_failure(from_failure_handler const & f)492 from_failure_handler const& set_invariant_failure(
493         from_failure_handler const& f)  BOOST_NOEXCEPT_OR_NOTHROW {
494     set_entry_invariant_failure(f);
495     set_exit_invariant_failure(f);
496     return f;
497 }
498 
499 } } // namespace
500 
501 #endif // #include guard
502 
503