| // -*- C++ -*- std::contracts::contract_violation and friends |
| |
| // Copyright The GNU Toolchain Authors. |
| // |
| // This file is part of GCC. |
| // |
| // GCC is free software; you can redistribute it and/or modify |
| // it under the terms of the GNU General Public License as published by |
| // the Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| // |
| // GCC is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| // |
| // Under Section 7 of GPL version 3, you are granted additional |
| // permissions described in the GCC Runtime Library Exception, version |
| // 3.1, as published by the Free Software Foundation. |
| |
| // You should have received a copy of the GNU General Public License and |
| // a copy of the GCC Runtime Library Exception along with this program; |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| // <http://www.gnu.org/licenses/>. |
| |
| #include <contracts> |
| |
| #ifndef __cpp_lib_contracts |
| # error "This file requires C++26 contracts support to be enabled" |
| #endif |
| |
| #if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE |
| # include <iostream> |
| # include <cxxabi.h> |
| #endif |
| |
| void __handle_contract_violation(const std::contracts::contract_violation &violation) noexcept |
| { |
| #if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE |
| |
| std::cerr << "contract violation in function " << violation.location().function_name() |
| << " at " << violation.location().file_name() << ':' << violation.location().line() |
| << ": " << violation.comment(); |
| |
| const char* delimiter = "\n["; |
| |
| std::cerr << delimiter << "assertion_kind:"; |
| switch (violation.kind()) |
| { |
| case std::contracts::assertion_kind::pre: |
| std::cerr << " pre"; |
| break; |
| case std::contracts::assertion_kind::post: |
| std::cerr << " post"; |
| break; |
| case std::contracts::assertion_kind::assert: |
| std::cerr << " assert"; |
| break; |
| default: |
| std::cerr << " unknown" << (int) violation.semantic(); |
| } |
| delimiter = ", "; |
| |
| std::cerr << delimiter << "semantic:"; |
| switch (violation.semantic()) |
| { |
| case std::contracts::evaluation_semantic::enforce: |
| std::cerr << " enforce"; |
| break; |
| case std::contracts::evaluation_semantic::observe: |
| std::cerr << " observe"; |
| break; |
| default: |
| std::cerr << " unknown" << (int) violation.semantic(); |
| } |
| delimiter = ", "; |
| |
| std::cerr << delimiter << "mode:"; |
| switch (violation.mode()) |
| { |
| case std::contracts::detection_mode::predicate_false: |
| std::cerr << " predicate_false"; |
| break; |
| case std::contracts::detection_mode::evaluation_exception: |
| std::cerr << " evaluation_exception"; |
| break; |
| default: |
| std::cerr << "unknown"; |
| } |
| delimiter = ", "; |
| |
| if (violation.mode() == std::contracts::detection_mode::evaluation_exception) |
| { |
| /* Based on the impl. in vterminate.cc. */ |
| std::type_info *t = __cxxabiv1::__cxa_current_exception_type(); |
| if (t) |
| { |
| int status = -1; |
| char *dem = 0; |
| // Note that "name" is the mangled name. |
| char const *name = t->name(); |
| dem = __cxxabiv1::__cxa_demangle(name, 0, 0, &status); |
| std::cerr << ": threw an instance of '"; |
| std::cerr << ( status == 0 ? dem : name) << "'"; |
| } |
| else |
| std::cerr << ": threw an unknown type"; |
| } |
| |
| std::cerr << delimiter << "terminating:" |
| << (violation.is_terminating () ? " yes" : " no"); |
| |
| if (delimiter[0] == ',') |
| std::cerr << ']'; |
| |
| std::cerr << std::endl; |
| #endif |
| } |
| |
| namespace std _GLIBCXX_VISIBILITY(default) |
| { |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION |
| |
| namespace contracts |
| { |
| |
| void invoke_default_contract_violation_handler(const std::contracts::contract_violation& violation) noexcept |
| { |
| return __handle_contract_violation(violation); |
| } |
| |
| } |
| } |
| |
| __attribute__ ((weak)) void |
| handle_contract_violation (const std::contracts::contract_violation &violation) |
| { |
| return __handle_contract_violation(violation); |
| } |
| |
| #if _GLIBCXX_INLINE_VERSION |
| // The compiler expects the contract_violation class to be in an unversioned |
| // namespace, so provide a forwarding function with the expected symbol name. |
| extern "C" void |
| _Z25handle_contract_violationRKNSt9contracts18contract_violationE |
| (const std::contracts::contract_violation &violation) |
| { handle_contract_violation(violation); } |
| |
| extern "C" void |
| _Z27__handle_contract_violationRKNSt9contracts18contract_violationE |
| (const std::contracts::contract_violation &violation) |
| { __handle_contract_violation(violation); } |
| |
| extern "C" void |
| _Z41invoke_default_contract_violation_handlerRKNSt9contracts18contract_violationE |
| (const std::contracts::contract_violation &violation) |
| { invoke_default_contract_violation_handler(violation); } |
| |
| #endif |