From: Jason Merrill Date: Sun, 12 Jul 2020 21:31:24 +0000 (-0400) Subject: c++: Pseudo-destructor ends object lifetime. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e443d8213864ac337c29092d4767224f280d2062;p=gcc.git 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. --- 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 **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 +void f() +{ + T t = 42; + t.~T(); + if (t == 42) __builtin_abort(); +} + +int main() +{ + f(); +} +