boost/contract/detail/inlined/core/exception.hpp
#ifndef BOOST_CONTRACT_DETAIL_INLINED_EXCEPTION_HPP_
#define BOOST_CONTRACT_DETAIL_INLINED_EXCEPTION_HPP_
// Copyright (C) 2008-2018 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0 (see accompanying
// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
// IMPORTANT: Do NOT use config macros BOOST_CONTRACT_... in this file so lib
// .cpp does not need recompiling if config changes (recompile only user code).
#include <boost/contract/core/exception.hpp>
#include <boost/contract/detail/static_local_var.hpp>
#include <boost/contract/detail/declspec.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/config.hpp>
#include <string>
#include <sstream>
#include <iostream>
#include <exception>
namespace boost { namespace contract {
BOOST_CONTRACT_DETAIL_DECLINLINE
exception::~exception() BOOST_NOEXCEPT_OR_NOTHROW {}
BOOST_CONTRACT_DETAIL_DECLINLINE
bad_virtual_result_cast::bad_virtual_result_cast(char const* from_type_name,
char const* to_type_name) {
std::ostringstream text;
text
<< "incompatible contracted virtual function result type "
<< "conversion from '" << from_type_name << "' to '"
<< to_type_name << "'"
;
what_ = text.str();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
bad_virtual_result_cast::~bad_virtual_result_cast() BOOST_NOEXCEPT_OR_NOTHROW {}
BOOST_CONTRACT_DETAIL_DECLINLINE
char const* bad_virtual_result_cast::what() const BOOST_NOEXCEPT_OR_NOTHROW {
return what_.c_str();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
assertion_failure::assertion_failure(char const* const file,
unsigned long const line, char const* const code) :
file_(file), line_(line), code_(code)
{ init(); }
BOOST_CONTRACT_DETAIL_DECLINLINE
assertion_failure::assertion_failure(char const* const code) :
file_(""), line_(0), code_(code)
{ init(); }
BOOST_CONTRACT_DETAIL_DECLINLINE
assertion_failure::~assertion_failure() BOOST_NOEXCEPT_OR_NOTHROW {}
BOOST_CONTRACT_DETAIL_DECLINLINE
char const* assertion_failure::what() const BOOST_NOEXCEPT_OR_NOTHROW {
return what_.c_str();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
char const* assertion_failure::file() const { return file_; }
BOOST_CONTRACT_DETAIL_DECLINLINE
unsigned long assertion_failure::line() const { return line_; }
BOOST_CONTRACT_DETAIL_DECLINLINE
char const* assertion_failure::code() const { return code_; }
BOOST_CONTRACT_DETAIL_DECLINLINE
void assertion_failure::init() {
std::ostringstream text;
text << "assertion";
if(std::string(code_) != "") text << " \"" << code_ << "\"";
text << " failed";
if(std::string(file_) != "") {
text << ": file \"" << file_ << "\"";
if(line_ != 0) text << ", line " << line_;
}
what_ = text.str();
}
namespace exception_ {
enum failure_key {
check_failure_key,
pre_failure_key,
post_failure_key,
except_failure_key,
old_failure_key,
entry_inv_failure_key,
exit_inv_failure_key
};
template<failure_key Key>
void default_handler() {
std::string k = "";
switch(Key) {
case check_failure_key: k = "check "; break;
case pre_failure_key: k = "precondition "; break;
case post_failure_key: k = "postcondition "; break;
case except_failure_key: k = "except "; break;
case old_failure_key: k = "old copy "; break;
case entry_inv_failure_key: k = "entry invariant "; break;
case exit_inv_failure_key: k = "exit invariant "; break;
// No default (so compiler warning/error on missing enum case).
}
try { throw; }
catch(boost::contract::assertion_failure const& error) {
// what = "assertion '...' failed: ...".
std::cerr << k << error.what() << std::endl;
} catch(...) { // old_failure_key prints this, not above.
std::cerr << k << "threw following exception:" << std::endl
<< boost::current_exception_diagnostic_information();
}
std::terminate(); // Default handlers log and call terminate.
}
template<failure_key Key>
void default_from_handler(from) { default_handler<Key>(); }
// Check failure.
struct check_failure_mutex_tag;
typedef boost::contract::detail::static_local_var<check_failure_mutex_tag,
boost::mutex> check_failure_mutex;
struct check_failure_handler_tag;
typedef boost::contract::detail::static_local_var_init<
check_failure_handler_tag,
failure_handler,
void (*)(),
&default_handler<check_failure_key>
> check_failure_handler;
BOOST_CONTRACT_DETAIL_DECLINLINE
failure_handler const& set_check_failure_unlocked(failure_handler const& f)
BOOST_NOEXCEPT_OR_NOTHROW {
check_failure_handler::ref() = f;
return f;
}
BOOST_CONTRACT_DETAIL_DECLINLINE
failure_handler const& set_check_failure_locked(failure_handler const& f)
BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(check_failure_mutex::ref());
return set_check_failure_unlocked(f);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
failure_handler get_check_failure_unlocked() BOOST_NOEXCEPT_OR_NOTHROW {
return check_failure_handler::ref();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
failure_handler get_check_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(check_failure_mutex::ref());
return get_check_failure_unlocked();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void check_failure_unlocked() /* can throw */ {
check_failure_handler::ref()();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void check_failure_locked() /* can throw */ {
boost::lock_guard<boost::mutex> lock(check_failure_mutex::ref());
check_failure_unlocked();
}
// Precondition failure.
struct pre_failure_mutex_tag;
typedef boost::contract::detail::static_local_var<pre_failure_mutex_tag,
boost::mutex> pre_failure_mutex;
struct pre_failure_handler_tag;
typedef boost::contract::detail::static_local_var_init<
pre_failure_handler_tag,
from_failure_handler,
void (*)(from),
&default_from_handler<pre_failure_key>
> pre_failure_handler;
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_pre_failure_unlocked(from_failure_handler
const& f) BOOST_NOEXCEPT_OR_NOTHROW {
pre_failure_handler::ref() = f;
return f;
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_pre_failure_locked(from_failure_handler
const& f) BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(pre_failure_mutex::ref());
return set_pre_failure_unlocked(f);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_pre_failure_unlocked() BOOST_NOEXCEPT_OR_NOTHROW {
return pre_failure_handler::ref();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_pre_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(pre_failure_mutex::ref());
return get_pre_failure_unlocked();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void pre_failure_unlocked(from where) /* can throw */ {
pre_failure_handler::ref()(where);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void pre_failure_locked(from where) /* can throw */ {
boost::lock_guard<boost::mutex> lock(pre_failure_mutex::ref());
pre_failure_unlocked(where);
}
// Postcondition failure.
struct post_failure_mutex_tag;
typedef boost::contract::detail::static_local_var<post_failure_mutex_tag,
boost::mutex> post_failure_mutex;
struct post_failure_handler_tag;
typedef boost::contract::detail::static_local_var_init<
post_failure_handler_tag,
from_failure_handler,
void (*)(from),
&default_from_handler<post_failure_key>
> post_failure_handler;
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_post_failure_unlocked(from_failure_handler
const& f) BOOST_NOEXCEPT_OR_NOTHROW {
post_failure_handler::ref() = f;
return f;
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_post_failure_locked(from_failure_handler
const& f) BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(post_failure_mutex::ref());
return set_post_failure_unlocked(f);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_post_failure_unlocked() BOOST_NOEXCEPT_OR_NOTHROW {
return post_failure_handler::ref();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_post_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(post_failure_mutex::ref());
return get_post_failure_unlocked();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void post_failure_unlocked(from where) /* can throw */ {
post_failure_handler::ref()(where);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void post_failure_locked(from where) /* can throw */ {
boost::lock_guard<boost::mutex> lock(post_failure_mutex::ref());
post_failure_unlocked(where);
}
// Except failure.
struct except_failure_mutex_tag;
typedef boost::contract::detail::static_local_var<except_failure_mutex_tag,
boost::mutex> except_failure_mutex;
struct except_failure_handler_tag;
typedef boost::contract::detail::static_local_var_init<
except_failure_handler_tag,
from_failure_handler,
void (*)(from),
&default_from_handler<except_failure_key>
> except_failure_handler;
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_except_failure_unlocked(from_failure_handler
const& f) BOOST_NOEXCEPT_OR_NOTHROW {
except_failure_handler::ref() = f;
return f;
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_except_failure_locked(from_failure_handler
const& f) BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(except_failure_mutex::ref());
return set_except_failure_unlocked(f);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_except_failure_unlocked()
BOOST_NOEXCEPT_OR_NOTHROW {
return except_failure_handler::ref();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_except_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(except_failure_mutex::ref());
return get_except_failure_unlocked();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void except_failure_unlocked(from where) /* can throw */ {
except_failure_handler::ref()(where);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void except_failure_locked(from where) /* can throw */ {
boost::lock_guard<boost::mutex> lock(except_failure_mutex::ref());
except_failure_unlocked(where);
}
// Old-copy failure.
struct old_failure_mutex_tag;
typedef boost::contract::detail::static_local_var<old_failure_mutex_tag,
boost::mutex> old_failure_mutex;
struct old_failure_handler_tag;
typedef boost::contract::detail::static_local_var_init<
old_failure_handler_tag,
from_failure_handler,
void (*)(from),
&default_from_handler<old_failure_key>
> old_failure_handler;
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_old_failure_unlocked(from_failure_handler
const& f) BOOST_NOEXCEPT_OR_NOTHROW {
old_failure_handler::ref() = f;
return f;
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_old_failure_locked(from_failure_handler
const& f) BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(old_failure_mutex::ref());
return set_old_failure_unlocked(f);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_old_failure_unlocked() BOOST_NOEXCEPT_OR_NOTHROW {
return old_failure_handler::ref();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_old_failure_locked() BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(old_failure_mutex::ref());
return get_old_failure_unlocked();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void old_failure_unlocked(from where) /* can throw */ {
old_failure_handler::ref()(where);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void old_failure_locked(from where) /* can throw */ {
boost::lock_guard<boost::mutex> lock(old_failure_mutex::ref());
old_failure_unlocked(where);
}
// Entry invariant failure.
struct entry_inv_failure_mutex_tag;
typedef boost::contract::detail::static_local_var<
entry_inv_failure_mutex_tag, boost::mutex> entry_inv_failure_mutex;
struct entry_inv_failure_handler_tag;
typedef boost::contract::detail::static_local_var_init<
entry_inv_failure_handler_tag,
from_failure_handler,
void (*)(from),
&default_from_handler<entry_inv_failure_key>
> entry_inv_failure_handler;
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_entry_inv_failure_unlocked(
from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
entry_inv_failure_handler::ref() = f;
return f;
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_entry_inv_failure_locked(
from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(entry_inv_failure_mutex::ref());
return set_entry_inv_failure_unlocked(f);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_entry_inv_failure_unlocked()
BOOST_NOEXCEPT_OR_NOTHROW {
return entry_inv_failure_handler::ref();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_entry_inv_failure_locked()
BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(entry_inv_failure_mutex::ref());
return get_entry_inv_failure_unlocked();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void entry_inv_failure_unlocked(from where) /* can throw */ {
entry_inv_failure_handler::ref()(where);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void entry_inv_failure_locked(from where) /* can throw */ {
boost::lock_guard<boost::mutex> lock(entry_inv_failure_mutex::ref());
entry_inv_failure_unlocked(where);
}
// Exit invariant failure.
struct exit_inv_failure_mutex_tag;
typedef boost::contract::detail::static_local_var<
exit_inv_failure_mutex_tag, boost::mutex> exit_inv_failure_mutex;
struct exit_inv_failure_handler_tag;
typedef boost::contract::detail::static_local_var_init<
exit_inv_failure_handler_tag,
from_failure_handler,
void (*)(from),
&default_from_handler<exit_inv_failure_key>
> exit_inv_failure_handler;
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_exit_inv_failure_unlocked(
from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
exit_inv_failure_handler::ref() = f;
return f;
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_exit_inv_failure_locked(
from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(exit_inv_failure_mutex::ref());
return set_exit_inv_failure_unlocked(f);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_exit_inv_failure_unlocked()
BOOST_NOEXCEPT_OR_NOTHROW {
return exit_inv_failure_handler::ref();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler get_exit_inv_failure_locked()
BOOST_NOEXCEPT_OR_NOTHROW {
boost::lock_guard<boost::mutex> lock(exit_inv_failure_mutex::ref());
return get_exit_inv_failure_unlocked();
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void exit_inv_failure_unlocked(from where) /* can throw */ {
exit_inv_failure_handler::ref()(where);
}
BOOST_CONTRACT_DETAIL_DECLINLINE
void exit_inv_failure_locked(from where) /* can throw */ {
boost::lock_guard<boost::mutex> lock(exit_inv_failure_mutex::ref());
exit_inv_failure_unlocked(where);
}
}
from_failure_handler const& set_entry_invariant_failure(
from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
from_failure_handler const& set_exit_invariant_failure(
from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
BOOST_CONTRACT_DETAIL_DECLINLINE
from_failure_handler const& set_invariant_failure(
from_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW {
set_entry_invariant_failure(f);
set_exit_invariant_failure(f);
return f;
}
} } // namespace
#endif // #include guard