From 20b06addf9bfe928559f3bccca9e70485eec7c02 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 15 Dec 2014 13:31:40 -0500 Subject: [PATCH] N3778: Sized Deallocation N3778: Sized Deallocation gcc/c-family/ * c.opt (-fsized-deallocation, -Wc++14-compat): New. (-Wsized-deallocation): New. * c-opts.c (c_common_post_options): -fsized-deallocation defaults to on in C++14 and up. gcc/cp/ * call.c (non_placement_deallocation_fn_p): A global sized operator delete is not a usual deallocation function until C++14. (build_op_delete_call): Choose the global sized op delete if we know the size. * cp-tree.h: Declare non_placement_deallocation_fn_p. (enum cp_tree_index): Remove CPTI_GLOBAL_DELETE_FNDECL. (global_delete_fndecl): Remove. * decl.c (cxx_init_decl_processing): Also declare sized op deletes. (grok_op_properties): Warn about sized dealloc without the flag. * init.c (build_builtin_delete_call): Remove. (build_vec_delete_1, build_delete): Don't call it. * decl2.c (maybe_warn_sized_delete): New. (cp_write_global_declarations): Call it. libstdc++-v3/ * libsupc++/del_ops.cc: New. * libsupc++/del_opvs.cc: New. * libsupc++/Makefile.am: Add them. * libsupc++/Makefile.in: Regenerate. * config/abi/pre/gnu.ver: Export _ZdlPvm and _ZdaPvm. From-SVN: r218755 --- gcc/c-family/ChangeLog | 7 ++ gcc/c-family/c-opts.c | 4 ++ gcc/c-family/c.opt | 12 ++++ gcc/cp/ChangeLog | 17 +++++ gcc/cp/call.c | 40 +++++++++-- gcc/cp/cp-tree.h | 3 +- gcc/cp/decl.c | 30 +++++++-- gcc/cp/decl2.c | 43 ++++++++++++ gcc/cp/init.c | 28 +++----- gcc/doc/invoke.texi | 40 ++++++++++- gcc/testsuite/g++.dg/cpp1y/sized-dealloc1.C | 75 +++++++++++++++++++++ gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C | 5 ++ gcc/testsuite/g++.dg/cpp1y/sized-dealloc3.C | 3 + gcc/testsuite/g++.dg/tree-ssa/pr61034.C | 2 + libstdc++-v3/ChangeLog | 8 +++ libstdc++-v3/config/abi/pre/gnu.ver | 5 ++ libstdc++-v3/libsupc++/Makefile.am | 2 + libstdc++-v3/libsupc++/Makefile.in | 25 ++++--- libstdc++-v3/libsupc++/del_ops.cc | 33 +++++++++ libstdc++-v3/libsupc++/del_opvs.cc | 33 +++++++++ 20 files changed, 372 insertions(+), 43 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/sized-dealloc1.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/sized-dealloc3.C create mode 100644 libstdc++-v3/libsupc++/del_ops.cc create mode 100644 libstdc++-v3/libsupc++/del_opvs.cc diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index f064370cc78..2d0c2fe5872 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2014-12-15 Jason Merrill + + * c.opt (-fsized-deallocation, -Wc++14-compat): New. + (-Wsized-deallocation): New. + * c-opts.c (c_common_post_options): -fsized-deallocation defaults + to on in C++14 and up. + 2014-12-11 Jason Merrill * c-cppbuiltin.c (c_cpp_builtins): Enable C++14 __cpp_constexpr. diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 08a36f03c8c..dbb99125462 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -889,6 +889,10 @@ c_common_post_options (const char **pfilename) else if (warn_narrowing == -1) warn_narrowing = 0; + /* Global sized deallocation is new in C++14. */ + if (flag_sized_deallocation == -1) + flag_sized_deallocation = (cxx_dialect >= cxx14); + if (flag_extern_tls_init) { #if !defined (ASM_OUTPUT_DEF) || !SUPPORTS_WEAK diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index b9f7c656209..1676f65bcd2 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -315,6 +315,10 @@ Wc++11-compat C++ ObjC++ Warning Alias(Wc++0x-compat) Warn about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 2011 +Wc++14-compat +C++ ObjC++ Var(warn_cxx14_compat) Warning LangEnabledBy(C++ ObjC++,Wall) +Warn about C++ constructs whose meaning differs between ISO C++ 2011 and ISO C++ 2014 + Wcast-qual C ObjC C++ ObjC++ Var(warn_cast_qual) Warning Warn about casts which discard qualifiers @@ -554,6 +558,10 @@ Wmissing-field-initializers C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Warning EnabledBy(Wextra) Warn about missing fields in struct initializers +Wsized-deallocation +C++ ObjC++ Var(warn_sized_deallocation) Warning EnabledBy(Wextra) +Warn about missing sized deallocation functions + Wsizeof-pointer-memaccess C ObjC C++ ObjC++ Var(warn_sizeof_pointer_memaccess) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn about suspicious length parameters to certain string functions if the argument uses sizeof @@ -1341,6 +1349,10 @@ fsigned-char C ObjC C++ ObjC++ LTO Var(flag_signed_char) Make \"char\" signed by default +fsized-deallocation +C++ ObjC++ Var(flag_sized_deallocation) Init(-1) +Enable C++14 sized deallocation support + fsquangle C++ ObjC++ Ignore Warn(switch %qs is no longer supported) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4eb762c91ab..c14020dafd6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +2014-12-15 Jason Merrill + + N3778: Sized Deallocation + * call.c (non_placement_deallocation_fn_p): A global sized + operator delete is not a usual deallocation function until C++14. + (build_op_delete_call): Choose the global sized op delete if we + know the size. + * cp-tree.h: Declare non_placement_deallocation_fn_p. + (enum cp_tree_index): Remove CPTI_GLOBAL_DELETE_FNDECL. + (global_delete_fndecl): Remove. + * decl.c (cxx_init_decl_processing): Also declare sized op deletes. + (grok_op_properties): Warn about sized dealloc without the flag. + * init.c (build_builtin_delete_call): Remove. + (build_vec_delete_1, build_delete): Don't call it. + * decl2.c (maybe_warn_sized_delete): New. + (cp_write_global_declarations): Call it. + 2014-12-15 Paolo Carlini PR c++/58882 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 312dfdf2421..86c78ab47f6 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5733,7 +5733,7 @@ build_new_op (location_t loc, enum tree_code code, int flags, /* Returns true iff T, an element of an OVERLOAD chain, is a usual deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]). */ -static bool +bool non_placement_deallocation_fn_p (tree t) { /* A template instance is never a usual deallocation function, @@ -5749,9 +5749,11 @@ non_placement_deallocation_fn_p (tree t) function named operator delete with exactly two parameters, the second 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)) return true; return false; @@ -5883,9 +5885,39 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, which has type std::size_t (18.2), then this function is a usual deallocation function." - So (void*) beats (void*, size_t). */ - if (FUNCTION_ARG_CHAIN (fn) == void_list_node) - break; + So in a class (void*) beats (void*, size_t). */ + if (DECL_CLASS_SCOPE_P (fn)) + { + if (FUNCTION_ARG_CHAIN (fn) == void_list_node) + break; + } + /* At global scope (in C++14 and above) the rules are different: + + If deallocation function lookup finds both a usual + deallocation function with only a pointer parameter and a + usual deallocation function with both a pointer parameter + and a size parameter, the function to be called is selected + as follows: + + * If the type is complete and if, for the second alternative + (delete array) only, the operand is a pointer to a class + type with a non-trivial destructor or a (possibly + multi-dimensional) array thereof, the function with two + parameters is selected. + + * Otherwise, it is unspecified which of the two deallocation + functions is selected. */ + else + { + bool want_size = COMPLETE_TYPE_P (type); + if (code == VEC_DELETE_EXPR + && !TYPE_VEC_NEW_USES_COOKIE (type)) + /* We need a cookie to determine the array size. */ + want_size = false; + bool have_size = (FUNCTION_ARG_CHAIN (fn) != void_list_node); + if (want_size == have_size) + break; + } } } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e8516606184..e0e7690b188 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -891,7 +891,6 @@ enum cp_tree_index CPTI_CONST_TYPE_INFO_TYPE, CPTI_TYPE_INFO_PTR_TYPE, CPTI_ABORT_FNDECL, - CPTI_GLOBAL_DELETE_FNDECL, CPTI_AGGR_TAG, CPTI_CTOR_IDENTIFIER, @@ -962,7 +961,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; #define const_type_info_type_node cp_global_trees[CPTI_CONST_TYPE_INFO_TYPE] #define type_info_ptr_type cp_global_trees[CPTI_TYPE_INFO_PTR_TYPE] #define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL] -#define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL] #define current_aggr cp_global_trees[CPTI_AGGR_TAG] #define nullptr_node cp_global_trees[CPTI_NULLPTR] #define nullptr_type_node cp_global_trees[CPTI_NULLPTR_TYPE] @@ -5185,6 +5183,7 @@ extern tree build_new_op (location_t, enum tree_code, tsubst_flags_t); extern tree build_op_call (tree, vec **, tsubst_flags_t); +extern bool non_placement_deallocation_fn_p (tree); extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree, tsubst_flags_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d47865287a8..bbaf3d68d9e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -159,10 +159,6 @@ static void expand_static_init (tree, tree); tree abort_fndecl; - The FUNCTION_DECL for the default `::operator delete'. - - tree global_delete_fndecl; - Used by RTTI tree type_info_type_node, tinfo_decl_id, tinfo_decl_type; tree tinfo_var_id; */ @@ -3954,8 +3950,22 @@ cxx_init_decl_processing (void) opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; DECL_IS_OPERATOR_NEW (opnew) = 1; - global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); + push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + if (flag_sized_deallocation) + { + /* Also push the sized deallocation variants: + void operator delete(void*, std::size_t) throw(); + void operator delete[](void*, std::size_t) throw(); */ + tree void_ftype_ptr_size + = build_function_type_list (void_type_node, ptr_type_node, + size_type_node, NULL_TREE); + deltype = cp_build_type_attribute_variant (void_ftype_ptr_size, + extvisattr); + deltype = build_exception_variant (deltype, empty_except_spec); + push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); + push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + } nullptr_type_node = make_node (NULLPTR_TYPE); TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode)); @@ -11745,6 +11755,16 @@ 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/cp/decl2.c b/gcc/cp/decl2.c index f3b94a93dc5..07bdd92de93 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4308,6 +4308,47 @@ dump_tu (void) } } +/* Check the deallocation functions for CODE to see if we want to warn that + only one was defined. */ + +static void +maybe_warn_sized_delete (enum tree_code code) +{ + tree sized = NULL_TREE; + tree unsized = NULL_TREE; + + for (tree ovl = IDENTIFIER_GLOBAL_VALUE (ansi_opname (code)); + ovl; ovl = OVL_NEXT (ovl)) + { + tree fn = OVL_CURRENT (ovl); + /* We're only interested in usual deallocation functions. */ + if (!non_placement_deallocation_fn_p (fn)) + continue; + if (FUNCTION_ARG_CHAIN (fn) == void_list_node) + unsized = fn; + else + sized = fn; + } + if (DECL_INITIAL (unsized) && !DECL_INITIAL (sized)) + warning_at (DECL_SOURCE_LOCATION (unsized), OPT_Wsized_deallocation, + "the program should also define %qD", sized); + else if (!DECL_INITIAL (unsized) && DECL_INITIAL (sized)) + warning_at (DECL_SOURCE_LOCATION (sized), OPT_Wsized_deallocation, + "the program should also define %qD", unsized); +} + +/* Check the global deallocation functions to see if we want to warn about + defining unsized without sized (or vice versa). */ + +static void +maybe_warn_sized_delete () +{ + if (!flag_sized_deallocation || !warn_sized_deallocation) + return; + maybe_warn_sized_delete (DELETE_EXPR); + maybe_warn_sized_delete (VEC_DELETE_EXPR); +} + /* This routine is called at the end of compilation. Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -4638,6 +4679,8 @@ cp_write_global_declarations (void) FOR_EACH_VEC_SAFE_ELT (no_linkage_decls, i, decl) no_linkage_error (decl); + maybe_warn_sized_delete (); + /* Then, do the Objective-C stuff. This is where all the Objective-C module stuff gets generated (symtab, class/protocol/selector lists etc). This must be done after C++ diff --git a/gcc/cp/init.c b/gcc/cp/init.c index b987ef15a0d..8a7dca32b46 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -39,7 +39,6 @@ static void construct_virtual_base (tree, tree); static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); static void perform_member_init (tree, tree); -static tree build_builtin_delete_call (tree); static int member_init_ok_or_else (tree, tree, tree); static void expand_virtual_init (tree, tree); static tree sort_mem_initializers (tree, tree); @@ -2094,15 +2093,6 @@ decl_constant_value (tree decl) } /* Common subroutines of build_new and build_vec_delete. */ - -/* Call the global __builtin_delete to delete ADDR. */ - -static tree -build_builtin_delete_call (tree addr) -{ - mark_used (global_delete_fndecl); - return build_call_n (global_delete_fndecl, 1, addr); -} /* Build and return a NEW_EXPR. If NELTS is non-NULL, TYPE[NELTS] is the type of the object being allocated; otherwise, it's just TYPE. @@ -3211,7 +3201,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, "class-specific operator delete [] will be called, " "even if they are declared when the class is defined"); } - return build_builtin_delete_call (base); + /* This size won't actually be used. */ + size_exp = size_one_node; + goto no_destructor; } size_exp = size_in_bytes (type); @@ -3967,8 +3959,6 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete, if (TYPE_PTR_P (otype)) { - bool complete_p = true; - addr = mark_rvalue_use (addr); /* We don't want to warn about delete of void*, only other @@ -3993,7 +3983,6 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete, "operator delete will be called, even if they are " "declared when the class is defined"); } - complete_p = false; } else if (auto_delete == sfk_deleting_destructor && warn_delnonvdtor && MAYBE_CLASS_TYPE_P (type) && !CLASSTYPE_FINAL (type) @@ -4016,9 +4005,6 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete, } } } - if (VOID_TYPE_P (type) || !complete_p || !MAYBE_CLASS_TYPE_P (type)) - /* Call the builtin operator delete. */ - return build_builtin_delete_call (addr); if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); @@ -4079,7 +4065,13 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete, addr = save_expr (addr); head = get_target_expr (build_headof (addr)); /* Delete the object. */ - do_delete = build_builtin_delete_call (head); + do_delete = build_op_delete_call (DELETE_EXPR, + head, + cxx_sizeof_nowarn (type), + /*global_p=*/true, + /*placement=*/NULL_TREE, + /*alloc_fn=*/NULL_TREE, + complain); /* Otherwise, treat this like a complete object destructor call. */ auto_delete = sfk_complete_destructor; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index eb9a64dc9ba..19422d78cd1 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -187,7 +187,8 @@ in the following sections. -fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol -fno-optional-diags -fpermissive @gol -fno-pretty-templates @gol --frepo -fno-rtti -fstats -ftemplate-backtrace-limit=@var{n} @gol +-frepo -fno-rtti -fsized-deallocation @gol +-fstats -ftemplate-backtrace-limit=@var{n} @gol -ftemplate-depth=@var{n} @gol -fno-threadsafe-statics -fuse-cxa-atexit @gol -fno-weak -nostdinc++ @gol @@ -243,7 +244,7 @@ Objective-C and Objective-C++ Dialects}. -Wbool-compare @gol -Wno-attributes -Wno-builtin-macro-redefined @gol -Wc90-c99-compat -Wc99-c11-compat @gol --Wc++-compat -Wc++11-compat -Wcast-align -Wcast-qual @gol +-Wc++-compat -Wc++11-compat -Wc++14-compat -Wcast-align -Wcast-qual @gol -Wchar-subscripts -Wclobbered -Wcomment -Wconditionally-supported @gol -Wconversion -Wcoverage-mismatch -Wdate-time -Wdelete-incomplete -Wno-cpp @gol -Wno-deprecated -Wno-deprecated-declarations -Wno-designated-init @gol @@ -2304,6 +2305,19 @@ needed. The @samp{dynamic_cast} operator can still be used for casts that do not require run-time type information, i.e.@: casts to @code{void *} or to unambiguous base classes. +@item -fsized-deallocation +@opindex fsized-deallocation +Enable the built-in global declarations +@smallexample +void operator delete (void *, std::size_t) noexcept; +void operator delete[] (void *, std::size_t) noexcept; +@end smallexample +as introduced in C++14. This is useful for user-defined replacement +deallocation functions that, for example, use the size of the object +to make deallocation faster. Enabled by default under +@samp{-std=c++14} and above. The flag @option{-Wsized-deallocation} will +warn about places that might want to add a definition. + @item -fstats @opindex fstats Emit statistics about front-end processing at the end of the compilation. @@ -3356,7 +3370,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}. @gccoptlist{-Waddress @gol -Warray-bounds @r{(only with} @option{-O2}@r{)} @gol --Wc++11-compat @gol +-Wc++11-compat -Wc++14-compat@gol -Wchar-subscripts @gol -Wenum-compare @r{(in C/ObjC; this is on by default in C++)} @gol -Wimplicit-int @r{(C and Objective-C only)} @gol @@ -4608,6 +4622,10 @@ and ISO C++ 2011, e.g., identifiers in ISO C++ 1998 that are keywords in ISO C++ 2011. This warning turns on @option{-Wnarrowing} and is enabled by @option{-Wall}. +@item -Wc++14-compat @r{(C++ and Objective-C++ only)} +Warn about C++ constructs whose meaning differs between ISO C++ 2011 +and ISO C++ 2014. This warning is enabled by @option{-Wall}. + @item -Wcast-qual @opindex Wcast-qual @opindex Wno-cast-qual @@ -4767,6 +4785,22 @@ This includes conversions from real to integer, and from higher precision real to lower precision real values. This option is also enabled by @option{-Wconversion}. +@item -Wsized-deallocation @r{(C++ and Objective-C++ only)} +@opindex Wsized-deallocation +@opindex -Wno-sized-deallocation +Warn about a definition of an unsized deallocation function +@smallexample +void operator delete (void *) noexcept; +void operator delete[] (void *) noexcept; +@end smallexample +without a definition of the corresponding sized deallocation function +@smallexample +void operator delete (void *, std::size_t) noexcept; +void operator delete[] (void *, std::size_t) noexcept; +@end smallexample +or vice versa. Enabled by @option{-Wextra} along with +@option{-fsized-deallocation}. + @item -Wsizeof-pointer-memaccess @opindex Wsizeof-pointer-memaccess @opindex Wno-sizeof-pointer-memaccess diff --git a/gcc/testsuite/g++.dg/cpp1y/sized-dealloc1.C b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc1.C new file mode 100644 index 00000000000..846fce61990 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc1.C @@ -0,0 +1,75 @@ +// Test for C++14 sized deallocation. The operators delete defined below +// should be called only in C++14 mode and above. +// { dg-do run } + +extern "C" void abort(); +typedef __SIZE_TYPE__ size_t; +#include + +bool called; +void operator delete[] (void *p, size_t s) throw() +{ + called = true; + operator delete[] (p); +} + +void operator delete (void *p, size_t s) throw() +{ + called = true; + operator delete (p); +} + +void operator delete[] (void *p, size_t s, const std::nothrow_t &) throw() +{ + called = true; + operator delete[] (p); +} + +void operator delete (void *p, size_t s, const std::nothrow_t &) throw() +{ + called = true; + operator delete (p); +} + +struct A { ~A(){} }; + +struct B { }; + +struct C; + +struct D { ~D(){}; D() { throw 1; } }; + +int main() +{ + /* * If the type is complete and if, for the second alternative (delete + array) only, the operand is a pointer to a class type with a + non-trivial destructor or a (possibly multi-dimensional) array + thereof, the function with two parameters is selected. + + * Otherwise, it is unspecified which of the two deallocation functions + is selected. */ + delete new int; + if (called != (__cplusplus >= 201402L)) abort(); called = false; + + delete new A; + if (called != (__cplusplus >= 201402L)) abort(); called = false; + + delete[] new A[2]; + if (called != (__cplusplus >= 201402L)) abort(); called = false; + + delete new B; + if (called != (__cplusplus >= 201402L)) abort(); called = false; + + /* N3778 added the sized placement deallocation functions, but the core + language rules don't provide any way they would be called. */ + try { new (std::nothrow) D; } catch (int) {} + if (called) abort(); + + try { new (std::nothrow) D[2]; } catch (int) {} + if (called) abort(); + + /* Make sure we don't try to use the size of an array that doesn't have a + cookie. */ + delete[] new B[2]; + if (called) abort(); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C new file mode 100644 index 00000000000..a3ab64c26ae --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C @@ -0,0 +1,5 @@ +// Test that -Wc++14-compat warns about the change in meaning. +// { dg-options "-Wall" } + +typedef __SIZE_TYPE__ size_t; +void operator delete[] (void *p, size_t s) throw(); // { dg-warning "usual" "" { target { ! c++14 } } } diff --git a/gcc/testsuite/g++.dg/cpp1y/sized-dealloc3.C b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc3.C new file mode 100644 index 00000000000..e5bfe7cdde9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/sized-dealloc3.C @@ -0,0 +1,3 @@ +// { dg-options "-Wsized-deallocation" } + +void operator delete (void *p) throw() { __builtin_free(p); } // { dg-warning "sized" "" { target c++14 } } diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C index fe09df31209..9ec3995afde 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C @@ -5,6 +5,8 @@ inline void* operator new(__SIZE_TYPE__ n){ return __builtin_malloc(n); } inline void operator delete(void *p) { __builtin_free(p); } +// C++14 sized deallocation function +inline void operator delete(void *p, __SIZE_TYPE__) { __builtin_free(p); } struct O { double num; int count; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4e79925ff0f..2f8c54b2603 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2014-12-15 Jason Merrill + + * libsupc++/del_ops.cc: New. + * libsupc++/del_opvs.cc: New. + * libsupc++/Makefile.am: Add them. + * libsupc++/Makefile.in: Regenerate. + * config/abi/pre/gnu.ver: Export _ZdlPvm and _ZdaPvm. + 2014-12-13 Tim Shen PR libstdc++/64239 diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index c73ebe7a655..9b516599563 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -1733,6 +1733,11 @@ CXXABI_1.3.9 { _ZTSP[no]; _ZTSPK[no]; + # operator delete(void*, std::size_t) + _ZdlPvm; + # operator delete[](void*, std::size_t) + _ZdaPvm; + } CXXABI_1.3.8; # Symbols in the support library (libsupc++) supporting transactional memory. diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am index 679d71750f2..2e60f65249e 100644 --- a/libstdc++-v3/libsupc++/Makefile.am +++ b/libstdc++-v3/libsupc++/Makefile.am @@ -55,8 +55,10 @@ sources = \ bad_typeid.cc \ class_type_info.cc \ del_op.cc \ + del_ops.cc \ del_opnt.cc \ del_opv.cc \ + del_opvs.cc \ del_opvnt.cc \ dyncast.cc \ eh_alloc.cc \ diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in index 88b237e1275..1c7270a69d3 100644 --- a/libstdc++-v3/libsupc++/Makefile.in +++ b/libstdc++-v3/libsupc++/Makefile.in @@ -93,17 +93,18 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES) libsupc___la_LIBADD = am__objects_1 = array_type_info.lo atexit_arm.lo atexit_thread.lo \ bad_alloc.lo bad_array_length.lo bad_array_new.lo bad_cast.lo \ - bad_typeid.lo class_type_info.lo del_op.lo del_opnt.lo \ - del_opv.lo del_opvnt.lo dyncast.lo eh_alloc.lo eh_arm.lo \ - eh_aux_runtime.lo eh_call.lo eh_catch.lo eh_exception.lo \ - eh_globals.lo eh_personality.lo eh_ptr.lo eh_term_handler.lo \ - eh_terminate.lo eh_tm.lo eh_throw.lo eh_type.lo \ - eh_unex_handler.lo enum_type_info.lo function_type_info.lo \ - fundamental_type_info.lo guard.lo guard_error.lo hash_bytes.lo \ - nested_exception.lo new_handler.lo new_op.lo new_opnt.lo \ - new_opv.lo new_opvnt.lo pbase_type_info.lo pmem_type_info.lo \ - pointer_type_info.lo pure.lo si_class_type_info.lo tinfo.lo \ - tinfo2.lo vec.lo vmi_class_type_info.lo vterminate.lo + bad_typeid.lo class_type_info.lo del_op.lo del_ops.lo \ + del_opnt.lo del_opv.lo del_opvs.lo del_opvnt.lo dyncast.lo \ + eh_alloc.lo eh_arm.lo eh_aux_runtime.lo eh_call.lo eh_catch.lo \ + eh_exception.lo eh_globals.lo eh_personality.lo eh_ptr.lo \ + eh_term_handler.lo eh_terminate.lo eh_tm.lo eh_throw.lo \ + eh_type.lo eh_unex_handler.lo enum_type_info.lo \ + function_type_info.lo fundamental_type_info.lo guard.lo \ + guard_error.lo hash_bytes.lo nested_exception.lo \ + new_handler.lo new_op.lo new_opnt.lo new_opv.lo new_opvnt.lo \ + pbase_type_info.lo pmem_type_info.lo pointer_type_info.lo \ + pure.lo si_class_type_info.lo tinfo.lo tinfo2.lo vec.lo \ + vmi_class_type_info.lo vterminate.lo @GLIBCXX_HOSTED_TRUE@am__objects_2 = cp-demangle.lo @ENABLE_VTABLE_VERIFY_TRUE@am__objects_3 = vtv_stubs.lo am_libsupc___la_OBJECTS = $(am__objects_1) $(am__objects_2) \ @@ -381,8 +382,10 @@ sources = \ bad_typeid.cc \ class_type_info.cc \ del_op.cc \ + del_ops.cc \ del_opnt.cc \ del_opv.cc \ + del_opvs.cc \ del_opvnt.cc \ dyncast.cc \ eh_alloc.cc \ diff --git a/libstdc++-v3/libsupc++/del_ops.cc b/libstdc++-v3/libsupc++/del_ops.cc new file mode 100644 index 00000000000..d97815ee5bc --- /dev/null +++ b/libstdc++-v3/libsupc++/del_ops.cc @@ -0,0 +1,33 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. + +// Copyright (C) 1997-2014 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#include +#include "new" + +_GLIBCXX_WEAK_DEFINITION void +operator delete(void* ptr, std::size_t) _GLIBCXX_USE_NOEXCEPT +{ + ::operator delete (ptr); +} diff --git a/libstdc++-v3/libsupc++/del_opvs.cc b/libstdc++-v3/libsupc++/del_opvs.cc new file mode 100644 index 00000000000..11bae1e306d --- /dev/null +++ b/libstdc++-v3/libsupc++/del_opvs.cc @@ -0,0 +1,33 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. + +// Copyright (C) 1997-2014 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#include +#include "new" + +_GLIBCXX_WEAK_DEFINITION void +operator delete[] (void *ptr, std::size_t) _GLIBCXX_USE_NOEXCEPT +{ + ::operator delete[] (ptr); +} -- 2.30.2