Patch rebased onto r16-5785-g3b30d09ac7bbf8 (includes change to default to C++20)
> On 17 Nov 2025, at 06:57, Jonathan Wakely <[email protected]> wrote: >> * src/experimental/contract26.cc: New file. >> * testsuite/18_support/contracts/invoke_default_cvh.cc: New test. >> * testsuite/18_support/contracts/invoke_default_cvh2.cc: New test. >Should this define __cpp_lib_contracts and gate the contents of <contracts> >behind a preprocessor check for that feature test macro? As written here, >including <contracts> in C++98 more will just cause errors (for e.g. 'enum >class'). New ftm for contracts added. Flags hooked in where needed. > The new test cases are run for c++2a and later, should that be c++26 instead? Yes. Fixed. >>+// Copyright (C) 2019-2024 Free Software Foundation, Inc. > 2025 Fixed. >>+ class contract_violation; > This is not a reserved word before C++26 so should only be declared for C++26 > and later. Fixed in two places. >>+// Copyright (C) 2019-2024 Free Software Foundation, Inc. > 2025 Fixed. Revised version re-tested on x86_64-linux and x86_64-darwin. OK for trunk (when the other patches are approved)? Thank you, Nina --- 8< --- What we need to do here (and, of course, in the code synthesis that produces the objects) needs to be interoperable with other platforms that share ABI. For the present, this means Itanium and to interoperate with clang and libc++. The model we have followed in the development is essentially the same as the model used for the C++2a edition. However there is some concern that the read-only data footprint of this is potentially high and alternate schemes are in discussion with the clang folks. Since the layout of the violation object is ABI let's leave this in experimental until an agreed solution is fixed. Remove the cxx2a support at the same time, GCC no longer supports this mode. libstdc++-v3/ChangeLog: * include/Makefile.am: Add contract include. * include/Makefile.in: Regenerate. * include/bits/version.def: Add ftm for contracts. * include/bits/version.h: Regenerate. * include/std/source_location: Befriend the contract_violation class so that we can initialise a source_location from an existing __impl *. * src/experimental/Makefile.am: Add new contract violation implementation, remove the old one. * src/experimental/Makefile.in: Regenerate. * include/experimental/contract: Removed. * src/experimental/contract.cc: Removed. * include/std/contracts: New file. * src/experimental/contract26.cc: New file. * testsuite/18_support/contracts/invoke_default_cvh.cc: New test. * testsuite/18_support/contracts/invoke_default_cvh2.cc: New test. Co-Authored-by: Iain Sandoe <[email protected]> Co-Authored-by: Ville Voutilainen <[email protected]> Signed-off-by: Nina Ranns <[email protected]> --- libstdc++-v3/include/Makefile.am | 2 +- libstdc++-v3/include/Makefile.in | 2 +- libstdc++-v3/include/bits/version.def | 9 + libstdc++-v3/include/bits/version.h | 10 ++ libstdc++-v3/include/experimental/contract | 83 --------- libstdc++-v3/include/std/contracts | 116 +++++++++++++ libstdc++-v3/include/std/source_location | 14 ++ libstdc++-v3/src/experimental/Makefile.am | 8 +- libstdc++-v3/src/experimental/Makefile.in | 15 +- libstdc++-v3/src/experimental/contract.cc | 78 --------- libstdc++-v3/src/experimental/contract26.cc | 157 ++++++++++++++++++ .../contracts/invoke_default_cvh.cc | 40 +++++ .../contracts/invoke_default_cvh2.cc | 72 ++++++++ 13 files changed, 437 insertions(+), 169 deletions(-) delete mode 100644 libstdc++-v3/include/experimental/contract create mode 100644 libstdc++-v3/include/std/contracts delete mode 100644 libstdc++-v3/src/experimental/contract.cc create mode 100644 libstdc++-v3/src/experimental/contract26.cc create mode 100644 libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh.cc create mode 100644 libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh2.cc diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index ae7a7ca9073..7fb238d7a0d 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -32,6 +32,7 @@ std_freestanding = \ ${std_srcdir}/bit \ ${std_srcdir}/bitset \ ${std_srcdir}/concepts \ + ${std_srcdir}/contracts \ ${std_srcdir}/coroutine \ ${std_srcdir}/expected \ ${std_srcdir}/functional \ @@ -793,7 +794,6 @@ experimental_headers = \ ${experimental_srcdir}/array \ ${experimental_srcdir}/buffer \ ${experimental_srcdir}/chrono \ - ${experimental_srcdir}/contract \ ${experimental_srcdir}/deque \ ${experimental_srcdir}/executor \ ${experimental_srcdir}/forward_list \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index f07e2326816..f60f555c690 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -393,6 +393,7 @@ std_freestanding = \ ${std_srcdir}/bit \ ${std_srcdir}/bitset \ ${std_srcdir}/concepts \ + ${std_srcdir}/contracts \ ${std_srcdir}/coroutine \ ${std_srcdir}/expected \ ${std_srcdir}/functional \ @@ -1142,7 +1143,6 @@ experimental_headers = \ ${experimental_srcdir}/array \ ${experimental_srcdir}/buffer \ ${experimental_srcdir}/chrono \ - ${experimental_srcdir}/contract \ ${experimental_srcdir}/deque \ ${experimental_srcdir}/executor \ ${experimental_srcdir}/forward_list \ diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 1fde9eef9d3..8a7ef55766b 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -2211,6 +2211,15 @@ ftms = { }; }; +ftms = { + name = contracts; + values = { + v = 202502; + cxxmin = 26; + extra_cond = "__cpp_contracts >= 202502L"; + }; +}; + // Standard test specifications. stds[97] = ">= 199711L"; stds[03] = ">= 199711L"; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 2ebc48b234b..00c2037da5d 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2474,4 +2474,14 @@ #endif /* !defined(__cpp_lib_is_implicit_lifetime) */ #undef __glibcxx_want_is_implicit_lifetime +#if !defined(__cpp_lib_contracts) +# if (__cplusplus > 202302L) && (__cpp_contracts >= 202502L) +# define __glibcxx_contracts 202502L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_contracts) +# define __cpp_lib_contracts 202502L +# endif +# endif +#endif /* !defined(__cpp_lib_contracts) */ +#undef __glibcxx_want_contracts + #undef __glibcxx_want_all diff --git a/libstdc++-v3/include/experimental/contract b/libstdc++-v3/include/experimental/contract deleted file mode 100644 index 8b1be86db57..00000000000 --- a/libstdc++-v3/include/experimental/contract +++ /dev/null @@ -1,83 +0,0 @@ -// Contracts support header for -*- C++ -*- - -// Copyright (C) 2019-2025 Free Software Foundation, Inc. -// -// 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/>. - -/** @file contract - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_CONTRACT -#define _GLIBCXX_CONTRACT 1 - -#ifdef _GLIBCXX_SYSHDR -#pragma GCC system_header -#endif - -#if __cplusplus >= 201703L - -#include <string_view> -#include <cstdint> - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -namespace experimental -{ - // From P1332 - enum class contract_violation_continuation_mode { - never_continue, maybe_continue - }; - - class contract_violation { - const char* _M_file; - const char* _M_function; - const char* _M_comment; - const char* _M_level; - const char* _M_role; - uint_least32_t _M_line; - signed char _M_continue; - public: - // From N4820 - uint_least32_t line_number() const noexcept { return _M_line; } - string_view file_name() const noexcept { return _M_file; } - string_view function_name() const noexcept { return _M_function; } - string_view comment() const noexcept { return _M_comment; } - string_view assertion_level() const noexcept { return _M_level; } - // From P1332 - string_view assertion_role() const noexcept { return _M_role; } - contract_violation_continuation_mode continuation_mode() const noexcept - { return static_cast<contract_violation_continuation_mode>(_M_continue); } - }; - -} // namespace experimental - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -// To override the contract violation handler, define -//void ::handle_contract_violation (const std::experimental::contract_violation &); - -#endif // C++17 -#endif // _GLIBCXX_CONTRACT diff --git a/libstdc++-v3/include/std/contracts b/libstdc++-v3/include/std/contracts new file mode 100644 index 00000000000..3ca56481f1f --- /dev/null +++ b/libstdc++-v3/include/std/contracts @@ -0,0 +1,116 @@ +// Contracts support header for -*- C++ -*- + +// Copyright (C) 2025 Free Software Foundation, Inc. +// +// 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/>. + +/** @file contracts + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_CONTRACTS +#define _GLIBCXX_CONTRACTS 1 + +#pragma GCC system_header + +#define __glibcxx_want_contracts +#include <bits/version.h> + +#ifdef __cpp_lib_contracts +#include <source_location> +#include <cstdint> +#include <bits/exception_ptr.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace contracts +{ + // From P2900R14 + D3290R3 + + enum class assertion_kind : uint16_t { + pre = 1, + post = 2, + assert = 3, + // From D3290R3 + manual = 4, + cassert = 5, + + /* Implementation−defined values should have a minimum value of 1000. */ + }; + + enum class evaluation_semantic : uint16_t { + ignore = 1, + observe = 2, + enforce = 3, + quick_enforce = 4, + + /* Implementation−defined values should have a minimum value of 1000. */ + }; + + enum class detection_mode : uint16_t { + unspecified = 0, // From D3290R3 + predicate_false = 1, + evaluation_exception = 2, + + /* Implementation−defined values should have a minimum value of 1000. */ + }; + + using __vendor_ext = void; + + class contract_violation { + uint16_t _M_version; + assertion_kind _M_assertion_kind; + evaluation_semantic _M_evaluation_semantic; + detection_mode _M_detection_mode; + const char* _M_comment; + const void* _M_src_loc_ptr; + __vendor_ext* _M_ext; + + public: + // cannot be copied or moved or assigned to + contract_violation(const contract_violation&) = delete; + contract_violation& operator=(const contract_violation&) = delete; + + assertion_kind kind() const noexcept { return _M_assertion_kind; } + evaluation_semantic semantic() const noexcept { return _M_evaluation_semantic; } + detection_mode mode() const noexcept { return _M_detection_mode; } + const char* comment() const noexcept { return _M_comment; } + std::source_location location() const noexcept { + return std::source_location (_M_src_loc_ptr); + } + bool is_terminating () const noexcept { + return _M_evaluation_semantic == std::contracts::evaluation_semantic::enforce + || _M_evaluation_semantic == std::contracts::evaluation_semantic::quick_enforce; + } + }; + + void invoke_default_contract_violation_handler(const contract_violation&) noexcept; + +} // namespace contracts + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cpp_lib_contracts +#endif // _GLIBCXX_CONTRACTS diff --git a/libstdc++-v3/include/std/source_location b/libstdc++-v3/include/std/source_location index 16df9382fa5..32a07b3e174 100644 --- a/libstdc++-v3/include/std/source_location +++ b/libstdc++-v3/include/std/source_location @@ -38,6 +38,12 @@ namespace std { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#ifdef __cpp_lib_contracts + namespace contracts + { + class contract_violation; + } +#endif // __cpp_lib_contracts /// A class that describes a location in source code. struct source_location @@ -85,6 +91,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: const __impl* _M_impl = nullptr; + + constexpr source_location (const void *__t) + : _M_impl (static_cast <const __impl*>(__t)) {} + +#ifdef __cpp_lib_contracts + /* To enable use of the source __impl*. */ + friend class std::contracts::contract_violation; +#endif // __cpp_lib_contracts }; _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/src/experimental/Makefile.am b/libstdc++-v3/src/experimental/Makefile.am index 3ecb76e1cc1..b0ebcde5853 100644 --- a/libstdc++-v3/src/experimental/Makefile.am +++ b/libstdc++-v3/src/experimental/Makefile.am @@ -39,10 +39,16 @@ endif headers = sources = \ - contract.cc + contract26.cc # vpath % $(top_srcdir)/src/experimental + +contract26.lo: contract26.cc + $(LTCXXCOMPILE) -std=gnu++26 -fcontracts -c $< +contract26.o: contract26.cc + $(CXXCOMPILE) -std=gnu++26 -fcontracts -c $< + libstdc__exp_la_SOURCES = $(sources) libstdc__exp_la_LIBADD = \ diff --git a/libstdc++-v3/src/experimental/Makefile.in b/libstdc++-v3/src/experimental/Makefile.in index 8cb0acd4e68..a9248197f8c 100644 --- a/libstdc++-v3/src/experimental/Makefile.in +++ b/libstdc++-v3/src/experimental/Makefile.in @@ -152,7 +152,7 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" LTLIBRARIES = $(toolexeclib_LTLIBRARIES) @ENABLE_FILESYSTEM_TS_TRUE@am__DEPENDENCIES_1 = $(top_builddir)/src/filesystem/libstdc++fsconvenience.la @ENABLE_BACKTRACE_TRUE@am__DEPENDENCIES_2 = $(top_builddir)/src/libbacktrace/libstdc++_libbacktrace.la -am__objects_1 = contract.lo +am__objects_1 = contract26.lo am_libstdc__exp_la_OBJECTS = $(am__objects_1) libstdc__exp_la_OBJECTS = $(am_libstdc__exp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -458,10 +458,8 @@ toolexeclib_LTLIBRARIES = libstdc++exp.la @ENABLE_BACKTRACE_TRUE@backtrace_lib = $(top_builddir)/src/libbacktrace/libstdc++_libbacktrace.la headers = sources = \ - contract.cc + contract26.cc - -# vpath % $(top_srcdir)/src/experimental libstdc__exp_la_SOURCES = $(sources) libstdc__exp_la_LIBADD = \ $(top_builddir)/src/c++23/libc++23convenience.la \ @@ -480,7 +478,7 @@ libstdc__exp_la_DEPENDENCIES = \ # OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden # as the occasion calls for it. AM_CXXFLAGS = \ - -std=gnu++17 -nostdinc++ \ + -std=gnu++20 -nostdinc++ \ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ $(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \ $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) \ @@ -808,6 +806,13 @@ uninstall-am: uninstall-toolexeclibLTLIBRARIES .PRECIOUS: Makefile +# vpath % $(top_srcdir)/src/experimental + +contract26.lo: contract26.cc + $(LTCXXCOMPILE) -std=gnu++26 -fcontracts -c $< +contract26.o: contract26.cc + $(CXXCOMPILE) -std=gnu++26 -fcontracts -c $< + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libstdc++-v3/src/experimental/contract.cc b/libstdc++-v3/src/experimental/contract.cc deleted file mode 100644 index 06c19df6558..00000000000 --- a/libstdc++-v3/src/experimental/contract.cc +++ /dev/null @@ -1,78 +0,0 @@ -// -*- C++ -*- std::experimental::contract_violation and friends - -// Copyright (C) 2019-2025 Free Software Foundation, Inc. -// -// 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 <experimental/contract> -#if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE -# include <iostream> -#endif - -__attribute__ ((weak)) void -handle_contract_violation (const std::experimental::contract_violation &violation) -{ -#if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE - bool level_default_p = violation.assertion_level() == "default"; - bool role_default_p = violation.assertion_role() == "default"; - bool cont_mode_default_p = violation.continuation_mode() - == std::experimental::contract_violation_continuation_mode::never_continue; - - const char* modes[]{ "off", "on" }; // Must match enumerators in header. - std::cerr << "contract violation in function " << violation.function_name() - << " at " << violation.file_name() << ':' << violation.line_number() - << ": " << violation.comment(); - - const char* delimiter = "\n["; - - if (!level_default_p) - { - std::cerr << delimiter << "level:" << violation.assertion_level(); - delimiter = ", "; - } - if (!role_default_p) - { - std::cerr << delimiter << "role:" << violation.assertion_role(); - delimiter = ", "; - } - if (!cont_mode_default_p) - { - std::cerr << delimiter << "continue:" - << modes[(int)violation.continuation_mode() & 1]; - delimiter = ", "; - } - - if (delimiter[0] == ',') - std::cerr << ']'; - - std::cerr << std::endl; -#endif -} - -#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_violationRKNSt12experimental18contract_violationE -(const std::experimental::contract_violation &violation) -{ handle_contract_violation(violation); } -#endif diff --git a/libstdc++-v3/src/experimental/contract26.cc b/libstdc++-v3/src/experimental/contract26.cc new file mode 100644 index 00000000000..b96e40b66ef --- /dev/null +++ b/libstdc++-v3/src/experimental/contract26.cc @@ -0,0 +1,157 @@ +// -*- C++ -*- std::experimental::contract_violation and friends + +// Copyright (C) 2025 Free Software Foundation, Inc. +// +// 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> + +#ifdef __cpp_lib_contracts +#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 +#endif // __cpp_lib_contracts diff --git a/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh.cc b/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh.cc new file mode 100644 index 00000000000..373f6b77542 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh.cc @@ -0,0 +1,40 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-fcontracts -fcontract-evaluation-semantic=observe" } +// { dg-do run { target c++26 } } + +#include <contracts> +#include <testsuite_hooks.h> + +bool custom_called = false; + + +void handle_contract_violation(const std::contracts::contract_violation& v) +{ + invoke_default_contract_violation_handler(v); + custom_called = true; +} + +void f(int i) pre (i>10) {}; + +int main() +{ + f(0); + VERIFY(custom_called); +} +// { dg-output "contract violation in function void f.int. at .*(\n|\r\n|\r)" } diff --git a/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh2.cc b/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh2.cc new file mode 100644 index 00000000000..f2c7fb29fb3 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh2.cc @@ -0,0 +1,72 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// check that default contract violation is not invoked if not explicitly invoked +// { dg-options "-fcontracts -fcontract-evaluation-semantic=observe" } +// { dg-do run { target c++26 } } + +#include <contracts> +#include <testsuite_hooks.h> +#include <iostream> +#include <sstream> + + +struct checking_buf + : public std::streambuf +{ + bool written = false; + + checking_buf() = default; + + virtual int_type + overflow(int_type) + { + written = true; + return int_type(); + } + + std::streamsize xsputn(const char* s, std::streamsize count) + { + written = true; + return count; + } + +}; + + +bool custom_called = false; + + +void handle_contract_violation(const std::contracts::contract_violation& v) +{ + custom_called = true; +} + +void f(int i) pre (i>10) {}; + +int main() +{ + auto save_buf = std::cerr.rdbuf(); + checking_buf buf; + std::cerr.rdbuf(&buf); + + f(0); + std::cerr.rdbuf(save_buf); + VERIFY(!buf.written); + return 0; +} + -- 2.47.1
