mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-20 12:41:17 +08:00
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
This commit is contained in:
parent
14fa3e7fdf
commit
20b06addf9
@ -1,3 +1,10 @@
|
||||
2014-12-15 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* 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 <jason@redhat.com>
|
||||
|
||||
* c-cppbuiltin.c (c_cpp_builtins): Enable C++14 __cpp_constexpr.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -1,3 +1,20 @@
|
||||
2014-12-15 Jason Merrill <jason@redhat.com>
|
||||
|
||||
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 <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/58882
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<tree, va_gc> **,
|
||||
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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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++
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
75
gcc/testsuite/g++.dg/cpp1y/sized-dealloc1.C
Normal file
75
gcc/testsuite/g++.dg/cpp1y/sized-dealloc1.C
Normal file
@ -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 <new>
|
||||
|
||||
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();
|
||||
}
|
5
gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C
Normal file
5
gcc/testsuite/g++.dg/cpp1y/sized-dealloc2.C
Normal file
@ -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 } } }
|
3
gcc/testsuite/g++.dg/cpp1y/sized-dealloc3.C
Normal file
3
gcc/testsuite/g++.dg/cpp1y/sized-dealloc3.C
Normal file
@ -0,0 +1,3 @@
|
||||
// { dg-options "-Wsized-deallocation" }
|
||||
|
||||
void operator delete (void *p) throw() { __builtin_free(p); } // { dg-warning "sized" "" { target c++14 } }
|
@ -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;
|
||||
|
@ -1,3 +1,11 @@
|
||||
2014-12-15 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* 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 <timshen@google.com>
|
||||
|
||||
PR libstdc++/64239
|
||||
|
@ -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.
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
33
libstdc++-v3/libsupc++/del_ops.cc
Normal file
33
libstdc++-v3/libsupc++/del_ops.cc
Normal file
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include "new"
|
||||
|
||||
_GLIBCXX_WEAK_DEFINITION void
|
||||
operator delete(void* ptr, std::size_t) _GLIBCXX_USE_NOEXCEPT
|
||||
{
|
||||
::operator delete (ptr);
|
||||
}
|
33
libstdc++-v3/libsupc++/del_opvs.cc
Normal file
33
libstdc++-v3/libsupc++/del_opvs.cc
Normal file
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include "new"
|
||||
|
||||
_GLIBCXX_WEAK_DEFINITION void
|
||||
operator delete[] (void *ptr, std::size_t) _GLIBCXX_USE_NOEXCEPT
|
||||
{
|
||||
::operator delete[] (ptr);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user