aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-10-02 09:00:49 +0200
committerRichard Biener <rguenther@suse.de>2020-10-02 11:22:20 +0200
commit4f4ced28826ece7b7b76649522ee2a9601a63b90 (patch)
tree4fe85bc7a6d70681537bfe2d93b32fbd39ad5a8c
parent0b945f959f03a6185a3130f30bfd524d01d4142c (diff)
downloadgcc-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.c29
-rw-r--r--gcc/cp/init.c14
-rw-r--r--gcc/gimple.c4
-rw-r--r--gcc/gimple.h2
-rw-r--r--gcc/testsuite/g++.dg/pr94314.C2
-rw-r--r--gcc/tree-ssa-dce.c8
-rw-r--r--gcc/tree-ssa-structalias.c2
-rw-r--r--gcc/tree.h3
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
diff --git a/gcc/tree.h b/gcc/tree.h
index f27a739..c0a027a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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)