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.
This commit is contained in:
Jason Merrill 2020-07-12 17:31:24 -04:00
parent 812798917c
commit e443d82138
3 changed files with 31 additions and 9 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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>();
}