Implement P0035R4, C++17 new of over-aligned types.
authorJason Merrill <jason@redhat.com>
Fri, 9 Sep 2016 21:22:15 +0000 (17:22 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 9 Sep 2016 21:22:15 +0000 (17:22 -0400)
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.

From-SVN: r240056

39 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c-cppbuiltin.c
gcc/c-family/c.opt
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/tree.c
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
gcc/testsuite/g++.dg/cpp1z/aligned-new1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/aligned-new2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/aligned-new3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/aligned-new4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/aligned-new4a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/aligned-new5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
libstdc++-v3/ChangeLog
libstdc++-v3/config.h.in
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/configure
libstdc++-v3/configure.ac
libstdc++-v3/libsupc++/Makefile.am
libstdc++-v3/libsupc++/Makefile.in
libstdc++-v3/libsupc++/del_opa.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/del_opant.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/del_opsa.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/del_opva.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/del_opvant.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/del_opvsa.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/new
libstdc++-v3/libsupc++/new_opa.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/new_opant.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/new_opva.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/new_opvant.cc [new file with mode: 0644]

index 331be699edb4424b29689dc380a4d330542eb8a0..ba892487aa8657185bd4d191f39f9c65319f1111 100644 (file)
@@ -1,3 +1,12 @@
+2016-09-09  Jason Merrill  <jason@redhat.com>
+
+       Implement C++17 new of over-aligned types.
+       * 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.
+
 2016-09-09  Joseph Myers  <joseph@codesourcery.com>
 
        * c-cppbuiltin.c (builtin_define_type_width): New function.
index 656f639767db5e5d4b75af20f8f122949a368a77..9a66cfeb297a58661319b862460ae52ead12421f 100644 (file)
@@ -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.  */
index 1d923c90de41aeb3d5308393278c4b6f049fdd1b..2e211c491a52d891eb78a38da9574c4d090f4517 100644 (file)
@@ -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);
index 33382766a974afb1087ddb121da2bd98304ef492..bb30829c9871984d2de98d60f6454cee0919004d 100644 (file)
@@ -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.  */
index a5358ededb30119e3922fb99e44f16dd6f2b1590..c55c7c34961044b0c79f39691bb9402b56e44181 100644 (file)
@@ -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)
 
index a3f51bb55090dd8538d5047c8ae02fa1a583b476..94809939c6384d73d33856103ebb6883cb66b03a 100644 (file)
@@ -1,3 +1,18 @@
+2016-09-09  Jason Merrill  <jason@redhat.com>
+
+       Implement P0035R4, C++17 new of over-aligned types.
+       * 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.
+
 2016-09-02  Jakub Jelinek  <jakub@redhat.com>
 
        PR sanitizer/77396
index 024519d36011a85490d0309d9422aaf8fac0c77a..167d77810c8b451a44e938485580056c43a9ccc6 100644 (file)
@@ -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."
-
-              So in a class (void*) beats (void*, size_t).  */
-           if (DECL_CLASS_SCOPE_P (fn))
+           if (!fn)
              {
-               if (FUNCTION_ARG_CHAIN (fn) == void_list_node)
-                 break;
+               fn = elt;
+               continue;
              }
