decl.c (grok_op_properties): Don't complain about size_t placement delete here.
authorJason Merrill <jason@redhat.com>
Wed, 20 May 2015 21:32:46 +0000 (17:32 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 20 May 2015 21:32:46 +0000 (17:32 -0400)
* decl.c (grok_op_properties): Don't complain about size_t
placement delete here.
* call.c (second_parm_is_size_t): Split out from...
(non_placement_deallocation_fn_p): ...here.
(build_op_delete_call): Warn about size_t placement delete with
-Wc++14-compat.

From-SVN: r223460

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/decl.c
gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C
gcc/testsuite/g++.dg/init/placement5.C

index cb9219dd835c08f68fff339dc84718601dc1de6a..320023a5ad81a86e8592e16051f218b53f3f7272 100644 (file)
@@ -1,3 +1,12 @@
+2015-05-20  Jason Merrill  <jason@redhat.com>
+
+       * decl.c (grok_op_properties): Don't complain about size_t
+       placement delete here.
+       * call.c (second_parm_is_size_t): Split out from...
+       (non_placement_deallocation_fn_p): ...here.
+       (build_op_delete_call): Warn about size_t placement delete with
+       -Wc++14-compat.
+
 2015-05-19  Nathan sidwell  <nathan@acm.org>
 
        PR c++/65954
index 07ccea99971e0ae17d92dc7991549ec78185785f..bad49f15d4867e8cf75cb48d58bbb0adc3cc783d 100644 (file)
@@ -5748,6 +5748,18 @@ build_new_op (location_t loc, enum tree_code code, int flags,
   return ret;
 }
 
+/* Returns true if FN has two parameters, of which the second has type
+   size_t.  */
+
+static bool
+second_parm_is_size_t (tree fn)
+{
+  tree t = FUNCTION_ARG_CHAIN (fn);
+  return (t
+         && same_type_p (TREE_VALUE (t), size_type_node)
+         && TREE_CHAIN (t) == void_list_node);
+}
+
 /* Returns true iff T, an element of an OVERLOAD chain, is a usual
    deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]).  */
 
@@ -5768,11 +5780,9 @@ non_placement_deallocation_fn_p (tree t)
      of which has type std::size_t (18.2), then this function is a usual
      deallocation function.  */
   bool global = DECL_NAMESPACE_SCOPE_P (t);
-  t = FUNCTION_ARG_CHAIN (t);
-  if (t == void_list_node
-      || (t && same_type_p (TREE_VALUE (t), size_type_node)
-         && (!global || flag_sized_deallocation)
-         && TREE_CHAIN (t) == void_list_node))
+  if (FUNCTION_ARG_CHAIN (t) == void_list_node
+      || ((!global || flag_sized_deallocation)
+         && second_parm_is_size_t (t)))
     return true;
   return false;
 }
@@ -5859,23 +5869,49 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
         function (3.7.4.2) and that function, considered as a placement
         deallocation function, would have been selected as a match for the
         allocation function, the program is ill-formed."  */
-      if (non_placement_deallocation_fn_p (fn))
+      if (second_parm_is_size_t (fn))
        {
+         const char *msg1
+           = G_("exception cleanup for this placement new selects "
+                "non-placement operator delete");
+         const char *msg2
+           = G_("%q+D is a usual (non-placement) deallocation "
+                "function in C++14 (or with -fsized-deallocation)");
+
          /* But if the class has an operator delete (void *), then that is
             the usual deallocation function, so we shouldn't complain
             about using the operator delete (void *, size_t).  */
-         for (t = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
-              t; t = OVL_NEXT (t))
+         if (DECL_CLASS_SCOPE_P (fn))
+           for (t = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
+                t; t = OVL_NEXT (t))
+             {
+               tree elt = OVL_CURRENT (t);
+               if (non_placement_deallocation_fn_p (elt)
+                   && FUNCTION_ARG_CHAIN (elt) == void_list_node)
+                 goto ok;
+             }
+         /* Before C++14 a two-parameter global deallocation function is
+            always a placement deallocation function, but warn if
+            -Wc++14-compat.  */
+         else if (!flag_sized_deallocation)
            {
-             tree elt = OVL_CURRENT (t);
-             if (non_placement_deallocation_fn_p (elt)
-                 && FUNCTION_ARG_CHAIN (elt) == void_list_node)
-               goto ok;
+             if ((complain & tf_warning)
+                 && warning (OPT_Wc__14_compat, msg1))
+               inform (0, msg2, fn);
+             goto ok;
            }
-         if (complain & tf_error)
+
+         if (complain & tf_warning_or_error)
            {
-             permerror (0, "non-placement deallocation function %q+D", fn);
-             permerror (input_location, "selected for placement delete");
+             if (permerror (input_location, msg1))
+               {
+                 /* Only mention C++14 for namespace-scope delete.  */
+                 if (DECL_NAMESPACE_SCOPE_P (fn))
+                   inform (0, msg2, fn);
+                 else
+                   inform (0, "%q+D is a usual (non-placement) deallocation "
+                           "function", fn);
+               }
            }
          else
            return error_mark_node;
index 261a12d61162d0d6b33e81f17d9c7487152c36de..e4d3c1db6965f48ef2772bdf138401d0b5185b16 100644 (file)
@@ -11767,16 +11767,6 @@ grok_op_properties (tree decl, bool complain)
              error ("%qD may not be declared as static", decl);
              return false;
            }
-         if (!flag_sized_deallocation && warn_cxx14_compat)
-           {
-             tree parm = FUNCTION_ARG_CHAIN (decl);
-             if (parm && same_type_p (TREE_VALUE (parm), size_type_node)
-                 && TREE_CHAIN (parm) == void_list_node)
-               warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc__14_compat,
-                           "%qD is a usual (non-placement) deallocation "
-                           "function in C++14 (or with -fsized-deallocation)",
-                           decl);
-           }
        }
     }
 
index a3ab64c26ae8aebfb7e436e1375f311bf0e4880f..0a76cdccd3294e0cee9fc682a0d0cd54c052a175 100644 (file)
@@ -1,5 +1,26 @@
-// Test that -Wc++14-compat warns about the change in meaning.
-// { dg-options "-Wall" }
+// Test for a diagnostic about a usual deallocation function used as a
+// placement deallocation function.  This will be a warning in C++98/11
+// modes and an error in C++14 mode.
 
-typedef __SIZE_TYPE__ size_t;
-void operator delete[] (void *p, size_t s) throw(); // { dg-warning "usual" "" { target { ! c++14 } } }
+// { dg-options "-Wc++14-compat" }
+
+#include <new>
+void *operator new (std::size_t s, std::size_t)
+{
+  return operator new (s);
+}
+
+void operator delete (void *p, std::size_t) throw()
+{
+  return ::operator delete (p);
+}
+
+struct A
+{
+  A();
+};
+
+void f()
+{
+  new (42) A;          // { dg-message "" }
+}
index 1d540daca4329b34e0b36bf607ce819e81657443..c9f2ea54eb50c57e39dc9ed0df05519e8923123d 100644 (file)
@@ -13,7 +13,7 @@ struct A
 {
   A();
   void* operator new (size_t, size_t);
-  void operator delete (void *, size_t); // { dg-error "non-placement" }
+  void operator delete (void *, size_t); // { dg-message "non-placement" }
 };
 
 struct B
@@ -27,6 +27,6 @@ struct B
 
 int main()
 {
-  A* ap = new (24) A;          // { dg-error "placement delete" }
+  A* ap = new (24) A;          // { dg-error "placement" }
   B* bp = new (24) B;
 }