RFA (libstdc++): PATCH to implement C++17 over-aligned new

Jason Merrill jason@redhat.com
Fri Sep 9 21:40:00 GMT 2016


On Thu, Sep 8, 2016 at 7:06 AM, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 08/09/16 09:10 +0200, Marc Glisse wrote:
>>
>> Do we want a generic fallback implementation (similar to
>> gcc/config/i386/gmm_malloc.h)? A windows version with _aligned_malloc /
>> _aligned_free would also be possible.
>
> Making it work for MinGW would be nice.

OK, this is what I'm checking in; could someone test it on MinGW?

Jason
-------------- next part --------------
commit a528da2f1cabfcfd127e3246342dab2271254e45
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Sep 7 16:22:54 2016 -0400

            Implement P0035R4, C++17 new of over-aligned types.
    
    gcc/cp/
            * cp-tree.h (enum cp_tree_index): Add CPTI_ALIGN_TYPE.
            (align_type_node): New macro.
            * call.c (build_operator_new_call): Handle C++17 aligned new.
            (second_parm_is_size_t, build_op_delete_call): Likewise.
            (non_placement_deallocation_fn_p): Likewise. Rename to
            usual_deallocation_fn_p.
            (aligned_allocation_fn_p, aligned_deallocation_fn_p): New.
            * decl.c (cxx_init_decl_processing): Add aligned new support.
            * init.c (type_has_new_extended_alignment): New.
            (build_new_1): Handle aligned new.
            * tree.c (vec_copy_and_insert): New.
    gcc/c-family/
            * c.opt: Add -faligned-new and -Waligned-new.
            * c-common.c (max_align_t_align): Split out from...
            (cxx_fundamental_alignment_p): ...here.
            * c-common.h: Declare it.
            * c-cppbuiltin.c (c_cpp_builtins): Handle aligned new.
    libstdc++-v3/
            * libsupc++/new: Declare aligned new/delete operators.
            * config/abi/pre/gnu.ver: Export them.
            * configure.ac: Check for aligned_alloc, posix_memalign, memalign,
            _aligned_malloc.
            * libsupc++/new_opa.cc: New.
            * libsupc++/new_opant.cc: New.
            * libsupc++/new_opva.cc: New.
            * libsupc++/new_opva.cc: New.
            * libsupc++/del_opa.cc: New.
            * libsupc++/del_opant.cc: New.
            * libsupc++/del_opsa.cc: New.
            * libsupc++/del_opva.cc: New.
            * libsupc++/del_opvant.cc: New.
            * libsupc++/del_opvsa.cc: New.
            * libsupc++/Makefile.am: Build them.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 656f639..9a66cfe 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -12878,6 +12878,19 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1,
   return stv_nothing;
 }
 
+/* Return the alignment of std::max_align_t.
+
+   [support.types.layout] The type max_align_t is a POD type whose alignment
+   requirement is at least as great as that of every scalar type, and whose
+   alignment requirement is supported in every context.  */
+
+unsigned
+max_align_t_align ()
+{
+  return MAX (TYPE_ALIGN (long_long_integer_type_node),
+	      TYPE_ALIGN (long_double_type_node));
+}
+
 /* Return true iff ALIGN is an integral constant that is a fundamental
    alignment, as defined by [basic.align] in the c++-11
    specifications.
@@ -12886,14 +12899,12 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1,
 
        [A fundamental alignment is represented by an alignment less than or
         equal to the greatest alignment supported by the implementation
-        in all contexts, which is equal to
-        alignof(max_align_t)].  */
+        in all contexts, which is equal to alignof(max_align_t)].  */
 
 bool
-cxx_fundamental_alignment_p  (unsigned align)
+cxx_fundamental_alignment_p (unsigned align)
 {
-  return (align <=  MAX (TYPE_ALIGN (long_long_integer_type_node),
-			 TYPE_ALIGN (long_double_type_node)));
+  return (align <= max_align_t_align ());
 }
 
 /* Return true if T is a pointer to a zero-sized aggregate.  */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 1d923c9..2e211c4 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -863,6 +863,7 @@ extern bool keyword_begins_type_specifier (enum rid);
 extern bool keyword_is_storage_class_specifier (enum rid);
 extern bool keyword_is_type_qualifier (enum rid);
 extern bool keyword_is_decl_specifier (enum rid);
+extern unsigned max_align_t_align (void);
 extern bool cxx_fundamental_alignment_p (unsigned);
 extern bool pointer_to_zero_sized_aggr_p (tree);
 extern bool diagnose_mismatched_attributes (tree, tree);
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 3338276..bb30829 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -944,6 +944,12 @@ c_cpp_builtins (cpp_reader *pfile)
 	cpp_define (pfile, "__cpp_transactional_memory=210500");
       if (flag_sized_deallocation)
 	cpp_define (pfile, "__cpp_sized_deallocation=201309");
+      if (aligned_new_threshhold)
+	{
+	  cpp_define (pfile, "__cpp_aligned_new=201606");
+	  cpp_define_formatted (pfile, "__STDCPP_DEFAULT_NEW_ALIGNMENT__=%d",
+				aligned_new_threshhold);
+	}
     }
   /* Note that we define this for C as well, so that we know if
      __attribute__((cleanup)) will interface with EH.  */
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index a5358ed..c55c7c3 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -271,6 +271,26 @@ Waddress
 C ObjC C++ ObjC++ Var(warn_address) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
 Warn about suspicious uses of memory addresses.
 