-           /* 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. */
+
+           /* -- 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))
+             want_size = false;
+
+           /* -- 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.
+
+              -- 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;
index 5bcb98b97561b4607defa3b4863a9d36c6a7d476..d4bfb26d1e390252fe46edca17b0497099bd2fc9 100644 (file)
@@ -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);
index 43cf3df36bac33dc7f1d5529dc098aba7338c190..9d91387c7f1b91ce378efe7d189c31272ec75929 100644 (file)
@@ -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));
index 2ba5ffb31dca4ebd015b9dc5d49e537d2dc00736..a320f92d402b15b2dd61fb5495c733f210848b37 100644 (file)
@@ -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;
index 1a5766a42b7734fe3ea493cdc0500c63eac466e7..5bb7f2911179d4638a0ffd15e19bd8f76f6fa738 100644 (file)
@@ -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
index 6d254ddbf14600b6c94310f5a4a03d17b3a71712..bd2e8f667390780abf53760cc9e4b1365f242fd8 100644 (file)
@@ -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)
 {
index 20be9b747510efc3c338068ccae1698832a536df..b2eaea7c15d2bc1b216fe5f38ea7a51554270960 100644 (file)
@@ -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
index dd9011b887025318249797408e176421554c7aae..b0a1e864effc3ffb1191ec74343b029b7b6e629c 100644 (file)
@@ -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 (file)
index 0000000..735296f
--- /dev/null
@@ -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 (file)
index 0000000..fe15969
--- /dev/null
@@ -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 (file)
index 0000000..73e3343
--- /dev/null
@@ -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 (file)
index 0000000..cc63a14
--- /dev/null
@@ -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 (file)
index 0000000..eb178d4
--- /dev/null
@@ -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 (file)
index 0000000..525129e
--- /dev/null
@@ -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();
+}
index 41b6111453752302db0160fda1f8886f74a91834..982572e65cc500310f012cdeafc60149b37e0153 100644 (file)
 #  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)
index 517db5662f7034ef5079a59334b68b9f25c50ec8..4ba6593664bfafde0eabc435f8ad042411905d58 100644 (file)
@@ -1,3 +1,22 @@
+2016-09-09  Jason Merrill  <jason@redhat.com>
+
+       Implement P0035R4, C++17 new of over-aligned types.
+       * 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.
+
 2016-09-05  Tim Shen  <timshen@google.com>
 
        * include/std/variant: include bits/move.h for std::addressof.
index 5ac2df4d8a840e26ea5b9ca1baedd69ab1d72a8b..2ab6e0d6a49a14c4900a495e89aeb5241b267cf9 100644 (file)
@@ -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
 
 /* 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
 
 /* 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
 
 /* 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
 
index 0ab4bb10b35293f5a42513a1b08b4587919f1da9..9b5bb238b7ed3475fe2c860be51df26432c46a78 100644 (file)
@@ -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.
index bfcb465f29962076c105ba4d85add04c6a2ca9c4..6332c4d7f87a959002fbf8b5728c64031681e977 100755 (executable)
@@ -27969,6 +27969,19 @@ if test "x$ac_cv_func___cxa_thread_atexit_impl" = x""yes; then :
 #define HAVE___CXA_THREAD_ATEXIT_IMPL 1
 _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
 
index 9e19e9927fd1b56e24199189cc8e4df505855b73..5657ecb27dc505ce4ec514611596751a480d9a7f 100644 (file)
@@ -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
index ba4eac1e3f86670f15defa509a65c5f76316d7f3..2df31ff668ef8e1b31198edfb6723a42ea9b196c 100644 (file)
@@ -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
index 3fb9d16e527ff046a89d6c8730981a2b5b47b12d..e828ed909cae06e4455644db825742439fdda5fa 100644 (file)
@@ -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 (file)
index 0000000..889bdb7
--- /dev/null
@@ -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 (file)
index 0000000..1b1919c
--- /dev/null
@@ -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 (file)
index 0000000..7880efe
--- /dev/null
@@ -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 (file)
index 0000000..95d2a3f
--- /dev/null
@@ -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 (file)
index 0000000..5840c8f
--- /dev/null
@@ -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 (file)
index 0000000..61586b0
--- /dev/null
@@ -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);
+}
index 8e8a3272a8d43d7c0dc66ae3d95a9a0bd50cc5af..477fadc218cb4d8d620bee2be10a617d7431a341 100644 (file)
@@ -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 (file)
index 0000000..6ff5421
--- /dev/null
@@ -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 (file)
index 0000000..c863d64
--- /dev/null
@@ -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 (file)
index 0000000..7109431
--- /dev/null
@@ -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 (file)
index 0000000..a32fec8
--- /dev/null
@@ -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;
+    }
+}