[PATCH 6/9 v4] libstdc++, contracts: Add base P2900R14 contracts support.
Jonathan Wakely
jwakely@redhat.com
Tue Jan 27 12:11:19 GMT 2026
On Tue, 27 Jan 2026 at 00:33 +0000, Iain Sandoe wrote:
>From: Nina Ranns <dinka.ranns@gmail.com>
>
>Changes since v3
>
> - rebased onto r16-7033-gfb6a2e3f1fa842 (includes reflection changes).
>
>Changes since v2
>
> - rebased onto r16-6757-g460edeb8bea11e (includes new year (c) change).
>
>Changes since v1
> - addressed Jonathan's review comments
> - fixed a merge error in the removal of C++2a code.
> - rebased onto r16-5785-g3b30d09ac7bbf8 (includes change to default to
> C++20).
>
>--- 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 <iain@sandoe.co.uk>
>Co-Authored-by: Ville Voutilainen <ville.voutilainen@gmail.com>
>Signed-off-by: Nina Ranns <dinka.ranns@gmail.com>
>---
> 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 dd1cc1ceb2f4..e6ac312ac7a4 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 1dfb40385f5d..b2e40c4d313f 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 8bb3e8d185f3..a1672b6be49f 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 107b19002d7a..dccc2a6c0df6 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 697045e0a2ba..000000000000
>--- 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
>-// <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 000000000000..3ca56481f1f9
>--- /dev/null
>+++ b/libstdc++-v3/include/std/contracts
>@@ -0,0 +1,116 @@
>+// Contracts support header for -*- C++ -*-
>+
>+// Copyright (C) 2025 Free Software Foundation, Inc.
As discussed in chat, this should be:
// 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/>.
>+
>+/** @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>
We usually try to avoid including <cstdint> and use __UINT16_TYPE__
instead, so that we don't pollute the global namespace with C
declarations.
But I'm starting to wonder if that's causing unnecessary pain, because
*nobody* ever remembers to include <cstdint> or <stdint.h>, and if
they do, they include the wrong one (i.e. include <cstdint> then don't
use std:: qualification).
>+#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 {
assertion_kind and the other public names in this file should be
exported from the 'std' modules, which is done by adding them to
src/c++23/std.cc.in -- and for that to work we need to include
<contracts> in include/precompiled/stdc++.h (at the bottom with other
C++26 headers).
>+ pre = 1,
>+ post = 2,
>+ assert = 3,
>+ // From D3290R3
>+ manual = 4,
>+ cassert = 5,
What's the status of this paper? It's not part of C++26 so do we want
to use '__manual' and '__cassert# for now, or put these enumerators
behind #ifndef __STRICT_ANSI__?
(We can't guard them with #if __cplusplus > 202400L because there's no
-std=c++29 yet, so they'd be unusable).
>+
>+ /* 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
Same question here.
>+ 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 ca09e980e172..3a631c31c1e3 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 e6d41cf66eb2..e428aef23c04 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 8cb0acd4e68b..a9248197f8c7 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 35ae7148234d..000000000000
>--- 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
>-// <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 000000000000..b96e40b66efb
>--- /dev/null
>+++ b/libstdc++-v3/src/experimental/contract26.cc
>@@ -0,0 +1,157 @@
>+// -*- C++ -*- std::experimental::contract_violation and friends
s/experimental/contracts/
>+
>+// Copyright (C) 2025 Free Software Foundation, Inc.
Same change as to the header.
>+//
>+// 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 000000000000..373f6b77542e
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/18_support/contracts/invoke_default_cvh.cc
>@@ -0,0 +1,40 @@
>+// Copyright (C) 2025 Free Software Foundation, Inc.
As per
https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.new_tests
we don't bother with copyright and licence notices in new libstdc++
tests, they're rarely interesting or legally significant.
>+//
>+// 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 000000000000..f2c7fb29fb3d
>--- /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.50.1 (Apple Git-155)
>
>
More information about the Libstdc++
mailing list