+Enum
+Name(warn_aligned_new_level) Type(int) UnknownError(argument %qs to %<-Waligned-new%> not recognized)
+
+EnumValue
+Enum(warn_aligned_new_level) String(none) Value(0)
+
+EnumValue
+Enum(warn_aligned_new_level) String(global) Value(1)
+
+EnumValue
+Enum(warn_aligned_new_level) String(all) Value(2)
+
+Waligned-new
+C++ ObjC++ Alias(Waligned-new=,global,none)
+Warn about 'new' of type with extended alignment without -faligned-new.
+
+Waligned-new=
+C++ ObjC++ Var(warn_aligned_new) Enum(warn_aligned_new_level) Joined Warning LangEnabledBy(C++ ObjC++,Wall,1,0)
+-Waligned-new=all Warn even if 'new' uses a class member allocation function.
+
 Wall
 C ObjC C++ ObjC++ Warning
 Enable most warning messages.
@@ -1032,6 +1052,14 @@ fada-spec-parent=
 C ObjC C++ ObjC++ RejectNegative Joined Var(ada_specs_parent)
 -fada-spec-parent=unit  Dump Ada specs as child units of given parent.
 
+faligned-new
+C++ ObjC++ Alias(faligned-new=,1,0)
+Support C++17 allocation of over-aligned types.
+
+faligned-new=
+C++ ObjC++ Joined Var(aligned_new_threshhold) UInteger Init(-1)
+-faligned-new=<N> Use C++17 over-aligned type allocation for alignments greater than N.
+
 fall-virtual
 C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
 
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 024519d..167d778 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4211,13 +4211,14 @@ build_new_function_call (tree fn, vec<tree, va_gc> **args, bool koenig_p,
 
 tree
 build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
-			 tree *size, tree *cookie_size, tree size_check,
+			 tree *size, tree *cookie_size,
+			 tree align_arg, tree size_check,
 			 tree *fn, tsubst_flags_t complain)
 {
   tree original_size = *size;
   tree fns;
   struct z_candidate *candidates;
-  struct z_candidate *cand;
+  struct z_candidate *cand = NULL;
   bool any_viable_p;
 
   if (fn)
@@ -4247,9 +4248,20 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
      we disregard block-scope declarations of "operator new".  */
   fns = lookup_function_nonclass (fnname, *args, /*block_p=*/false);
 
+  if (align_arg)
+    {
+      vec<tree, va_gc>* align_args
+	= vec_copy_and_insert (*args, align_arg, 1);
+      cand = perform_overload_resolution (fns, align_args, &candidates,
+					  &any_viable_p, tf_none);
+      /* If no aligned allocation function matches, try again without the
+	 alignment.  */
+    }
+
   /* Figure out what function is being called.  */
-  cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p,
-				      complain);
+  if (!cand)
+    cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p,
+					complain);
 
   /* If no suitable function could be found, issue an error message
      and give up.  */
@@ -5945,16 +5957,65 @@ static bool
 second_parm_is_size_t (tree fn)
 {
   tree t = FUNCTION_ARG_CHAIN (fn);
-  return (t
-	  && same_type_p (TREE_VALUE (t), size_type_node)
-	  && TREE_CHAIN (t) == void_list_node);
+  if (!t || !same_type_p (TREE_VALUE (t), size_type_node))
+    return false;
+  t = TREE_CHAIN (t);
+  if (t == void_list_node)
+    return true;
+  if (aligned_new_threshhold && t
+      && same_type_p (TREE_VALUE (t), align_type_node)
+      && TREE_CHAIN (t) == void_list_node)
+    return true;
+  return false;
+}
+
+/* True if T, an allocation function, has std::align_val_t as its second
+   argument.  */
+
+bool
+aligned_allocation_fn_p (tree t)
+{
+  if (!aligned_new_threshhold)
+    return false;
+
+  tree a = FUNCTION_ARG_CHAIN (t);
+  return (a && same_type_p (TREE_VALUE (a), align_type_node));
+}
+
+/* Returns true iff T, an element of an OVERLOAD chain, is a usual deallocation
+   function (3.7.4.2 [basic.stc.dynamic.deallocation]) with a parameter of
+   std::align_val_t.  */
+
+static bool
+aligned_deallocation_fn_p (tree t)
+{
+  if (!aligned_new_threshhold)
+    return false;
+
+  /* A template instance is never a usual deallocation function,
+     regardless of its signature.  */
+  if (TREE_CODE (t) == TEMPLATE_DECL
+      || primary_template_instantiation_p (t))
+    return false;
+
+  tree a = FUNCTION_ARG_CHAIN (t);
+  if (same_type_p (TREE_VALUE (a), align_type_node)
+      && TREE_CHAIN (a) == void_list_node)
+    return true;
+  if (!same_type_p (TREE_VALUE (a), size_type_node))
+    return false;
+  a = TREE_CHAIN (a);
+  if (a && same_type_p (TREE_VALUE (a), align_type_node)
+      && TREE_CHAIN (a) == void_list_node)
+    return true;
+  return false;
 }
 
 /* Returns true iff T, an element of an OVERLOAD chain, is a usual
    deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]).  */
 
 bool
