c++: Set CALL_FROM_NEW_OR_DELETE_P on more calls.
authorJason Merrill <jason@redhat.com>
Fri, 2 Oct 2020 07:00:49 +0000 (09:00 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 2 Oct 2020 09:22:20 +0000 (11:22 +0200)
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.

gcc/cp/call.c
gcc/cp/init.c
gcc/gimple.c
gcc/gimple.h
gcc/testsuite/g++.dg/pr94314.C
gcc/tree-ssa-dce.c
gcc/tree-ssa-structalias.c
gcc/tree.h

index d67e8fe2b2867f1eb6dfae0c33d09e8604a9117b..bd662518958321ff5c0cbb99cf671418fc0befc5 100644 (file)
@@ -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]
index e84e985492dfaddcc6a28665080af75f1f746733..00fff3f732750ca38345013d1a8a2882213d2f29 100644 (file)
@@ -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;
index f07ddab79531a8747f056798af2fe811cf278f19..523d845de892fc09160e2b90ea64e552a468cd8a 100644 (file)
@@ -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;
 }
 
index 108ae84684929adf4ff8c33fc7a11af838668330..3c9b9965f5a11093d6113f4950a1375dd7d591eb 100644 (file)
@@ -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);
index 4e5ae122e9fe1b870359b9021a5450532c11f0c1..72467127feaae9a6be0de7044cd73d77b42d068b 100644 (file)
@@ -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"} } */
index c9e0c8fd116602045f5bfa14fa0323de97f9ba1b..a0466127f9c8fce2b243d64357be1bb69564eac8 100644 (file)
@@ -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)
index 69de932b14cbafe933ee73e6ceb0b21647b7d584..30a8c93b4ff82e519e7feed4fb2b246575ca03c7 100644 (file)
@@ -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
index f27a7399a37dccb0f973f230d7e1caa7f777e8a4..c0a027a650d591291fccfa7e1eb468abf93e3af5 100644 (file)
@@ -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)