mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
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.ranns@gmail.com>
This commit is contained in:
parent
a3d1469c7c
commit
40a990c8b5
@ -7194,6 +7194,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);
|
||||
|
@ -5172,6 +5172,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);
|
||||
|
||||
|
@ -42,6 +42,28 @@ static tree wrap_cleanups_r (tree *, int *, void *);
|
||||
static bool is_admissible_throw_operand_or_catch_parameter (tree, bool,
|
||||
tsubst_flags_t);
|
||||
|
||||
/* Initializes the node to std::terminate, which is used in exception
|
||||
handling and contract handling. */
|
||||
|
||||
void
|
||||
init_terminate_fn (void)
|
||||
{
|
||||
if (terminate_fn)
|
||||
return;
|
||||
|
||||
tree tmp;
|
||||
|
||||
push_nested_namespace (std_node);
|
||||
tmp = build_function_type_list (void_type_node, NULL_TREE);
|
||||
terminate_fn = build_cp_library_fn_ptr ("terminate", tmp,
|
||||
ECF_NOTHROW | ECF_NORETURN
|
||||
| ECF_COLD);
|
||||
gcc_checking_assert (TREE_THIS_VOLATILE (terminate_fn)
|
||||
&& 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. */
|
||||
|
||||
@ -51,14 +73,7 @@ init_exception_processing (void)
|
||||
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,
|
||||
ECF_NOTHROW | ECF_NORETURN
|
||||
| ECF_COLD);
|
||||
gcc_checking_assert (TREE_THIS_VOLATILE (terminate_fn)
|
||||
&& TREE_NOTHROW (terminate_fn));
|
||||
pop_nested_namespace (std_node);
|
||||
init_terminate_fn ();
|
||||
|
||||
/* void __cxa_call_unexpected(void *); */
|
||||
tmp = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
|
||||
|
27
gcc/testsuite/g++.dg/contracts/pr110159.C
Normal file
27
gcc/testsuite/g++.dg/contracts/pr110159.C
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user