From: Jason Merrill Date: Fri, 9 Sep 2016 21:22:15 +0000 (-0400) Subject: Implement P0035R4, C++17 new of over-aligned types. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=af63ba4b309ea3ff8946be59e8dba7333594f4ff;p=gcc.git 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. From-SVN: r240056 --- diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 331be699edb..ba892487aa8 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2016-09-09 Jason Merrill + + 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 * c-cppbuiltin.c (builtin_define_type_width): New function. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 656f639767d..9a66cfeb297 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 1d923c90de4..2e211c491a5 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 33382766a97..bb30829c987 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 a5358ededb3..c55c7c34961 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= 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/ChangeLog b/gcc/cp/ChangeLog index a3f51bb5509..94809939c63 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2016-09-09 Jason Merrill + + 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 PR sanitizer/77396 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 024519d3601..167d77810c8 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4211,13 +4211,14 @@ build_new_function_call (tree fn, vec **args, bool koenig_p, tree build_operator_new_call (tree fnname, vec **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 **args, we disregard block-scope declarations of "operator new". */ fns = lookup_function_nonclass (fnname, *args, /*block_p=*/false); + if (align_arg) + { + vec* 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 *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 5bcb98b9756..d4bfb26d1e3 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 **, bool, tsubst_flags_t); extern tree build_operator_new_call (tree, vec **, tree *, - tree *, tree, tree *, + tree *, tree, tree, tree *, tsubst_flags_t); extern tree build_new_method_call (tree, tree, vec **, 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 **, 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, tree, vec **, 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 *); +extern vec* vec_copy_and_insert (vec*, 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 43cf3df36ba..9d91387c7f1 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 2ba5ffb31dc..a320f92d402 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 1a5766a42b7..5bb7f291117 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 **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 **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 *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 **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 **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_, "% 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 6d254ddbf14..bd2e8f66739 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 * +vec_copy_and_insert (vec *old_vec, tree elt, unsigned idx) +{ + unsigned len = vec_safe_length (old_vec); + gcc_assert (idx <= len); + + vec *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 20be9b74751..b2eaea7c15d 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 dd9011b8870..b0a1e864eff 100644 --- a/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C +++ b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C @@ -5,4 +5,4 @@ #include __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 00000000000..735296fd8fa --- /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 + +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 00000000000..fe159692b3b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new2.C @@ -0,0 +1,31 @@ +// { dg-options -std=c++1z } +// { dg-do run } + +#include + +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 00000000000..73e33432542 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C @@ -0,0 +1,23 @@ +// { dg-options -std=c++1z } +// { dg-do run } + +#include + +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 00000000000..cc63a145589 --- /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 00000000000..eb178d46dff --- /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 00000000000..525129e4c40 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new5.C @@ -0,0 +1,14 @@ +// { dg-options -faligned-new } +// { dg-do run } + +#include +#include + +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 41b61114537..982572e65cc 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/ChangeLog b/libstdc++-v3/ChangeLog index 517db5662f7..4ba6593664b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2016-09-09 Jason Merrill + + 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 * include/std/variant: include bits/move.h for std::addressof. diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 5ac2df4d8a8..2ab6e0d6a49 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 header file. */ #undef HAVE_MEMORY_H @@ -309,6 +315,9 @@ /* Define if poll is available in . */ #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 0ab4bb10b35..9b5bb238b7e 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 bfcb465f299..6332c4d7f87 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -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 diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index 9e19e9927fd..5657ecb27dc 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 ba4eac1e3f8..2df31ff668e 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 3fb9d16e527..e828ed909ca 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 00000000000..889bdb71935 --- /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 +// . + +#include + +#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 +#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 00000000000..1b1919ce927 --- /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 +// . + +#include +#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 00000000000..7880efeb279 --- /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 +// . + +#include +#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 00000000000..95d2a3f8d24 --- /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 +// . + +#include +#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 00000000000..5840c8f70e0 --- /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 +// . + +#include +#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 00000000000..61586b06e11 --- /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 +// . + +#include +#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 8e8a3272a8d..477fadc218c 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 00000000000..6ff5421bd15 --- /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 +// . + +#include +#include +#include +#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 +#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 00000000000..c863d64f2d4 --- /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 +// . + +#include +#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 00000000000..7109431b269 --- /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 +// . + +#include +#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 00000000000..a32fec8432a --- /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 +// . + +#include +#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; + } +}