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