PR c++/90171 - reorganize usual_deallocation_fn_p
authorJason Merrill <jason@redhat.com>
Tue, 7 May 2019 22:37:24 +0000 (18:37 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 7 May 2019 22:37:24 +0000 (18:37 -0400)
When fixing 90171 it struck me as undesirable to have so many separate
functions that all needed to know about the definition of a usual
deallocation function.  So this patch condenses them into one.  I left
destroying_delete_p because it is used by other files as well.

* call.c (struct dealloc_info): New.
(usual_deallocation_fn_p): Take a dealloc_info*.
(aligned_deallocation_fn_p, sized_deallocation_fn_p): Remove.
(build_op_delete_call): Adjust.

From-SVN: r270986

gcc/cp/ChangeLog
gcc/cp/call.c

index d90cc099767d3708701f0d4263c57d4cf637472a..dade3e0c8b945b18d6faaae01c4ac5fa4fb5e8f0 100644 (file)
@@ -1,3 +1,11 @@
+2019-05-06  Jason Merrill  <jason@redhat.com>
+
+       PR c++/90171 - reorganize usual_deallocation_fn_p
+       * call.c (struct dealloc_info): New.
+       (usual_deallocation_fn_p): Take a dealloc_info*.
+       (aligned_deallocation_fn_p, sized_deallocation_fn_p): Remove.
+       (build_op_delete_call): Adjust.
+
 2019-05-07  Jason Merrill  <jason@redhat.com>
 
        PR c++/86485 - -Wmaybe-unused with empty class ?:
index 1a79017eff460f36d9c5884d79e0ca7c2e844f45..20db2974b56bbc21b819bbba305f9fabb8304c66 100644 (file)
@@ -6348,63 +6348,22 @@ destroying_delete_p (tree t)
   return std_destroying_delete_t_p (type) ? type : NULL_TREE;
 }
 
-/* Returns true iff T, an element of an OVERLOAD chain, is a usual deallocation
-   function (3.7.4.2 [basic.stc.dynamic.deallocation]) with a parameter of
-   std::align_val_t.  */
-
-static bool
-aligned_deallocation_fn_p (tree t)
+struct dealloc_info
 {
-  if (!aligned_new_threshold)
-    return false;
-
-  /* A template instance is never a usual deallocation function,
-     regardless of its signature.  */
-  if (TREE_CODE (t) == TEMPLATE_DECL
-      || primary_template_specialization_p (t))
-    return false;
-
-  tree a = FUNCTION_ARG_CHAIN (t);
-  if (destroying_delete_p (t))
-    a = TREE_CHAIN (a);
-  if (same_type_p (TREE_VALUE (a), align_type_node)
-      && TREE_CHAIN (a) == void_list_node)
-    return true;
-  if (!same_type_p (TREE_VALUE (a), size_type_node))
-    return false;
-  a = TREE_CHAIN (a);
-  if (a && same_type_p (TREE_VALUE (a), align_type_node)
-      && TREE_CHAIN (a) == void_list_node)
-    return true;
-  return false;
-}
+  bool sized;
+  bool aligned;
+  tree destroying;
+};
 
-/* Returns true if FN is a usual deallocation fn with a size_t parameter.  */
+/* Returns true iff T, an element of an OVERLOAD chain, is a usual deallocation
+   function (3.7.4.2 [basic.stc.dynamic.deallocation]).  If so, and DI is
+   non-null, also set *DI. */
 
 static bool
-sized_deallocation_fn_p (tree fn)
+usual_deallocation_fn_p (tree t, dealloc_info *di)
 {
-  tree t = FUNCTION_ARG_CHAIN (fn);
-  if (destroying_delete_p (fn))
-    t = TREE_CHAIN (t);
-  if (!t || !same_type_p (TREE_VALUE (t), size_type_node))
-    return false;
-  t = TREE_CHAIN (t);
-  if (t == void_list_node)
-    return true;
-  if (aligned_new_threshold && t
-      && same_type_p (TREE_VALUE (t), align_type_node)
-      && TREE_CHAIN (t) == void_list_node)
-    return true;
-  return false;
-}
+  if (di) *di = dealloc_info();
 
