Commit ee392fc2 by Nathan Sidwell Committed by Nathan Sidwell

re PR c++/55635 (Deallocation function ("operator delete") not called when…

re PR c++/55635 (Deallocation function ("operator delete") not called when destructor throws exception)

	cp/
	PR c++/55635
	* init.c (build_vec_delete_1): Protect operator delete call in try
	finally.
	(build_delete): Likewise.
	* optimize.c (build_delete_destructor_body): Likewise.

	testsuite/
	PR c++/55635
	* g++.dg/eh/delete1.C: New.

From-SVN: r235297
parent dda49daf
2016-04-20 Nathan Sidwell <nathan@acm.org>
PR c++/55635
* init.c (build_vec_delete_1): Protect operator delete call in try
finally.
(build_delete): Likewise.
* optimize.c (build_delete_destructor_body): Likewise.
2016-04-20 Ilya Verbin <ilya.verbin@intel.com>
PR c++/69363
......
......@@ -3673,7 +3673,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
else if (!body)
body = deallocate_expr;
else
body = build_compound_expr (input_location, body, deallocate_expr);
/* The delete operator mist be called, even if a destructor
throws. */
body = build2 (TRY_FINALLY_EXPR, void_type_node, body, deallocate_expr);
if (!body)
body = integer_zero_node;
......@@ -4510,7 +4512,13 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
if (expr == error_mark_node)
return error_mark_node;
if (do_delete)
expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete);
/* The delete operator must be called, regardless of whether
the destructor throws.
[expr.delete]/7 The deallocation function is called
regardless of whether the destructor for the object or some
element of the array throws an exception. */
expr = build2 (TRY_FINALLY_EXPR, void_type_node, expr, do_delete);
/* We need to calculate this before the dtor changes the vptr. */
if (head)
......
......@@ -112,26 +112,24 @@ clone_body (tree clone, tree fn, void *arg_map)
static void
build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
{
tree call_dtor, call_delete;
tree parm = DECL_ARGUMENTS (delete_dtor);
tree virtual_size = cxx_sizeof (current_class_type);
/* Call the corresponding complete destructor. */
gcc_assert (complete_dtor);
call_dtor = build_cxx_call (complete_dtor, 1, &parm,
tf_warning_or_error);
add_stmt (call_dtor);
add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label));
tree call_dtor = build_cxx_call (complete_dtor, 1, &parm,
tf_warning_or_error);
/* Call the delete function. */
call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
virtual_size,
/*global_p=*/false,
/*placement=*/NULL_TREE,
/*alloc_fn=*/NULL_TREE,
tf_warning_or_error);
add_stmt (call_delete);
tree call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
virtual_size,
/*global_p=*/false,
/*placement=*/NULL_TREE,
/*alloc_fn=*/NULL_TREE,
tf_warning_or_error);
/* Operator delete must be called, whether or not the dtor throws. */
add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node, call_dtor, call_delete));
/* Return the address of the object. */
if (targetm.cxx.cdtor_returns_this ())
......
2016-04-20 Nathan Sidwell <nathan@acm.org>
PR c++/55635
* g++.dg/eh/delete1.C: New.
2016-04-20 H.J. Lu <hongjiu.lu@intel.com>
* gcc.target/i386/avx256-unaligned-store-2.c: Add
......
// { dg-do run }
// pr 55635, the delete operator must be called, regardless of whether
// the dtor throws
static int deleted;
void operator delete (void *) throw ()
{
deleted = 1;
}
struct Foo {
~Foo() throw(int) {throw 1;}
};
struct Baz {
void operator delete (void *) throw ()
{
deleted = 2;
}
virtual ~Baz() throw(int) {throw 1;}
};
int non_virt ()
{
deleted = 0;
Foo *p = new Foo;
try { delete p; }
catch (...) { return deleted != 1;}
return 1;
}
int virt_glob ()
{
deleted = 0;
Baz *p = ::new Baz;
try { ::delete p; }
catch (...) { return deleted != 1;}
return 1;
}
int virt_del ()
{
deleted = 0;
Baz *p = new Baz;
try { delete p; }
catch (...) { return deleted != 2;}
return 1;
}
int ary ()
{
deleted = 0;
Baz *p = new Baz[5];
try { delete[] p; }
catch (...) { return deleted != 1;}
return 1;
}
int main ()
{
if (non_virt ())
return 1;
if (virt_glob ())
return 2;
if (virt_del ())
return 3;
if (ary ())
return 4;
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment