[pushend] c++: Pseudo-destructor ends object lifetime.

Message ID 20200720221746.11990-1-jason@redhat.com
State New
Headers show
Series
  • [pushend] c++: Pseudo-destructor ends object lifetime.
Related show

Commit Message

David Malcolm via Gcc-patches July 20, 2020, 10:17 p.m.
P0593R6 is mostly about a new object model whereby malloc and the like are
treated as implicitly starting the lifetime of whatever trivial types are
necessary to give the program well-defined semantics; that seems only
relevant to TBAA, and is not implemented here.

The paper also specifies that a pseudo-destructor call (a destructor call
for a non-class type) ends the lifetime of the object like a destructor call
for an object of class type, even though it doesn't call a destructor; this
patch implements that change.

The paper was voted as a DR, so I'm applying this change to all standard
levels.  Like class end-of-life clobbers, it is controlled by
 -flifetime-dse.

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/ChangeLog:

	* semantics.c (finish_call_expr): Use build_trivial_dtor_call for
	pseudo-destructor.

gcc/testsuite/ChangeLog:

	* g++.dg/opt/flifetime-dse7.C: New test.
---
 gcc/cp/pt.c                               |  3 +--
 gcc/cp/semantics.c                        | 21 ++++++++++++++-------
 gcc/testsuite/g++.dg/opt/flifetime-dse7.C | 16 ++++++++++++++++
 3 files changed, 31 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/opt/flifetime-dse7.C


base-commit: 812798917c59e95405a71b31ab37bd78c0f43f79
-- 
2.18.1

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cfe5dcd59cf..f9e80e5a1c3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -26729,8 +26729,7 @@  type_dependent_expression_p (tree expression)
     return true;
 
   /* Some expression forms are never type-dependent.  */
-  if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
-      || TREE_CODE (expression) == SIZEOF_EXPR
+  if (TREE_CODE (expression) == SIZEOF_EXPR
       || TREE_CODE (expression) == ALIGNOF_EXPR
       || TREE_CODE (expression) == AT_ENCODE_EXPR
       || TREE_CODE (expression) == NOEXCEPT_EXPR
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 4a3ef3d2839..3096fe83433 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2707,12 +2707,16 @@  finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
     {
       if (!vec_safe_is_empty (*args))
 	error ("arguments to destructor are not allowed");
-      /* Mark the pseudo-destructor call as having side-effects so
-	 that we do not issue warnings about its use.  */
-      result = build1 (NOP_EXPR,
-		       void_type_node,
-		       TREE_OPERAND (fn, 0));
-      TREE_SIDE_EFFECTS (result) = 1;
+      /* C++20/DR: If the postfix-expression names a pseudo-destructor (in
+	 which case the postfix-expression is a possibly-parenthesized class
+	 member access), the function call destroys the object of scalar type
+	 denoted by the object expression of the class member access.  */
+      tree ob = TREE_OPERAND (fn, 0);
+      if (obvalue_p (ob))
+	result = build_trivial_dtor_call (ob);
+      else
+	/* No location to clobber.  */
+	result = convert_to_void (ob, ICV_STATEMENT, complain);
     }
   else if (CLASS_TYPE_P (TREE_TYPE (fn)))
     /* If the "function" is really an object of class type, it might
@@ -2845,7 +2849,10 @@  finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
 	}
     }
 
-  return build3_loc (loc, PSEUDO_DTOR_EXPR, void_type_node, object,
+  tree type = (type_dependent_expression_p (object)
+	       ? NULL_TREE : void_type_node);
+
+  return build3_loc (loc, PSEUDO_DTOR_EXPR, type, object,
 		     scope, destructor);
 }
 
diff --git a/gcc/testsuite/g++.dg/opt/flifetime-dse7.C b/gcc/testsuite/g++.dg/opt/flifetime-dse7.C
new file mode 100644
index 00000000000..4fe1eb062f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/flifetime-dse7.C
@@ -0,0 +1,16 @@ 
+// { dg-options "-O3 -flifetime-dse" }
+// { dg-do run }
+
+template <class T>
+void f()
+{
+  T t = 42;
+  t.~T();
+  if (t == 42) __builtin_abort();
+}
+
+int main()
+{
+  f<int>();
+}
+