It would help if I attached the patch

Apologies,
Nina

On Tue, 16 Jul 2024 at 10:03, Nina Dinka Ranns <dinka.ra...@googlemail.com>
wrote:

> Hello,
>
> We currently only initialise terminate_fn if exceptions are enabled.
> However, contract handling requires terminate_fn when building the
> contract as a contract failure may result in std::terminate call
> regardless of whether the exceptions are enabled. Added possible
> initialisation of terminate_fn if contracts are enabled. Minor refactoring
> of the init_exception_processing to reuse the terminate_fn initialisation.
>
> Tested on x86_64-pc-linux-gnu.
>
> Patch attached to the email in hope of it being a workable solution for my
> email client.
>
> "OK for trunk?" :)
>
> Best,
> Nina
>
From 336d723a384f4413610e2e95b0588e7fbb235e5a Mon Sep 17 00:00:00 2001
From: Nina Ranns <dinka.ra...@gmail.com>
Date: Thu, 11 Jul 2024 17:47:34 +0100
Subject: [PATCH] c++/contracts: ICE in C++ Contracts with '-fno-exceptions'
 [PR 110159]

We currently only initialise terminate_fn if exceptions are enabled.
However, contract handling requires terminate_fn when building the
contract because a contract failure may result in std::terminate call
regardless of whether the exceptions are enabled. Refactored
init_exception_processing to extract the initialisation of
terminate_fn. New function init_terminate_fn added that initialises
terminate_fn if it hasn't already been initialised. Call to terminate_fn
added in cxx_init_decl_processing if contracts are enabled.

	PR c++/110159

gcc/cp/ChangeLog:

	* cp-tree.h (init_terminate_fn): Declaration of a new function.
	* decl.cc (cxx_init_decl_processing): If contracts are enabled,
	call init_terminate_fn.
	* except.cc (init_exception_processing): Function refactored to
	call init_terminate_fn.
	(init_terminate_fn): Added new function that initializes
	terminate_fn if	it hasn't already been initialised.

gcc/testsuite/ChangeLog:

	* g++.dg/contracts/pr110159.C: New test.

Signed-off-by: Nina Ranns <dinka.ra...@gmail.com>
---
 gcc/cp/cp-tree.h                          |  1 +
 gcc/cp/decl.cc                            |  3 +++
 gcc/cp/except.cc                          | 23 +++++++++++++++----
 gcc/testsuite/g++.dg/contracts/pr110159.C | 27 +++++++++++++++++++++++
 4 files changed, 50 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/contracts/pr110159.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f270b0b1077..7f9791a64d0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7202,6 +7202,7 @@ extern void qualified_name_lookup_error		(tree, tree, tree,
 						 location_t);
 
 /* in except.cc */
+extern void init_terminate_fn		(void);
 extern void init_exception_processing		(void);
 extern tree expand_start_catch_block		(tree);
 extern void expand_end_catch_block		(void);
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index edf4c155bf7..7ff873e229e 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -5167,6 +5167,9 @@ cxx_init_decl_processing (void)
   if (flag_exceptions)
     init_exception_processing ();
 
+  if (flag_contracts)
+    init_terminate_fn();
+
   if (modules_p ())
     init_modules (parse_in);
 
diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
index 1eb3ba53b4b..87f06bd1663 100644
--- a/gcc/cp/except.cc
+++ b/gcc/cp/except.cc
@@ -42,15 +42,17 @@ static tree wrap_cleanups_r (tree *, int *, void *);
 static bool is_admissible_throw_operand_or_catch_parameter (tree, bool,
 							    tsubst_flags_t);
 
-/* Sets up all the global eh stuff that needs to be initialized at the
-   start of compilation.  */
+/* Initializes the node to std::terminate, which is used in exception
+  handling and contract handling. */
 
 void
-init_exception_processing (void)
+init_terminate_fn (void)
 {
+  if (terminate_fn)
+    return;
+
   tree tmp;
 
-  /* void std::terminate (); */
   push_nested_namespace (std_node);
   tmp = build_function_type_list (void_type_node, NULL_TREE);
   terminate_fn = build_cp_library_fn_ptr ("terminate", tmp,
@@ -60,6 +62,19 @@ init_exception_processing (void)
 		       && TREE_NOTHROW (terminate_fn));
   pop_nested_namespace (std_node);
 
+}
+
+/* Sets up all the global eh stuff that needs to be initialized at the
+   start of compilation.  */
+
+void
+init_exception_processing (void)
+{
+  tree tmp;
+
+  /* void std::terminate (); */
+  init_terminate_fn();
+
   /* void __cxa_call_unexpected(void *); */
   tmp = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
   call_unexpected_fn
diff --git a/gcc/testsuite/g++.dg/contracts/pr110159.C b/gcc/testsuite/g++.dg/contracts/pr110159.C
new file mode 100644
index 00000000000..614b466b1a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/contracts/pr110159.C
@@ -0,0 +1,27 @@
+// check that contracts can be handled even when exceptions are disabled
+// { dg-do run }
+// { dg-options "-std=c++2a -fcontracts -fno-exceptions " }
+// { dg-output "contract violation in function f at .* a<5" }
+
+#include <exception>
+#include <cstdlib>
+
+int terminate_called = 0;
+void my_term()
+{
+    std::exit(0);
+}
+
+
+void f(int a)
+  [[ pre : a<5 ]]
+  {
+  }
+
+int
+main ()
+{
+  std::set_terminate (my_term);
+  f(3);
+  f(10);
+}
-- 
2.45.2

Reply via email to