[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