This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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 <jason@redhat.com>
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<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);
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 <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();
+}
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
+// <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);
+}
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
+// <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);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]