#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 #include #include #include #include #include #include #include #include #include #include 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 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 void default_from_handler(from) { default_handler(); } // Check failure. struct check_failure_mutex_tag; typedef boost::contract::detail::static_local_var 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_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 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 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 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; 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_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 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 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 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; 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_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 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 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 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; 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_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 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 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 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; 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_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 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 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 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_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 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 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 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_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 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 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 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