diff options
author | Jason Merrill <jason@redhat.com> | 2020-10-02 09:00:49 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2020-10-02 11:22:20 +0200 |
commit | 4f4ced28826ece7b7b76649522ee2a9601a63b90 (patch) | |
tree | 4fe85bc7a6d70681537bfe2d93b32fbd39ad5a8c | |
parent | 0b945f959f03a6185a3130f30bfd524d01d4142c (diff) | |
download | gcc-4f4ced28826ece7b7b76649522ee2a9601a63b90.zip gcc-4f4ced28826ece7b7b76649522ee2a9601a63b90.tar.gz gcc-4f4ced28826ece7b7b76649522ee2a9601a63b90.tar.bz2 |
c++: Set CALL_FROM_NEW_OR_DELETE_P on more calls.
We were failing to set the flag on a delete call in a new expression, in a
deleting destructor, and in a coroutine. Fixed by setting it in the
function that builds the call.
2020-10-02 Jason Merril <jason@redhat.com>
gcc/cp/ChangeLog:
* call.c (build_operator_new_call): Set CALL_FROM_NEW_OR_DELETE_P.
(build_op_delete_call): Likewise.
* init.c (build_new_1, build_vec_delete_1, build_delete): Not here.
(build_delete):
gcc/ChangeLog:
* gimple.h (gimple_call_operator_delete_p): Rename from
gimple_call_replaceable_operator_delete_p.
* gimple.c (gimple_call_operator_delete_p): Likewise.
* tree.h (DECL_IS_REPLACEABLE_OPERATOR_DELETE_P): Remove.
* tree-ssa-dce.c (mark_all_reaching_defs_necessary_1): Adjust.
(propagate_necessity): Likewise.
(eliminate_unnecessary_stmts): Likewise.
* tree-ssa-structalias.c (find_func_aliases_for_call): Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/pr94314.C: new/delete no longer omitted.
-rw-r--r-- | gcc/cp/call.c | 29 | ||||
-rw-r--r-- | gcc/cp/init.c | 14 | ||||
-rw-r--r-- | gcc/gimple.c | 4 | ||||
-rw-r--r-- | gcc/gimple.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr94314.C | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-dce.c | 8 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 2 | ||||
-rw-r--r-- | gcc/tree.h | 3 |
8 files changed, 33 insertions, 31 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d67e8fe..bd66251 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4769,7 +4769,16 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args, *fn = cand->fn; /* Build the CALL_EXPR. */ - return build_over_call (cand, LOOKUP_NORMAL, complain); + tree ret = build_over_call (cand, LOOKUP_NORMAL, complain); + + /* Set this flag for all callers of this function. In addition to + new-expressions, this is called for allocating coroutine state; treat + that as an implicit new-expression. */ + tree call = extract_call_expr (ret); + if (TREE_CODE (call) == CALL_EXPR) + CALL_FROM_NEW_OR_DELETE_P (call) = 1; + + return ret; } /* Build a new call to operator(). This may change ARGS. */ @@ -6146,7 +6155,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, case VEC_NEW_EXPR: case VEC_DELETE_EXPR: case DELETE_EXPR: - /* Use build_op_new_call and build_op_delete_call instead. */ + /* Use build_operator_new_call and build_op_delete_call instead. */ gcc_unreachable (); case CALL_EXPR: @@ -6983,6 +6992,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, if (DECL_DELETED_FN (fn) && alloc_fn) return NULL_TREE; + tree ret; if (placement) { /* The placement args might not be suitable for overload @@ -6995,7 +7005,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, argarray[i] = CALL_EXPR_ARG (placement, i); if (!mark_used (fn, complain) && !(complain & tf_error)) return error_mark_node; - return build_cxx_call (fn, nargs, argarray, complain); + ret = build_cxx_call (fn, nargs, argarray, complain); } else { @@ -7013,7 +7023,6 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, complain); } - tree ret; releasing_vec args; args->quick_push (addr); if (destroying) @@ -7026,8 +7035,18 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, args->quick_push (al); } ret = cp_build_function_call_vec (fn, &args, complain); - return ret; } + + /* Set this flag for all callers of this function. In addition to + delete-expressions, this is called for deallocating coroutine state; + treat that as an implicit delete-expression. This is also called for + the delete if the constructor throws in a new-expression, and for a + deleting destructor (which implements a delete-expression). */ + tree call = extract_call_expr (ret); + if (TREE_CODE (call) == CALL_EXPR) + CALL_FROM_NEW_OR_DELETE_P (call) = 1; + + return ret; } /* [expr.new] diff --git a/gcc/cp/init.c b/gcc/cp/init.c index e84e985..00fff3f 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3433,10 +3433,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, } } - tree alloc_call_expr = extract_call_expr (alloc_call); - if (TREE_CODE (alloc_call_expr) == CALL_EXPR) - CALL_FROM_NEW_OR_DELETE_P (alloc_call_expr) = 1; - if (cookie_size) alloc_call = maybe_wrap_new_for_constexpr (alloc_call, elt_type, cookie_size); @@ -4145,10 +4141,6 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type, /*placement=*/NULL_TREE, /*alloc_fn=*/NULL_TREE, complain); - - tree deallocate_call_expr = extract_call_expr (deallocate_expr); - if (TREE_CODE (deallocate_call_expr) == CALL_EXPR) - CALL_FROM_NEW_OR_DELETE_P (deallocate_call_expr) = 1; } body = loop; @@ -5073,12 +5065,6 @@ build_delete (location_t loc, tree otype, tree addr, if (do_delete == error_mark_node) return error_mark_node; - else if (do_delete) - { - tree do_delete_call_expr = extract_call_expr (do_delete); - if (TREE_CODE (do_delete_call_expr) == CALL_EXPR) - CALL_FROM_NEW_OR_DELETE_P (do_delete_call_expr) = 1; - } if (do_delete && !TREE_SIDE_EFFECTS (expr)) expr = do_delete; diff --git a/gcc/gimple.c b/gcc/gimple.c index f07ddab..523d845 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -2717,12 +2717,12 @@ gimple_builtin_call_types_compatible_p (const gimple *stmt, tree fndecl) /* Return true when STMT is operator a replaceable delete call. */ bool -gimple_call_replaceable_operator_delete_p (const gcall *stmt) +gimple_call_operator_delete_p (const gcall *stmt) { tree fndecl; if ((fndecl = gimple_call_fndecl (stmt)) != NULL_TREE) - return DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (fndecl); + return DECL_IS_OPERATOR_DELETE_P (fndecl); return false; } diff --git a/gcc/gimple.h b/gcc/gimple.h index 108ae84..3c9b996 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1605,7 +1605,7 @@ extern alias_set_type gimple_get_alias_set (tree); extern bool gimple_ior_addresses_taken (bitmap, gimple *); extern bool gimple_builtin_call_types_compatible_p (const gimple *, tree); extern combined_fn gimple_call_combined_fn (const gimple *); -extern bool gimple_call_replaceable_operator_delete_p (const gcall *); +extern bool gimple_call_operator_delete_p (const gcall *); extern bool gimple_call_builtin_p (const gimple *); extern bool gimple_call_builtin_p (const gimple *, enum built_in_class); extern bool gimple_call_builtin_p (const gimple *, enum built_in_function); diff --git a/gcc/testsuite/g++.dg/pr94314.C b/gcc/testsuite/g++.dg/pr94314.C index 4e5ae12..7246712 100644 --- a/gcc/testsuite/g++.dg/pr94314.C +++ b/gcc/testsuite/g++.dg/pr94314.C @@ -78,5 +78,5 @@ int main(){ return 0; } -/* { dg-final { scan-tree-dump-times "Deleting : operator delete" 1 "cddce1"} } */ +/* { dg-final { scan-tree-dump-not "Deleting : operator delete" "cddce1"} } */ /* { dg-final { scan-tree-dump-not "Deleting : B::operator delete" "cddce1"} } */ diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index c9e0c8f..a046612 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -612,7 +612,7 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED, if (callee != NULL_TREE && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee) - || DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (callee)) + || DECL_IS_OPERATOR_DELETE_P (callee)) && gimple_call_from_new_or_delete (call)) return false; } @@ -877,7 +877,7 @@ propagate_necessity (bool aggressive) bool is_delete_operator = (is_gimple_call (stmt) && gimple_call_from_new_or_delete (as_a <gcall *> (stmt)) - && gimple_call_replaceable_operator_delete_p (as_a <gcall *> (stmt))); + && gimple_call_operator_delete_p (as_a <gcall *> (stmt))); if (is_delete_operator || gimple_call_builtin_p (stmt, BUILT_IN_FREE)) { @@ -975,7 +975,7 @@ propagate_necessity (bool aggressive) if (callee != NULL_TREE && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee) - || DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (callee)) + || DECL_IS_OPERATOR_DELETE_P (callee)) && gimple_call_from_new_or_delete (call)) continue; @@ -1402,7 +1402,7 @@ eliminate_unnecessary_stmts (void) && (gimple_call_builtin_p (stmt, BUILT_IN_FREE) || (is_gimple_call (stmt) && gimple_call_from_new_or_delete (as_a <gcall *> (stmt)) - && gimple_call_replaceable_operator_delete_p (as_a <gcall *> (stmt))))) + && gimple_call_operator_delete_p (as_a <gcall *> (stmt))))) { tree ptr = gimple_call_arg (stmt, 0); if (TREE_CODE (ptr) == SSA_NAME) diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 69de932..30a8c93 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -4862,7 +4862,7 @@ find_func_aliases_for_call (struct function *fn, gcall *t) such operator, then the effects for PTA (in particular the escaping of the pointer) can be ignored. */ else if (fndecl - && DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (fndecl) + && DECL_IS_OPERATOR_DELETE_P (fndecl) && gimple_call_from_new_or_delete (t)) ; else @@ -3074,9 +3074,6 @@ set_function_decl_type (tree decl, function_decl_type t, bool set) #define DECL_IS_OPERATOR_DELETE_P(NODE) \ (FUNCTION_DECL_CHECK (NODE)->function_decl.decl_type == OPERATOR_DELETE) -#define DECL_IS_REPLACEABLE_OPERATOR_DELETE_P(NODE) \ - (DECL_IS_OPERATOR_DELETE_P (NODE) && DECL_IS_REPLACEABLE_OPERATOR (NODE)) - #define DECL_SET_IS_OPERATOR_DELETE(NODE, VAL) \ set_function_decl_type (FUNCTION_DECL_CHECK (NODE), OPERATOR_DELETE, VAL) |