From: Jason Merrill Date: Wed, 20 May 2015 21:32:46 +0000 (-0400) Subject: decl.c (grok_op_properties): Don't complain about size_t placement delete here. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1210105350eff9956347a4c0a3ae09d0514b81d0;p=gcc.git decl.c (grok_op_properties): Don't complain about size_t placement delete here. * 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cb9219dd835..320023a5ad8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2015-05-20 Jason Merrill + + * 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 PR c++/65954 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 07ccea99971..bad49f15d48 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 261a12d6116..e4d3c1db696 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); - } } } diff --git a/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C index a3ab64c26ae..0a76cdccd32 100644 --- a/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C +++ b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C @@ -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 +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 "" } +} diff --git a/gcc/testsuite/g++.dg/init/placement5.C b/gcc/testsuite/g++.dg/init/placement5.C index 1d540daca43..c9f2ea54eb5 100644 --- a/gcc/testsuite/g++.dg/init/placement5.C +++ b/gcc/testsuite/g++.dg/init/placement5.C @@ -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; }