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.
Co-Authored-by: Nina Ranns <[email protected]>
Co-Authored-by: Ville Voutilainen <[email protected]>
Signed-off-by: Iain Sandoe <[email protected]>
---
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.
+//
+// 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;
+ }
/// 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;
};
_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.
+//
+// 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)