diff options
author | Jason Merrill <jason@redhat.com> | 2020-07-12 17:31:24 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-07-20 18:18:12 -0400 |
commit | e443d8213864ac337c29092d4767224f280d2062 (patch) | |
tree | 1ae6feb7361f7274835f0e8051befab2a5a83f79 | |
parent | 812798917c59e95405a71b31ab37bd78c0f43f79 (diff) | |
download | gcc-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.c | 3 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/flifetime-dse7.C | 16 |
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>(); +} + |