-non_placement_deallocation_fn_p (tree t)
+usual_deallocation_fn_p (tree t)
 {
   /* A template instance is never a usual deallocation function,
      regardless of its signature.  */
@@ -5970,10 +6031,15 @@ non_placement_deallocation_fn_p (tree t)
      of which has type std::size_t (18.2), then this function is a usual
      deallocation function.  */
   bool global = DECL_NAMESPACE_SCOPE_P (t);
-  if (FUNCTION_ARG_CHAIN (t) == void_list_node
+  tree chain = FUNCTION_ARG_CHAIN (t);
+  if (!chain)
+    return false;
+  if (chain == void_list_node
       || ((!global || flag_sized_deallocation)
 	  && second_parm_is_size_t (t)))
     return true;
+  if (aligned_deallocation_fn_p (t))
+    return true;
   return false;
 }
 
@@ -6076,7 +6142,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 		 t; t = OVL_NEXT (t))
 	      {
 		tree elt = OVL_CURRENT (t);
-		if (non_placement_deallocation_fn_p (elt)
+		if (usual_deallocation_fn_p (elt)
 		    && FUNCTION_ARG_CHAIN (elt) == void_list_node)
 		  goto ok;
 	      }
@@ -6118,51 +6184,62 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 	 t; t = OVL_NEXT (t))
       {
 	tree elt = OVL_CURRENT (t);
-	if (non_placement_deallocation_fn_p (elt))
+	if (usual_deallocation_fn_p (elt))
 	  {
-	    fn = elt;
-	    /* "If a class T has a member deallocation function named
-	       operator delete with exactly one parameter, then that
-	       function is a usual (non-placement) deallocation
-	       function. If class T does not declare such an operator
-	       delete but does declare a member deallocation 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."
+	    if (!fn)
+	      {
+		fn = elt;
+		continue;
+	      }
 
-	       So in a class (void*) beats (void*, size_t).  */
+	    /* -- If the type has new-extended alignment, a function with a
+	       parameter of type std::align_val_t is preferred; otherwise a
+	       function without such a parameter is preferred. If exactly one
+	       preferred function is found, that function is selected and the
+	       selection process terminates. If more than one preferred
+	       function is found, all non-preferred functions are eliminated
+	       from further consideration.  */
+	    if (aligned_new_threshhold)
+	      {
+		bool want_align = type_has_new_extended_alignment (type);
+		bool fn_align = aligned_deallocation_fn_p (fn);
+		bool elt_align = aligned_deallocation_fn_p (elt);
+
+		if (elt_align != fn_align)
+		  {
+		    if (want_align == elt_align)
+		      fn = elt;
+		    continue;
+		  }
+	      }
+
+	    /* -- If the deallocation functions have class scope, the one
+	       without a parameter of type std::size_t is selected.  */
+	    bool want_size;
 	    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:
+	      want_size = false;
 
-	       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 a parameter of type std::size_t
+	       is selected.
 
-	       * 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. */
+	       -- Otherwise, it is unspecified whether a deallocation function
+	       with a parameter of type std::size_t is selected.  */
 	    else
 	      {
-		bool want_size = COMPLETE_TYPE_P (type);
+		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;
 	      }
+	    bool fn_size = second_parm_is_size_t (fn);
+	    bool elt_size = second_parm_is_size_t (elt);
+	    gcc_assert (fn_size != elt_size);
+	    if (want_size == elt_size)
+	      fn = elt;
 	  }
       }
 
@@ -6200,8 +6277,13 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 	  tree ret;
 	  vec<tree, va_gc> *args = make_tree_vector ();
 	  args->quick_push (addr);
-	  if (FUNCTION_ARG_CHAIN (fn) != void_list_node)
+	  if (second_parm_is_size_t (fn))
 	    args->quick_push (size);
+	  if (aligned_deallocation_fn_p (fn))
+	    {
+	      tree al = build_int_cst (align_type_node, TYPE_ALIGN_UNIT (type));
+	      args->quick_push (al);
+	    }
 	  ret = cp_build_function_call_vec (fn, &args, complain);
 	  release_tree_vector (args);
 	  return ret;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5bcb98b..d4bfb26 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1147,6 +1147,8 @@ enum cp_tree_index
     CPTI_NULLPTR,
     CPTI_NULLPTR_TYPE,
 
+    CPTI_ALIGN_TYPE,
+
     CPTI_MAX
 };
 
@@ -1182,6 +1184,8 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
 #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]
+/* std::align_val_t */
+#define align_type_node			cp_global_trees[CPTI_ALIGN_TYPE]
 
 /* We cache these tree nodes so as to call get_identifier less
    frequently.  */