-/* Returns true iff T, an element of an OVERLOAD chain, is a usual
-   deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]).  */
-
-bool
-usual_deallocation_fn_p (tree t)
-{
   /* A template instance is never a usual deallocation function,
      regardless of its signature.  */
   if (TREE_CODE (t) == TEMPLATE_DECL
@@ -6418,17 +6377,33 @@ usual_deallocation_fn_p (tree t)
      - optionally, a parameter of type std::align_val_t.  */
   bool global = DECL_NAMESPACE_SCOPE_P (t);
   tree chain = FUNCTION_ARG_CHAIN (t);
-  if (!chain)
-    return false;
-  if (destroying_delete_p (t))
-    chain = TREE_CHAIN (chain);
-  if (chain == void_list_node
-      || ((!global || flag_sized_deallocation)
-         && sized_deallocation_fn_p (t)))
-    return true;
-  if (aligned_deallocation_fn_p (t))
-    return true;
-  return false;
+  if (chain && destroying_delete_p (t))
+    {
+      if (di) di->destroying = TREE_VALUE (chain);
+      chain = TREE_CHAIN (chain);
+    }
+  if (chain
+      && (!global || flag_sized_deallocation)
+      && same_type_p (TREE_VALUE (chain), size_type_node))
+    {
+      if (di) di->sized = true;
+      chain = TREE_CHAIN (chain);
+    }
+  if (chain && aligned_new_threshold
+      && same_type_p (TREE_VALUE (chain), align_type_node))
+    {
+      if (di) di->aligned = true;
+      chain = TREE_CHAIN (chain);
+    }
+  return (chain == void_list_node);
+}
+
+/* Just return whether FN is a usual deallocation function.  */
+
+bool
+usual_deallocation_fn_p (tree fn)
+{
+  return usual_deallocation_fn_p (fn, NULL);
 }
 
 /* Build a call to operator delete.  This has to be handled very specially,
@@ -6457,6 +6432,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 {
   tree fn = NULL_TREE;
   tree fns, fnname, type, t;
+  dealloc_info di_fn = { };
 
   if (addr == error_mark_node)
     return error_mark_node;
@@ -6575,11 +6551,13 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
     for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (fns)); iter; ++iter)
       {
        tree elt = *iter;
-       if (usual_deallocation_fn_p (elt))
+       dealloc_info di_elt;
+       if (usual_deallocation_fn_p (elt, &di_elt))
          {
            if (!fn)
              {
                fn = elt;
+               di_fn = di_elt;
                continue;
              }
 
@@ -6587,12 +6565,13 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
               operator delete, all deallocation functions that are not
               destroying operator deletes are eliminated from further
               consideration.  */
-           bool fn_destroying = destroying_delete_p (fn);
-           bool elt_destroying = destroying_delete_p (elt);
-           if (elt_destroying != fn_destroying)
+           if (di_elt.destroying != di_fn.destroying)
              {
-               if (elt_destroying)
-                 fn = elt;
+               if (di_elt.destroying)
+                 {
+                   fn = elt;
+                   di_fn = di_elt;
+                 }
                continue;
              }
 
@@ -6606,13 +6585,13 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
            if (aligned_new_threshold)
              {
                bool want_align = type_has_new_extended_alignment (type);
-               bool fn_align = aligned_deallocation_fn_p (fn);
-               bool elt_align = aligned_deallocation_fn_p (elt);
-
-               if (elt_align != fn_align)
+               if (di_elt.aligned != di_fn.aligned)
                  {
-                   if (want_align == elt_align)
-                     fn = elt;
+                   if (want_align == di_elt.aligned)
+                     {
+                       fn = elt;
+                       di_fn = di_elt;
+                     }
                    continue;
                  }
              }
@@ -6639,11 +6618,12 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
                  /* We need a cookie to determine the array size.  */
                  want_size = false;
              }
-           bool fn_size = sized_deallocation_fn_p (fn);
-           bool elt_size = sized_deallocation_fn_p (elt);
-           gcc_assert (fn_size != elt_size);
-           if (want_size == elt_size)
-             fn = elt;
+           gcc_assert (di_fn.sized != di_elt.sized);
+           if (want_size == di_elt.sized)
+             {
+               fn = elt;
+               di_fn = di_elt;
+             }
          }
       }
 
@@ -6678,7 +6658,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
        }
       else
        {
-         tree destroying = destroying_delete_p (fn);
+         tree destroying = di_fn.destroying;
          if (destroying)
            {
              /* Strip const and volatile from addr but retain the type of the
@@ -6696,9 +6676,9 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
          args->quick_push (addr);
          if (destroying)
            args->quick_push (destroying);
-         if (sized_deallocation_fn_p (fn))
+         if (di_fn.sized)
            args->quick_push (size);
-         if (aligned_deallocation_fn_p (fn))
+         if (di_fn.aligned)
            {
              tree al = build_int_cst (align_type_node, TYPE_ALIGN_UNIT (type));
              args->quick_push (al);