aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-07-12 17:31:24 -0400
committerJason Merrill <jason@redhat.com>2020-07-20 18:18:12 -0400
commite443d8213864ac337c29092d4767224f280d2062 (patch)
tree1ae6feb7361f7274835f0e8051befab2a5a83f79
parent812798917c59e95405a71b31ab37bd78c0f43f79 (diff)
downloadgcc-e443d8213864ac337c29092d4767224f280d2062.zip
gcc-e443d8213864ac337c29092d4767224f280d2062.tar.gz
gcc-e443d8213864ac337c29092d4767224f280d2062.tar.bz2
c++: Pseudo-destructor ends object lifetime.
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. gcc/cp/ChangeLog: * pt.c (type_dependent_expression_p): A pseudo-dtor can be dependent. * semantics.c (finish_call_expr): Use build_trivial_dtor_call for pseudo-destructor. (finish_pseudo_destructor_expr): Leave type NULL for dependent arg. gcc/testsuite/ChangeLog: * g++.dg/opt/flifetime-dse7.C: New test.
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/cp/semantics.c21
-rw-r--r--gcc/testsuite/g++.dg/opt/flifetime-dse7.C16
3 files changed, 31 insertions, 9 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cfe5dcd..f9e80e5 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 4a3ef3d..3096fe8 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 0000000..4fe1eb0
--- /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>();
+}
+