@@ -5561,7 +5565,7 @@ extern tree build_user_type_conversion		(tree, tree, int,
 extern tree build_new_function_call		(tree, vec<tree, va_gc> **, bool, 
 						 tsubst_flags_t);
 extern tree build_operator_new_call		(tree, vec<tree, va_gc> **, tree *,
-						 tree *, tree, tree *,
+						 tree *, tree, tree, tree *,
 						 tsubst_flags_t);
 extern tree build_new_method_call		(tree, tree, vec<tree, va_gc> **,
 						 tree, int, tree *,
@@ -5573,7 +5577,8 @@ 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 bool aligned_allocation_fn_p		(tree);
+extern bool usual_deallocation_fn_p	(tree);
 extern tree build_op_delete_call		(enum tree_code, tree, tree,
 						 bool, tree, tree,
 						 tsubst_flags_t);
@@ -5966,6 +5971,7 @@ extern tree get_nsdmi				(tree, bool);
 extern tree build_offset_ref			(tree, tree, bool,
 						 tsubst_flags_t);
 extern tree throw_bad_array_new_length		(void);
+extern bool type_has_new_extended_alignment	(tree);
 extern tree build_new				(vec<tree, va_gc> **, tree, tree,
 						 vec<tree, va_gc> **, int,
                                                  tsubst_flags_t);
@@ -6528,6 +6534,7 @@ extern tree build_min_nt_loc			(location_t, enum tree_code,
 extern tree build_min_non_dep			(enum tree_code, tree, ...);
 extern tree build_min_non_dep_op_overload	(enum tree_code, tree, tree, ...);
 extern tree build_min_non_dep_call_vec		(tree, tree, vec<tree, va_gc> *);
+extern vec<tree, va_gc>* vec_copy_and_insert    (vec<tree, va_gc>*, tree, unsigned);
 extern tree build_cplus_new			(tree, tree, tsubst_flags_t);
 extern tree build_aggr_init_expr		(tree, tree);
 extern tree get_target_expr			(tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 43cf3df..9d91387 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4132,6 +4132,17 @@ cxx_init_decl_processing (void)
   /* Now, C++.  */
   current_lang_name = lang_name_cplusplus;
 
+  if (aligned_new_threshhold > 1
+      && exact_log2 (aligned_new_threshhold) == -1)
+    {
+      error ("-faligned-new=%d is not a power of two", aligned_new_threshhold);
+      aligned_new_threshhold = 1;
+    }
+  if (aligned_new_threshhold == -1)
+    aligned_new_threshhold = (cxx_dialect >= cxx1z) ? 1 : 0;
+  if (aligned_new_threshhold == 1)
+    aligned_new_threshhold = max_align_t_align () / BITS_PER_UNIT;
+
   {
     tree newattrs, extvisattr;
     tree newtype, deltype;
@@ -4199,6 +4210,47 @@ cxx_init_decl_processing (void)
 	push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
       }
 
+    if (aligned_new_threshhold)
+      {
+	push_namespace (std_identifier);
+	tree align_id = get_identifier ("align_val_t");
+	align_type_node = start_enum (align_id, NULL_TREE, size_type_node,
+				      NULL_TREE, /*scoped*/true, NULL);
+	pop_namespace ();
+
+	/* operator new (size_t, align_val_t); */
+	newtype = build_function_type_list (ptr_type_node, size_type_node,
+					    align_type_node, NULL_TREE);
+	newtype = cp_build_type_attribute_variant (newtype, newattrs);
+	newtype = build_exception_variant (newtype, new_eh_spec);
+	opnew = push_cp_library_fn (NEW_EXPR, newtype, 0);
+	DECL_IS_MALLOC (opnew) = 1;
+	DECL_IS_OPERATOR_NEW (opnew) = 1;
+	opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
+	DECL_IS_MALLOC (opnew) = 1;
+	DECL_IS_OPERATOR_NEW (opnew) = 1;
+
+	/* operator delete (void *, align_val_t); */
+	deltype = build_function_type_list (void_type_node, ptr_type_node,
+					    align_type_node, NULL_TREE);
+	deltype = cp_build_type_attribute_variant (deltype, 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);
+
+	if (flag_sized_deallocation)
+	  {
+	    /* operator delete (void *, size_t, align_val_t); */
+	    deltype = build_function_type_list (void_type_node, ptr_type_node,
+						size_type_node, align_type_node,
+						NULL_TREE);
+	    deltype = cp_build_type_attribute_variant (deltype, 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));
     TYPE_SIZE_UNIT (nullptr_type_node) = size_int (GET_MODE_SIZE (ptr_mode));
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 2ba5ffb..a320f92 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4488,7 +4488,7 @@ maybe_warn_sized_delete (enum tree_code code)
     {
       tree fn = OVL_CURRENT (ovl);
       /* We're only interested in usual deallocation functions.  */
-      if (!non_placement_deallocation_fn_p (fn))
+      if (!usual_deallocation_fn_p (fn))
 	continue;
       if (FUNCTION_ARG_CHAIN (fn) == void_list_node)
 	unsized = fn;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1a5766a..5bb7f29 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2569,6 +2569,15 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
     }
 }
 
+/* True if alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__.  */
+
+bool
+type_has_new_extended_alignment (tree t)
+{
+  return (aligned_new_threshhold
+	  && TYPE_ALIGN_UNIT (t) > (unsigned)aligned_new_threshhold);
+}
+
 /* Generate code for a new-expression, including calling the "operator
    new" function, initializing the object, and, if an exception occurs
    during construction, cleaning up.  The arguments are as for
@@ -2840,6 +2849,10 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	}
     }
 
+  tree align_arg = NULL_TREE;
+  if (type_has_new_extended_alignment (elt_type))
+    align_arg = build_int_cst (align_type_node, TYPE_ALIGN_UNIT (elt_type));
+
   alloc_fn = NULL_TREE;
 
   /* If PLACEMENT is a single simple pointer type not passed by
@@ -2954,12 +2967,28 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
                 }
 	      return error_mark_node;
 	    }
-	  alloc_call = build_new_method_call (build_dummy_object (elt_type),
-					      fns, placement,
-					      /*conversion_path=*/NULL_TREE,
-					      LOOKUP_NORMAL,
-					      &alloc_fn,
-					      complain);
+	  tree dummy = build_dummy_object (elt_type);
+	  alloc_call = NULL_TREE;
+	  if (align_arg)
+	    {
+	      vec<tree, va_gc> *align_args
+		= vec_copy_and_insert (*placement, align_arg, 1);
+	      alloc_call
+		= build_new_method_call (dummy, fns, &align_args,
+					 /*conversion_path=*/NULL_TREE,
+					 LOOKUP_NORMAL, &alloc_fn, tf_none);
+	      /* If no matching function is found and the allocated object type
+		 has new-extended alignment, the alignment argument is removed
+		 from the argument list, and overload resolution is performed
+		 again.  */
+	      if (alloc_call == error_mark_node)
+		alloc_call = NULL_TREE;
+	    }
+	  if (!alloc_call)
+	    alloc_call = build_new_method_call (dummy, fns, placement,
+						/*conversion_path=*/NULL_TREE,
+						LOOKUP_NORMAL,
+						&alloc_fn, complain);
 	}
       else
 	{
@@ -2976,6 +3005,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 
 	  alloc_call = build_operator_new_call (fnname, placement,
 						&size, &cookie_size,
+						align_arg,
 						outer_nelts_check,
 						&alloc_fn, complain);
 	}
@@ -2986,6 +3016,20 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 
   gcc_assert (alloc_fn != NULL_TREE);
 
+  if (warn_aligned_new
+      && TYPE_ALIGN (elt_type) > max_align_t_align ()
+      && (warn_aligned_new > 1
+	  || CP_DECL_CONTEXT (alloc_fn) == global_namespace)
+      && !aligned_allocation_fn_p (alloc_fn))
+    {
+      warning (OPT_Waligned_new_, "%<new%> of type %qT with extended "
+	       "alignment %d", elt_type, TYPE_ALIGN_UNIT (elt_type));
+      inform (input_location, "uses %qD, which does not have an alignment "
+	      "parameter", alloc_fn);
+      inform (input_location, "use %<-faligned-new%> to enable C++17 "
+	      "over-aligned new support");
+    }
+
   /* If we found a simple case of PLACEMENT_EXPR above, then copy it
      into a temporary variable.  */
   if (!processing_template_decl
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 6d254dd..bd2e8f6 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2920,6 +2920,30 @@ build_min_non_dep_op_overload (enum tree_code op,
   return call;
 }
 
+/* Return a new tree vec copied from VEC, with ELT inserted at index IDX.  */
+
+vec<tree, va_gc> *
+vec_copy_and_insert (vec<tree, va_gc> *old_vec, tree elt, unsigned idx)
+{
+  unsigned len = vec_safe_length (old_vec);
+  gcc_assert (idx <= len);
+
+  vec<tree, va_gc> *new_vec = NULL;
+  vec_alloc (new_vec, len + 1);
+
+  unsigned i;
+  for (i = 0; i < len; ++i)
+    {
+      if (i == idx)
+	new_vec->quick_push (elt);
+      new_vec->quick_push ((*old_vec)[i]);
+    }
+  if (i == idx)
+    new_vec->quick_push (elt);
+
+  return new_vec;
+}
+
 tree
 get_type_decl (tree t)
 {
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 20be9b7..b2eaea7 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -190,7 +190,7 @@ in the following sections.
 @item C++ Language Options
 @xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
 @gccoptlist{-fabi-version=@var{n}  -fno-access-control @gol
--fargs-in-order=@var{n} -fcheck-new @gol
+-faligned-new=@var{n} -fargs-in-order=@var{n} -fcheck-new @gol
 -fconstexpr-depth=@var{n} -fconstexpr-loop-limit=@var{n} @gol
 -ffriend-injection @gol
 -fno-elide-constructors @gol
@@ -2237,6 +2237,15 @@ option is used for the warning.
 Turn off all access checking.  This switch is mainly useful for working
 around bugs in the access control code.
 
+@item -faligned-new
+@opindex faligned-new
+Enable support for C++17 @code{new} of types that require more
+alignment than @code{void* ::operator new(std::size_t)} provides.  A
+numeric argument such as @code{-faligned-new=32} can be used to
+specify how much alignment (in bytes) is provided by that function,
+but few users will need to override the default of
+@code{alignof(std::max_align_t)}.
+
 @item -fcheck-new
 @opindex fcheck-new
 Check that the pointer returned by @code{operator new} is non-null
@@ -5062,6 +5071,18 @@ disables the warnings about non-ISO @code{printf} / @code{scanf} format
 width specifiers @code{I32}, @code{I64}, and @code{I} used on Windows targets,
 which depend on the MS runtime.
 
+@item -Waligned-new
+@opindex Waligned-new
+@opindex Wno-aligned-new
+Warn about a new-expression of a type that requires greater alignment
+than the @code{alignof(std::max_align_t)} but uses an allocation
+function without an explicit alignment parameter. This option is
+enabled by @option{-Wall}.
+
+Normally this only warns about global allocation functions, but
+@option{-Waligned-new=all} also warns about class member allocation
+functions.
+
 @item -Wplacement-new
 @itemx -Wplacement-new=@var{n}
 @opindex Wplacement-new
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
index dd9011b..b0a1e86 100644
--- a/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
@@ -5,4 +5,4 @@
 #include <new>
 __attribute__((visibility("hidden")))void*operator new(std::size_t); // { dg-warning "visibility attribute ignored" }
 
-// { dg-message "previous declaration" "" { target *-*-* } 116 }
+// { dg-message "previous declaration" "" { target *-*-* } 120 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/aligned-new1.C b/gcc/testsuite/g++.dg/cpp1z/aligned-new1.C
new file mode 100644
index 0000000..735296f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new1.C
@@ -0,0 +1,17 @@
+// { dg-options -std=c++1z }
+// { dg-do run }
+
+#ifndef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+#error __STDCPP_DEFAULT_NEW_ALIGNMENT__ not defined
+#endif
+
+#include <cstdint>
+
+struct alignas(64) A { int i; };
+
+int main()
+{
+  A *p = new A;
+  if (std::intptr_t(p) % 64 != 0)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/aligned-new2.C b/gcc/testsuite/g++.dg/cpp1z/aligned-new2.C
new file mode 100644
index 0000000..fe15969
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new2.C
@@ -0,0 +1,31 @@
+// { dg-options -std=c++1z }
+// { dg-do run }
+
+#include <new>
+
+struct alignas(64) A {
+  int i;
+  A() { throw 42; }
+};
+struct B { int i; } b;
+
+void *operator new (std::size_t s, std::align_val_t a, B b)
+{
+  return operator new (s, a);
+}
+
+bool deleted = false;
+void operator delete (void *p, std::align_val_t, B)
+{
+  deleted = true;
+}
+
+int main()
+{
+  try {
+    A *p = new (b) A;
+    __builtin_abort ();
+  } catch (...) {}
+  if (!deleted)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C b/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C
new file mode 100644
index 0000000..73e3343
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C
@@ -0,0 +1,23 @@
+// { dg-options -std=c++1z }
+// { dg-do run }
+
+#include <new>
+
+struct alignas(64) A {
+  int i;
+};
+
+bool deleted = false;
+void operator delete (void *p, std::size_t, std::align_val_t)
+{
+  deleted = true;
+  operator delete (p);
+}
+
+int main()
+{
+  A *p = new A;
+  delete p;
+  if (!deleted)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/aligned-new4.C b/gcc/testsuite/g++.dg/cpp1z/aligned-new4.C
new file mode 100644
index 0000000..cc63a14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new4.C
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++14 -Waligned-new" }
+
+struct alignas(64) A { int i; };
+struct alignas(64) B {
+  int i;
+  void *operator new(__SIZE_TYPE__);
+};
+
+int main()
+{
+  A* ap = new A;		// { dg-warning "-Waligned-new" }
+  B* bp = new B;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/aligned-new4a.C b/gcc/testsuite/g++.dg/cpp1z/aligned-new4a.C
new file mode 100644
index 0000000..eb178d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new4a.C
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++14 -Waligned-new=all" }
+
+struct alignas(64) A { int i; };
+struct alignas(64) B {
+  int i;
+  void *operator new(__SIZE_TYPE__);
+};
+
+int main()
+{
+  A* ap = new A;		// { dg-warning "-Waligned-new" }
+  B* bp = new B;		// { dg-warning "-Waligned-new" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/aligned-new5.C b/gcc/testsuite/g++.dg/cpp1z/aligned-new5.C
new file mode 100644
index 0000000..525129e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new5.C
@@ -0,0 +1,14 @@
+// { dg-options -faligned-new }
+// { dg-do run }
+
+#include <new>
+#include <stdint.h>
+
+struct A { int i; };
+
+int main()
+{
+  A* ap = new (std::align_val_t(64)) A;
+  if (intptr_t(ap) % 64 != 0)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C b/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
index 41b6111..982572e 100644
--- a/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
+++ b/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
@@ -350,6 +350,12 @@
 #  error "__cpp_if_constexpr != 201606"
 #endif
 
+#ifndef __cpp_aligned_new
+#  error "__cpp_aligned_new"
+#elif __cpp_aligned_new != 201606
+#  error "__cpp_aligned_new != 201606"
+#endif
+
 #ifdef __has_cpp_attribute
 
 #  if ! __has_cpp_attribute(maybe_unused)
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 5ac2df4..2ab6e0d 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -6,6 +6,9 @@
 /* Define to 1 if you have the `acosl' function. */
 #undef HAVE_ACOSL
 
+/* Define to 1 if you have the `aligned_alloc' function. */
+#undef HAVE_ALIGNED_ALLOC
+
 /* Define to 1 if you have the `asinf' function. */
 #undef HAVE_ASINF
 
@@ -285,6 +288,9 @@
 /* Define if mbstate_t exists in wchar.h. */
 #undef HAVE_MBSTATE_T
 
+/* Define to 1 if you have the `memalign' function. */
+#undef HAVE_MEMALIGN
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -309,6 +315,9 @@
 /* Define if poll is available in <poll.h>. */
 #undef HAVE_POLL
 
+/* Define to 1 if you have the `posix_memalign' function. */
+#undef HAVE_POSIX_MEMALIGN
+
 /* Define to 1 if you have the `powf' function. */
 #undef HAVE_POWF
 
@@ -505,6 +514,9 @@
 /* Define to 1 if you have the `_acosl' function. */
 #undef HAVE__ACOSL
 
+/* Define to 1 if you have the `_aligned_malloc' function. */
+#undef HAVE__ALIGNED_MALLOC
+
 /* Define to 1 if you have the `_asinf' function. */
 #undef HAVE__ASINF
 
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 0ab4bb1..9b5bb23 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2197,6 +2197,18 @@ CXXABI_1.3.11 {
     __cxa_init_primary_exception;
     _ZNSt15__exception_ptr13exception_ptrC1EPv;
 
+    # C++17 aligned new/delete
+    _ZnwmSt11align_val_t;
+    _ZnwmSt11align_val_tRKSt9nothrow_t;
+    _ZnamSt11align_val_t;
+    _ZnamSt11align_val_tRKSt9nothrow_t;
+    _ZdlPvSt11align_val_t;
+    _ZdlPvSt11align_val_tRKSt9nothrow_t;
+    _ZdlPvmSt11align_val_t;
+    _ZdaPvSt11align_val_t;
+    _ZdaPvSt11align_val_tRKSt9nothrow_t;
+    _ZdaPvmSt11align_val_t;
+
 } CXXABI_1.3.10;
 
 # Symbols in the support library (libsupc++) supporting transactional memory.
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index bfcb465..6332c4d 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -27972,6 +27972,19 @@ _ACEOF
 fi
 done
 
+  for ac_func in aligned_alloc posix_memalign memalign _aligned_malloc
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
 
   # For iconv support.
 
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index 9e19e99..5657ecb 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -256,6 +256,7 @@ if $GLIBCXX_IS_NATIVE; then
   GCC_CHECK_TLS
 
   AC_CHECK_FUNCS(__cxa_thread_atexit_impl)
+  AC_CHECK_FUNCS(aligned_alloc posix_memalign memalign _aligned_malloc)
 
   # For iconv support.
   AM_ICONV
diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am
index ba4eac1..2df31ff 100644
--- a/libstdc++-v3/libsupc++/Makefile.am
+++ b/libstdc++-v3/libsupc++/Makefile.am
@@ -88,6 +88,16 @@ sources = \
 	new_opnt.cc \
 	new_opv.cc \
 	new_opvnt.cc \
+	new_opa.cc \
+	new_opant.cc \
+	new_opva.cc \
+	new_opvant.cc \
+	del_opa.cc \
+	del_opant.cc \
+	del_opsa.cc \
+	del_opva.cc \
+	del_opvant.cc \
+	del_opvsa.cc \
 	pbase_type_info.cc \
 	pmem_type_info.cc \
 	pointer_type_info.cc \
@@ -189,6 +199,28 @@ del_opvs.lo: del_opvs.cc
 del_opvs.o: del_opvs.cc
 	$(CXXCOMPILE) -std=gnu++14 -Wno-sized-deallocation -c $<
 
+# Use special rules for the C++17 sources so that the proper flags are passed.
+new_opa.lo: new_opa.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+new_opant.lo: new_opant.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+new_opva.lo: new_opva.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+new_opvant.lo: new_opvant.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opa.lo: del_opa.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opant.lo: del_opant.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opsa.lo: del_opsa.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opva.lo: del_opva.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opvant.lo: del_opvant.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opvsa.lo: del_opvsa.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+
 # AM_CXXFLAGS needs to be in each subdirectory so that it can be
 # modified in a per-library or per-sub-library way.  Need to manually
 # set this option because CONFIG_CXXFLAGS has to be after
diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
index 3fb9d16..e828ed9 100644
--- a/libstdc++-v3/libsupc++/Makefile.in
+++ b/libstdc++-v3/libsupc++/Makefile.in
@@ -125,9 +125,11 @@ am__objects_1 = array_type_info.lo atexit_arm.lo atexit_thread.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
+	new_opa.lo new_opant.lo new_opva.lo new_opvant.lo del_opa.lo \
+	del_opant.lo del_opsa.lo del_opva.lo del_opvant.lo \
+	del_opvsa.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@@VTV_CYGMIN_FALSE@am__objects_3 =  \
 @ENABLE_VTABLE_VERIFY_TRUE@@VTV_CYGMIN_FALSE@	vtv_stubs.lo
@@ -445,6 +447,16 @@ sources = \
 	new_opnt.cc \
 	new_opv.cc \
 	new_opvnt.cc \
+	new_opa.cc \
+	new_opant.cc \
+	new_opva.cc \
+	new_opvant.cc \
+	del_opa.cc \
+	del_opant.cc \
+	del_opsa.cc \
+	del_opva.cc \
+	del_opvant.cc \
+	del_opvsa.cc \
 	pbase_type_info.cc \
 	pmem_type_info.cc \
 	pointer_type_info.cc \
@@ -916,6 +928,28 @@ del_opvs.lo: del_opvs.cc
 del_opvs.o: del_opvs.cc
 	$(CXXCOMPILE) -std=gnu++14 -Wno-sized-deallocation -c $<
 
+# Use special rules for the C++17 sources so that the proper flags are passed.
+new_opa.lo: new_opa.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+new_opant.lo: new_opant.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+new_opva.lo: new_opva.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+new_opvant.lo: new_opvant.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opa.lo: del_opa.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opant.lo: del_opant.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opsa.lo: del_opsa.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opva.lo: del_opva.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opvant.lo: del_opvant.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+del_opvsa.lo: del_opvsa.cc
+	$(LTCXXCOMPILE) -std=gnu++1z -c $<
+
 install-stdHEADERS: $(std_HEADERS)
 	@$(NORMAL_INSTALL)
 	$(mkinstalldirs) $(DESTDIR)$(stddir)
diff --git a/libstdc++-v3/libsupc++/del_opa.cc b/libstdc++-v3/libsupc++/del_opa.cc
new file mode 100644
index 0000000..889bdb7
--- /dev/null
+++ b/libstdc++-v3/libsupc++/del_opa.cc
@@ -0,0 +1,54 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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>
+
+#if !_GLIBCXX_HOSTED
+// A freestanding C runtime may not provide "free" -- but there is no
+// other reasonable way to implement "operator delete".
+namespace std
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  extern "C" void free(void*);
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#else
+# include <cstdlib>
+#endif
+
+#include "new"
+
+// The sized deletes are defined in other files.
+#pragma GCC diagnostic ignored "-Wsized-deallocation"
+
+_GLIBCXX_WEAK_DEFINITION void
+operator delete(void* ptr, std::align_val_t) _GLIBCXX_USE_NOEXCEPT
+{
+#if !_GLIBCXX_HAVE_ALIGNED_ALLOC && _GLIBCXX_HAVE__ALIGNED_MALLOC
+  _aligned_free (ptr);
+#else
+  std::free(ptr);
+#endif
+}
diff --git a/libstdc++-v3/libsupc++/del_opant.cc b/libstdc++-v3/libsupc++/del_opant.cc
new file mode 100644
index 0000000..1b1919c
--- /dev/null
+++ b/libstdc++-v3/libsupc++/del_opant.cc
@@ -0,0 +1,33 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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::align_val_t al, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+{
+  ::operator delete (ptr, al);
+}
diff --git a/libstdc++-v3/libsupc++/del_opsa.cc b/libstdc++-v3/libsupc++/del_opsa.cc
new file mode 100644
index 0000000..7880efe
--- /dev/null
+++ b/libstdc++-v3/libsupc++/del_opsa.cc
@@ -0,0 +1,33 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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, std::align_val_t al) _GLIBCXX_USE_NOEXCEPT
+{
+  ::operator delete (ptr, al);
+}
diff --git a/libstdc++-v3/libsupc++/del_opva.cc b/libstdc++-v3/libsupc++/del_opva.cc
new file mode 100644
index 0000000..95d2a3f
--- /dev/null
+++ b/libstdc++-v3/libsupc++/del_opva.cc
@@ -0,0 +1,36 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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"
+
+// The sized deletes are defined in other files.
+#pragma GCC diagnostic ignored "-Wsized-deallocation"
+
+_GLIBCXX_WEAK_DEFINITION void
+operator delete[] (void *ptr, std::align_val_t al) _GLIBCXX_USE_NOEXCEPT
+{
+  ::operator delete (ptr, al);
+}
diff --git a/libstdc++-v3/libsupc++/del_opvant.cc b/libstdc++-v3/libsupc++/del_opvant.cc
new file mode 100644
index 0000000..5840c8f
--- /dev/null
+++ b/libstdc++-v3/libsupc++/del_opvant.cc
@@ -0,0 +1,33 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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::align_val_t al, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+{
+  ::operator delete[] (ptr, al);
+}
diff --git a/libstdc++-v3/libsupc++/del_opvsa.cc b/libstdc++-v3/libsupc++/del_opvsa.cc
new file mode 100644
index 0000000..61586b0
--- /dev/null
+++ b/libstdc++-v3/libsupc++/del_opvsa.cc
@@ -0,0 +1,33 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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, std::align_val_t al) _GLIBCXX_USE_NOEXCEPT
+{
+  ::operator delete[] (ptr, al);
+}
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 8e8a327..477fadc 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -79,6 +79,10 @@ namespace std
   };
 #endif
 
+#if __cpp_aligned_new
+  enum class align_val_t: size_t {};
+#endif
+
   struct nothrow_t
   {
 #if __cplusplus >= 201103L
@@ -135,6 +139,30 @@ void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
   __attribute__((__externally_visible__));
 void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
   __attribute__((__externally_visible__));
+#if __cpp_aligned_new
+void* operator new(std::size_t, std::align_val_t)
+  __attribute__((__externally_visible__));
+void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&)
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
+void operator delete(void*, std::align_val_t)
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
+void operator delete(void*, std::align_val_t, const std::nothrow_t&)
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
+void* operator new[](std::size_t, std::align_val_t)
+  __attribute__((__externally_visible__));
+void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&)
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
+void operator delete[](void*, std::align_val_t)
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
+void operator delete[](void*, std::align_val_t, const std::nothrow_t&)
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
+#if __cpp_sized_deallocation
+void operator delete(void*, std::size_t, std::align_val_t)
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
+void operator delete[](void*, std::size_t, std::align_val_t)
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
+#endif // __cpp_sized_deallocation
+#endif // __cpp_aligned_new
 
 // Default placement versions of operator new.
 inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
diff --git a/libstdc++-v3/libsupc++/new_opa.cc b/libstdc++-v3/libsupc++/new_opa.cc
new file mode 100644
index 0000000..6ff5421
--- /dev/null
+++ b/libstdc++-v3/libsupc++/new_opa.cc
@@ -0,0 +1,76 @@
+// Support routines for the -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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 <stdlib.h>
+#include <bits/exception_defines.h>
+#include "new"
+
+using std::new_handler;
+using std::bad_alloc;
+
+#if !_GLIBCXX_HAVE_ALIGNED_ALLOC
+#if _GLIBCXX_HAVE__ALIGNED_MALLOC
+#define aligned_alloc(al,sz) _aligned_malloc(sz,al)
+#elif _GLIBCXX_HAVE_POSIX_MEMALIGN
+static inline void*
+aligned_alloc (std::size_t al, std::size_t sz)
+{
+  void *ptr;
+  int ret = posix_memalign (&ptr, al, sz);
+  if (ret == 0)
+    return ptr;
+  return nullptr;
+}
+#elif _GLIBCXX_HAVE_MEMALIGN
+#include <malloc.h>
+#define aligned_alloc memalign
+#else
+// The C library doesn't provide any aligned allocation functions, declare
+// aligned_alloc and get a link failure if aligned new is used.
+extern "C" void *aligned_alloc(std::size_t, std::size_t);
+#endif
+#endif
+
+_GLIBCXX_WEAK_DEFINITION void *
+operator new (std::size_t sz, std::align_val_t al)
+{
+  void *p;
+
+  /* malloc (0) is unpredictable; avoid it.  */
+  if (sz == 0)
+    sz = 1;
+
+  while (__builtin_expect ((p = aligned_alloc ((std::size_t)al, sz)) == 0,
+			   false))
+    {
+      new_handler handler = std::get_new_handler ();
+      if (! handler)
+	_GLIBCXX_THROW_OR_ABORT(bad_alloc());
+      handler ();
+    }
+
+  return p;
+}
diff --git a/libstdc++-v3/libsupc++/new_opant.cc b/libstdc++-v3/libsupc++/new_opant.cc
new file mode 100644
index 0000000..c863d64
--- /dev/null
+++ b/libstdc++-v3/libsupc++/new_opant.cc
@@ -0,0 +1,41 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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 new(std::size_t sz, std::align_val_t al, const std::nothrow_t&)
+  _GLIBCXX_USE_NOEXCEPT
+{
+  __try
+    {
+      return operator new(sz, al);
+    }
+  __catch(...)
+    {
+      return 0;
+    }
+}
diff --git a/libstdc++-v3/libsupc++/new_opva.cc b/libstdc++-v3/libsupc++/new_opva.cc
new file mode 100644
index 0000000..7109431
--- /dev/null
+++ b/libstdc++-v3/libsupc++/new_opva.cc
@@ -0,0 +1,33 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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 new[] (std::size_t sz, std::align_val_t al)
+{
+  return ::operator new(sz, al);
+}
diff --git a/libstdc++-v3/libsupc++/new_opvant.cc b/libstdc++-v3/libsupc++/new_opvant.cc
new file mode 100644
index 0000000..a32fec8
--- /dev/null
+++ b/libstdc++-v3/libsupc++/new_opvant.cc
@@ -0,0 +1,41 @@
+// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+
+// Copyright (C) 1997-2016 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 new[] (std::size_t sz, std::align_val_t al, const std::nothrow_t&)
+  _GLIBCXX_USE_NOEXCEPT
+{
+  __try
+    {
+      return ::operator new[](sz, al);
+    }
+  __catch(...)
+    {
+      return 0;
+    }
+}


More information about the Gcc-patches mailing list