From 5cd25f0725e01635bd3f8da6ae91d41670e18a1f Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Fri, 20 Nov 2009 00:03:21 -0500
Subject: [PATCH] re PR c++/42115 (r154072 & r154073 break build of ppl,
 non-placement deallocation issue)

	PR c++/42115
	* call.c (build_op_delete_call): Don't complain about using
	op delete (void *, size_t) for placement delete if there's an
	op delete (void *).

From-SVN: r154357
---
 gcc/cp/ChangeLog                       |  5 +++++
 gcc/cp/call.c                          | 12 ++++++++++++
 gcc/testsuite/ChangeLog                |  3 +++
 gcc/testsuite/g++.dg/init/placement5.C | 18 ++++++++++++++++--
 4 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c25d360eaf0c..042e637f8eac 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
 2009-11-19  Jason Merrill  <jason@redhat.com>
 
+	PR c++/42115
+	* call.c (build_op_delete_call): Don't complain about using
+	op delete (void *, size_t) for placement delete if there's an
+	op delete (void *).
+
 	DR 176 permissiveness
 	* class.c (build_self_reference): Call set_underlying_type.
 	* decl.c (check_elaborated_type_specifier): Don't complain about
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index ca6bd0b74621..3b3ccb66bad2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4622,8 +4622,20 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 	 allocation function, the program is ill-formed."  */
       if (non_placement_deallocation_fn_p (fn))
 	{
+	  /* But if the class has an operator delete (void *), then that is
+	     the usual deallocation function, so we shouldn't complain
+	     about using the operator delete (void *, size_t).  */
+	  for (t = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
+	       t; t = OVL_NEXT (t))
+	    {
+	      tree elt = OVL_CURRENT (t);
+	      if (non_placement_deallocation_fn_p (elt)
+		  && FUNCTION_ARG_CHAIN (elt) == void_list_node)
+		goto ok;
+	    }
 	  permerror (0, "non-placement deallocation function %q+D", fn);
 	  permerror (input_location, "selected for placement delete");
+	ok:;
 	}
     }
   else
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5a56a9c5fbb3..ecebcb136a36 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
 2009-11-19  Jason Merrill  <jason@redhat.com>
 
+	PR c++/42115
+	* g++.dg/init/placement5.C: Add positive test.
+
 	DR 176 permissiveness
 	* g++.dg/ext/injected-ttp.C: New.
 	* g++.old-deja/g++.pt/niklas01a.C: Adjust.
diff --git a/gcc/testsuite/g++.dg/init/placement5.C b/gcc/testsuite/g++.dg/init/placement5.C
index bb882396cf88..1d540daca432 100644
--- a/gcc/testsuite/g++.dg/init/placement5.C
+++ b/gcc/testsuite/g++.dg/init/placement5.C
@@ -3,16 +3,30 @@
 // placement deallocation function, would have been selected as a match for
 // the allocation function, the program is ill-formed.
 
+// But we should only complain about using op delete (void *, size_t) for
+// placement delete if it would also be selected for normal delete, not if
+// there's also an op delete (void *).
+
 typedef __SIZE_TYPE__ size_t;
 
 struct A
 {
   A();
-  static void* operator new (size_t, size_t);
-  static void operator delete (void *, size_t); // { dg-error "non-placement" }
+  void* operator new (size_t, size_t);
+  void operator delete (void *, size_t); // { dg-error "non-placement" }
+};
+
+struct B
+{
+  B();
+  void * operator new (size_t);
+  void * operator new (size_t, size_t);
+  void operator delete (void *);
+  void operator delete (void *, size_t);
 };
 
 int main()
 {
   A* ap = new (24) A;		// { dg-error "placement delete" }
+  B* bp = new (24) B;
 }
-- 
GitLab