This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 32251
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 5 Jul 2007 18:33:28 -0700
- Subject: C++ PATCH: PR 32251
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/32251, a GCC 4.2.x P1. The test case here
involves a variadic operator delete. We were assuming that all
operator delete functions have either one argument (and no variable
arguments) or at least two non-variadic arguments.
I also noticed that we were incorrectly handling code like this:
struct S {
void operator delete(void *, char *);
};
... new S ...
In particular, we were issuing an error about the call to new, because
there was no matching deallocation function. But, the standard says
that we must accept this code. (If operator new throws an exception,
there is no matching operator delete, so it is not called -- and the
user had better hope that they have some other way of deallocating the
memory.)
Tested on x86_64-unknown-linux-gnu. I will backport to 4.2.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
2007-07-05 Mark Mitchell <mark@codesourcery.com>
PR c++/32251
* init.c (build_new_1): Always pass the allocation function to
build_op_delete_call.
* call.c (build_op_delete_call): Handle operator delete with a
variable-argument list. Do not issue an error when no matching
deallocation function is available for a new operator.
2007-07-05 Mark Mitchell <mark@codesourcery.com>
PR c++/32251
* g++.dg/init/new21.C: Likewise.
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c (revision 126287)
+++ gcc/cp/call.c (working copy)
@@ -4062,8 +4062,12 @@ build_new_op (enum tree_code code, int f
GLOBAL_P is true if the delete-expression should not consider
class-specific delete operators.
PLACEMENT is the corresponding placement new call, or NULL_TREE.
- If PLACEMENT is non-NULL, then ALLOC_FN is the allocation function
- called to perform the placement new. */
+
+ If this call to "operator delete" is being generated as part to
+ deallocate memory allocated via a new-expression (as per [expr.new]
+ which requires that if the initialization throws an exception then
+ we call a deallocation function), then ALLOC_FN is the allocation
+ function. */
tree
build_op_delete_call (enum tree_code code, tree addr, tree size,
@@ -4151,9 +4155,13 @@ build_op_delete_call (enum tree_code cod
if (!a && !t)
break;
}
- /* On the second pass, the second argument must be
- "size_t". */
+ /* On the second pass, look for a function with exactly two
+ arguments: "void *" and "size_t". */
else if (pass == 1
+ /* For "operator delete(void *, ...)" there will be
+ no second argument, but we will not get an exact
+ match above. */
+ && t
&& same_type_p (TREE_VALUE (t), size_type_node)
&& TREE_CHAIN (t) == void_list_node)
break;
@@ -4201,10 +4209,18 @@ build_op_delete_call (enum tree_code cod
}
}
- /* If we are doing placement delete we do nothing if we don't find a
- matching op delete. */
- if (placement)
- return NULL_TREE;
+ /* [expr.new]
+
+ If no unambiguous matching deallocation function can be found,
+ propagating the exception does not cause the object's memory to
+ be freed. */
+ if (alloc_fn)
+ {
+ if (!placement)
+ warning (0, "no corresponding deallocation function for `%D'",
+ alloc_fn);
+ return NULL_TREE;
+ }
error ("no suitable %<operator %s%> for %qT",
operator_name_info[(int)code].name, type);
Index: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c (revision 126293)
+++ gcc/cp/init.c (working copy)
@@ -2038,8 +2038,7 @@ build_new_1 (tree placement, tree type,
globally_qualified_p,
(placement_allocation_fn_p
? alloc_call : NULL_TREE),
- (placement_allocation_fn_p
- ? alloc_fn : NULL_TREE));
+ alloc_fn);
if (!cleanup)
/* We're done. */;
Index: gcc/testsuite/g++.dg/init/new21.C
===================================================================
--- gcc/testsuite/g++.dg/init/new21.C (revision 0)
+++ gcc/testsuite/g++.dg/init/new21.C (revision 0)
@@ -0,0 +1,10 @@
+// PR c++/32251
+
+struct A {
+ A();
+ void operator delete(void *, ...);
+};
+
+void foo () {
+ new A; // { dg-warning "deallocation" }
+}