[PATCH 6/9] libstdc++, contracts: Add base P2900R14 contracts support.
Jonathan Wakely
jwakely.gcc@gmail.com
Mon Nov 17 06:57:16 GMT 2025
On Mon, 17 Nov 2025, 00:14 Iain Sandoe, <iains.gcc@gmail.com> wrote:
> 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/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.
>
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').
The new test cases are run for c++2a and later, should that be c++26
instead?
> Co-Authored-by: Nina Ranns <dinka.ranns@gmail.com>
> Co-Authored-by: Ville Voutilainen <ville.voutilainen@gmail.com>
> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
> ---
> libstdc++-v3/include/Makefile.am | 2 +-
> libstdc++-v3/include/Makefile.in | 2 +-
> libstdc++-v3/include/experimental/contract | 83 ----------
> libstdc++-v3/include/std/contracts | 111 +++++++++++++
> libstdc++-v3/include/std/source_location | 10 ++
> libstdc++-v3/src/experimental/Makefile.am | 4 +-
> libstdc++-v3/src/experimental/Makefile.in | 6 +-
> libstdc++-v3/src/experimental/contract.cc | 78 ---------
> libstdc++-v3/src/experimental/contract26.cc | 154 ++++++++++++++++++
> .../contracts/invoke_default_cvh.cc | 40 +++++
> .../contracts/invoke_default_cvh2.cc | 72 ++++++++
> 11 files changed, 394 insertions(+), 168 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/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..b528cf3169e
> --- /dev/null
> +++ b/libstdc++-v3/include/std/contracts
> @@ -0,0 +1,111 @@
> +// Contracts support header for -*- C++ -*-
> +
> +// Copyright (C) 2019-2024 Free Software Foundation, Inc.
>
2025
+//
> +// 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
> +
> +#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 // _GLIBCXX_CONTRACTS
> diff --git a/libstdc++-v3/include/std/source_location
> b/libstdc++-v3/include/std/source_location
> index 16df9382fa5..eace9de006e 100644
> --- a/libstdc++-v3/include/std/source_location
> +++ b/libstdc++-v3/include/std/source_location
> @@ -38,6 +38,10 @@
> namespace std
> {
> _GLIBCXX_BEGIN_NAMESPACE_VERSION
> + namespace contracts
> + {
> + class contract_violation;
>
This is not a reserved word before C++26 so should only be declared for
C++26 and later.
+ }
>
> /// A class that describes a location in source code.
> struct source_location
> @@ -85,6 +89,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
> private:
> const __impl* _M_impl = nullptr;
> +
> + constexpr source_location (const void *__t)
> + : _M_impl (static_cast <const __impl*>(__t)) {}
> +
> + /* To enable use of the source __impl*. */
> + friend class std::contracts::contract_violation;
>
Likewise.
};
>
> _GLIBCXX_END_NAMESPACE_VERSION
> diff --git a/libstdc++-v3/src/experimental/Makefile.am
> b/libstdc++-v3/src/experimental/Makefile.am
> index 3ecb76e1cc1..ff4ed46998f 100644
> --- a/libstdc++-v3/src/experimental/Makefile.am
> +++ b/libstdc++-v3/src/experimental/Makefile.am
> @@ -39,7 +39,7 @@ endif
> headers =
>
> sources = \
> - contract.cc
> + contract26.cc
>
> # vpath % $(top_srcdir)/src/experimental
>
> @@ -61,7 +61,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) \
> diff --git a/libstdc++-v3/src/experimental/Makefile.in
> b/libstdc++-v3/src/experimental/Makefile.in
> index 8cb0acd4e68..ab5c2cc829a 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,7 +458,7 @@ 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
> @@ -480,7 +480,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) \
> 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..806cf01a234
> --- /dev/null
> +++ b/libstdc++-v3/src/experimental/contract26.cc
> @@ -0,0 +1,154 @@
> +// -*- C++ -*- std::experimental::contract_violation and friends
> +
> +// Copyright (C) 2019-2024 Free Software Foundation, Inc.
>
2025
+//
> +// 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>
> +#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
> 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..5f1f0e6f645
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh.cc
> @@ -0,0 +1,40 @@
> +// Copyright (C) 2020-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++2a } }
+
> +#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..9e5c289b71e
> --- /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++2a } }
> +
> +#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.39.5 (Apple Git-154)
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20251117/f41b1656/attachment-0001.htm>
More information about the Libstdc++
mailing list