From efe5143f896d224c7b0811d9ee42161ac7c4171c Mon Sep 17 00:00:00 2001
From: Martin Liska <mliska@suse.cz>
Date: Mon, 5 Aug 2019 14:53:01 +0200
Subject: [PATCH] Handle new operators with no arguments in DCE.

2019-08-05  Martin Liska  <mliska@suse.cz>

	PR c++/91334
	* tree-ssa-dce.c (propagate_necessity): Handle new operators
	with not arguments.
	(eliminate_unnecessary_stmts): Likewise.
2019-08-05  Martin Liska  <mliska@suse.cz>

	PR c++/91334
	* g++.dg/torture/pr91334.C: New test.

From-SVN: r274115
---
 gcc/ChangeLog                          |  7 +++++++
 gcc/testsuite/ChangeLog                |  5 +++++
 gcc/testsuite/g++.dg/torture/pr91334.C | 14 ++++++++++++++
 gcc/tree-ssa-dce.c                     | 22 ++++++++++++++++------
 4 files changed, 42 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/pr91334.C

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c118e4ddca98..892f7aa5ef1c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2019-08-05  Martin Liska  <mliska@suse.cz>
+
+	PR c++/91334
+	* tree-ssa-dce.c (propagate_necessity): Handle new operators
+	with not arguments.
+	(eliminate_unnecessary_stmts): Likewise.
+
 2019-08-05  Richard Biener  <rguenther@suse.de>
 
 	PR middle-end/91169
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5dc9d11140b9..cff940e0b288 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-08-05  Martin Liska  <mliska@suse.cz>
+
+	PR c++/91334
+	* g++.dg/torture/pr91334.C: New test.
+
 2019-08-05  Richard Biener  <rguenther@suse.de>
 
 	PR middle-end/91169
diff --git a/gcc/testsuite/g++.dg/torture/pr91334.C b/gcc/testsuite/g++.dg/torture/pr91334.C
new file mode 100644
index 000000000000..ba79d712b079
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr91334.C
@@ -0,0 +1,14 @@
+/* PR c++/91334.  */
+/* { dg-do compile } */
+
+#include <new>
+#include <stdlib.h>
+
+struct A {
+  A() { throw 0; }
+  void* operator new(size_t size, double = 0.0) { return ::operator new(size);}
+  void operator delete(void* p, double) { exit(0); }
+  void operator delete(void* p) { abort(); }
+};
+
+int main() { try { new A; } catch(...) {} }
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 80d5f5c30f7f..afb7bd9dedc6 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -810,6 +810,11 @@ propagate_necessity (bool aggressive)
 	  if (is_delete_operator
 	      || gimple_call_builtin_p (stmt, BUILT_IN_FREE))
 	    {
+	      /* It can happen that a user delete operator has the pointer
+		 argument optimized out already.  */
+	      if (gimple_call_num_args (stmt) == 0)
+		continue;
+
 	      tree ptr = gimple_call_arg (stmt, 0);
 	      gimple *def_stmt;
 	      tree def_callee;
@@ -1323,13 +1328,18 @@ eliminate_unnecessary_stmts (void)
 		  || (is_gimple_call (stmt)
 		      && gimple_call_operator_delete_p (as_a <gcall *> (stmt)))))
 	    {
-	      tree ptr = gimple_call_arg (stmt, 0);
-	      if (TREE_CODE (ptr) == SSA_NAME)
+	      /* It can happen that a user delete operator has the pointer
+		 argument optimized out already.  */
+	      if (gimple_call_num_args (stmt) > 0)
 		{
-		  gimple *def_stmt = SSA_NAME_DEF_STMT (ptr);
-		  if (!gimple_nop_p (def_stmt)
-		      && !gimple_plf (def_stmt, STMT_NECESSARY))
-		    gimple_set_plf (stmt, STMT_NECESSARY, false);
+		  tree ptr = gimple_call_arg (stmt, 0);
+		  if (TREE_CODE (ptr) == SSA_NAME)
+		    {
+		      gimple *def_stmt = SSA_NAME_DEF_STMT (ptr);
+		      if (!gimple_nop_p (def_stmt)
+			  && !gimple_plf (def_stmt, STMT_NECESSARY))
+			gimple_set_plf (stmt, STMT_NECESSARY, false);
+		    }
 		}
 	    }
 
-- 
GitLab