From patchwork Mon Dec 15 18:30:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 421533 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A6C221400D2 for ; Tue, 16 Dec 2014 05:31:05 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=FKpy/QT+p+z6y0ONrjX8sCn1dPQ4Xu39BPrK7P4VbqAxdp M3VYLv4sa1IW1md4igXEteEaOl5+ThMTrpwcyTQmhDqLRfhDc91cnhQSDEICSGnL hmZPcKOyqIt0Uvma1yg3zIJOJPQbHDMfBHvPIb57GA1ikflSbn+E0NvrBEHhU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=7nEyujdskPj6Vg/Fyy5SDO73Oes=; b=D0WkHwHrTO5hNVH0vnih twsU/gu/stZFwq4w8lGvB/t1ZUDlmyKHjZiYLXVptQ4j0sTMjAxsqJPqczxd3xTO 5SLOl8UfK+NReJa2I/XhJGAUIELnuGdGM8KEbGTN5Y2T8KlBHaABvTiVA3ksy8RT dmmYzGyYaePg5Sgmcf5BuEs= Received: (qmail 30612 invoked by alias); 15 Dec 2014 18:30:56 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 30590 invoked by uid 89); 15 Dec 2014 18:30:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.7 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Mon, 15 Dec 2014 18:30:48 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id sBFIUkZi013964 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Mon, 15 Dec 2014 13:30:47 -0500 Received: from [10.10.116.25] ([10.10.116.25]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sBFIUjf3006852 for ; Mon, 15 Dec 2014 13:30:45 -0500 Message-ID: <548F28D2.5090505@redhat.com> Date: Mon, 15 Dec 2014 13:30:42 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for C++14 sized deallocation This patch implements the last remaining language feature for C++14, global sized deallocation. C++ has always had sized deallocation at class scope, but didn't for deletes that use the global operator delete. The support can be controlled separately from the -std level with the -fsized-deallocation flag (same as clang). The compiler will warn about the unsized variant being defined without the sized variant (or vice versa) with the -Wsized-deallocation flag, which is also enabled by -Wextra. This patch also adds -Wc++14-compat, which currently only warns about a deallocation function with a second size_t parameter changing from being a placement delete to a usual deallocation function. Tested x86_64-pc-linux-gnu, applying to trunk. commit 294f8f12f574592269513ba6f814e564c140b7b5 Author: Jason Merrill Date: Fri Dec 12 23:43:31 2014 -0500 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. diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 08a36f0..dbb9912 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 b9f7c65..1676f65 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/call.c b/gcc/cp/call.c index 312dfdf..86c78ab 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 e851660..e0e7690 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 d478652..bbaf3d6 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 f3b94a9..07bdd92 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 b987ef1..8a7dca3 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 eb9a64d..19422d7 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 0000000..846fce6 --- /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 0000000..a3ab64c --- /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 0000000..e5bfe7c --- /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 fe09df3..9ec3995 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/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index c73ebe7..9b51659 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 679d717..2e60f65 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 88b237e..1c7270a 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 0000000..d97815e --- /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 0000000..11bae1e --- /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); +}