mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 15:11:08 +08:00
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.
This commit is contained in:
parent
0b945f959f
commit
4f4ced2882
@ -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]
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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"} } */
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user