From: Nina Ranns Date: Sun, 19 Oct 2025 14:55:52 +0000 (+0100) Subject: libstdc++, contracts: Add base P2900R14 contracts support. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fbde291af66e026e0fe7031aa6d5abd4a90dc82b;p=thirdparty%2Fgcc.git libstdc++, contracts: Add base P2900R14 contracts support. 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/precompiled/stdc++.h: Add contracts header. * include/std/source_location: Befriend the contract_violation class so that we can initialise a source_location from an existing __impl *. * src/c++23/std.cc.in: Add contracts support. * 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 Co-Authored-by: Ville Voutilainen Signed-off-by: Nina Ranns --- diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index dd1cc1ceb2f..e6ac312ac7a 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 \ @@ -801,7 +802,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 1dfb40385f5..b2e40c4d313 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 \ @@ -1150,7 +1151,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 8bb3e8d185f..a1672b6be49 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -2272,6 +2272,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 107b19002d7..dccc2a6c0df 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2546,4 +2546,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 697045e0a2b..00000000000 --- a/libstdc++-v3/include/experimental/contract +++ /dev/null @@ -1,83 +0,0 @@ -// Contracts support header for -*- C++ -*- - -// Copyright (C) 2019-2026 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 -// . - -/** @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 -#include - -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(_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/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h index 433082facac..91f54edb15b 100644 --- a/libstdc++-v3/include/precompiled/stdc++.h +++ b/libstdc++-v3/include/precompiled/stdc++.h @@ -232,6 +232,7 @@ #endif #if __cplusplus > 202302L +#include #include #include #include diff --git a/libstdc++-v3/include/std/contracts b/libstdc++-v3/include/std/contracts new file mode 100644 index 00000000000..2cf67ac1dd8 --- /dev/null +++ b/libstdc++-v3/include/std/contracts @@ -0,0 +1,111 @@ +// Contracts support header for -*- C++ -*- + +// 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 +// . + +/** @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 + +#ifdef __cpp_lib_contracts +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace contracts +{ + // From P2900R14 + + enum class assertion_kind : __UINT16_TYPE__ { + pre = 1, + post = 2, + assert = 3, + + /* Implementation−defined values should have a minimum value of 1000. */ + }; + + enum class evaluation_semantic : __UINT16_TYPE__ { + ignore = 1, + observe = 2, + enforce = 3, + quick_enforce = 4, + + /* Implementation−defined values should have a minimum value of 1000. */ + }; + + enum class detection_mode : __UINT16_TYPE__ { + predicate_false = 1, + evaluation_exception = 2, + + /* Implementation−defined values should have a minimum value of 1000. */ + }; + + using __vendor_ext = void; + + class contract_violation { + __UINT16_TYPE__ _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 ca09e980e17..3a631c31c1e 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 (__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/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index e134e395bb6..f38660498cc 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -1017,6 +1017,18 @@ export namespace std } #endif +// 17.10.1 +#if __cpp_lib_contracts +export namespace std::contracts +{ + using std::contracts::assertion_kind; + using std::contracts::evaluation_semantic; + using std::contracts::detection_mode; + using std::contracts::contract_violation; + using std::contracts::invoke_default_violation_handler; +} +#endif // __cpp_lib_contracts + // 17.12.2 #if __cpp_lib_coroutine export namespace std diff --git a/libstdc++-v3/src/experimental/Makefile.am b/libstdc++-v3/src/experimental/Makefile.am index e6d41cf66eb..e428aef23c0 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 35ae7148234..00000000000 --- a/libstdc++-v3/src/experimental/contract.cc +++ /dev/null @@ -1,78 +0,0 @@ -// -*- C++ -*- std::experimental::contract_violation and friends - -// Copyright (C) 2019-2026 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 -// . - -#include -#if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE -# include -#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..d32a2ca13e2 --- /dev/null +++ b/libstdc++-v3/src/experimental/contract26.cc @@ -0,0 +1,157 @@ +// -*- 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 +// . + +#include + +#ifdef __cpp_lib_contracts +#if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE +# include +# include +#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..9b40ca170b1 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh.cc @@ -0,0 +1,23 @@ +// { dg-options "-fcontracts -fcontract-evaluation-semantic=observe" } +// { dg-do run { target c++26 } } + +#include +#include + +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..72a8e2fc330 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh2.cc @@ -0,0 +1,55 @@ +// 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 +#include +#include +#include + + +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; +} +