X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcp%2Finit.c;h=561477ace5787f8182a93af7d944079f435e246a;hb=c2b3ec18a494e33e5b3d4704adea633de728dd26;hp=9115df3dba692e6da7729bd0df6eab2a52e1ebf9;hpb=d2e312d7e54bb6d2c5b6446991a90548edb62d67;p=gcc.git diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 9115df3dba6..561477ace57 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1,7 +1,7 @@ /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + 2011, 2012 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -29,7 +29,6 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "cp-tree.h" #include "flags.h" -#include "output.h" #include "target.h" static bool begin_init_stmts (tree *, tree *); @@ -140,7 +139,9 @@ initialize_vtbl_ptrs (tree addr) zero-initialization does not simply mean filling the storage with zero bytes. FIELD_SIZE, if non-NULL, is the bit size of the field, subfields with bit positions at or above that bit size shouldn't - be added. */ + be added. Note that this only works when the result is assigned + to a base COMPONENT_REF; if we only have a pointer to the base subobject, + expand_assignment will end up clearing the full size of TYPE. */ static tree build_zero_init_1 (tree type, tree nelts, bool static_storage_p, @@ -176,6 +177,8 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p, items with static storage duration that are not otherwise initialized are initialized to zero. */ ; + else if (TYPE_PTR_OR_PTRMEM_P (type)) + init = convert (type, nullptr_node); else if (SCALAR_TYPE_P (type)) init = convert (type, integer_zero_node); else if (CLASS_TYPE_P (type)) @@ -331,7 +334,8 @@ build_value_init (tree type, tsubst_flags_t complain) constructor. */ /* The AGGR_INIT_EXPR tweaking below breaks in templates. */ - gcc_assert (!processing_template_decl || SCALAR_TYPE_P (type)); + gcc_assert (!processing_template_decl + || (SCALAR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)); if (CLASS_TYPE_P (type)) { @@ -357,11 +361,9 @@ build_value_init (tree type, tsubst_flags_t complain) tree ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, NULL, type, LOOKUP_NORMAL, complain); + ctor = build_aggr_init_expr (type, ctor, complain); if (ctor != error_mark_node) - { - ctor = build_aggr_init_expr (type, ctor, complain); - AGGR_INIT_ZERO_FIRST (ctor) = 1; - } + AGGR_INIT_ZERO_FIRST (ctor) = 1; return ctor; } } @@ -374,6 +376,12 @@ build_value_init (tree type, tsubst_flags_t complain) tree build_value_init_noctor (tree type, tsubst_flags_t complain) { + if (!COMPLETE_TYPE_P (type)) + { + if (complain & tf_error) + error ("value-initialization of incomplete type %qT", type); + return error_mark_node; + } /* FIXME the class and array cases should just use digest_init once it is SFINAE-enabled. */ if (CLASS_TYPE_P (type)) @@ -483,6 +491,30 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); } +/* Initialize current class with INIT, a TREE_LIST of + arguments for a target constructor. If TREE_LIST is void_type_node, + an empty initializer list was given. */ + +static void +perform_target_ctor (tree init) +{ + tree decl = current_class_ref; + tree type = current_class_type; + + finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL, + tf_warning_or_error)); + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + { + tree expr = build_delete (type, decl, sfk_complete_destructor, + LOOKUP_NORMAL + |LOOKUP_NONVIRTUAL + |LOOKUP_DESTRUCTOR, + 0, tf_warning_or_error); + if (expr != error_mark_node) + finish_eh_cleanup (expr); + } +} + /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of arguments. If TREE_LIST is void_type_node, an empty initializer list was given; if NULL_TREE no initializer was given. */ @@ -505,9 +537,26 @@ perform_member_init (tree member, tree init) tf_warning_or_error, member, /*function_p=*/false, /*integral_constant_expression_p=*/false)); else - init = break_out_target_exprs (DECL_INITIAL (member)); + { + init = DECL_INITIAL (member); + if (init && TREE_CODE (init) == DEFAULT_ARG) + { + error ("constructor required before non-static data member " + "for %qD has been parsed", member); + init = NULL_TREE; + } + /* Strip redundant TARGET_EXPR so we don't need to remap it, and + so the aggregate init code below will see a CONSTRUCTOR. */ + if (init && TREE_CODE (init) == TARGET_EXPR + && !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (init)))) + init = TARGET_EXPR_INITIAL (init); + init = break_out_target_exprs (init); + } } + if (init == error_mark_node) + return; + /* Effective C++ rule 12 requires that all data members be initialized. */ if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE) @@ -563,6 +612,44 @@ perform_member_init (tree member, tree init) finish_expr_stmt (init); } } + else if (init + && (TREE_CODE (type) == REFERENCE_TYPE + /* Pre-digested NSDMI. */ + || (((TREE_CODE (init) == CONSTRUCTOR + && TREE_TYPE (init) == type) + /* { } mem-initializer. */ + || (TREE_CODE (init) == TREE_LIST + && TREE_CODE (TREE_VALUE (init)) == CONSTRUCTOR + && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init)))) + && (CP_AGGREGATE_TYPE_P (type) + || is_std_init_list (type))))) + { + /* With references and list-initialization, we need to deal with + extending temporary lifetimes. 12.2p5: "A temporary bound to a + reference member in a constructor’s ctor-initializer (12.6.2) + persists until the constructor exits." */ + unsigned i; tree t; + VEC(tree,gc) *cleanups = make_tree_vector (); + if (TREE_CODE (init) == TREE_LIST) + init = build_x_compound_expr_from_list (init, ELK_MEM_INIT, + tf_warning_or_error); + if (TREE_TYPE (init) != type) + init = digest_init (type, init, tf_warning_or_error); + if (init == error_mark_node) + return; + /* A FIELD_DECL doesn't really have a suitable lifetime, but + make_temporary_var_for_ref_to_temp will treat it as automatic and + set_up_extended_ref_temp wants to use the decl in a warning. */ + init = extend_ref_init_temps (member, init, &cleanups); + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type))) + init = build_vec_init_expr (type, init, tf_warning_or_error); + init = build2 (INIT_EXPR, type, decl, init); + finish_expr_stmt (init); + FOR_EACH_VEC_ELT (tree, cleanups, i, t) + push_cleanup (decl, t, false); + release_tree_vector (cleanups); + } else if (type_build_ctor_call (type) || (init && CLASS_TYPE_P (strip_array_types (type)))) { @@ -940,6 +1027,16 @@ emit_mem_initializers (tree mem_inits) if (!COMPLETE_TYPE_P (current_class_type)) return; + if (mem_inits + && TYPE_P (TREE_PURPOSE (mem_inits)) + && same_type_p (TREE_PURPOSE (mem_inits), current_class_type)) + { + /* Delegating constructor. */ + gcc_assert (TREE_CHAIN (mem_inits) == NULL_TREE); + perform_target_ctor (TREE_VALUE (mem_inits)); + return; + } + if (DECL_DEFAULTED_FN (current_function_decl)) flags |= LOOKUP_DEFAULTED; @@ -1083,7 +1180,7 @@ expand_virtual_init (tree binfo, tree decl) gcc_assert (vtbl_ptr != error_mark_node); /* Assign the vtable to the vptr. */ - vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); + vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0, tf_warning_or_error); finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error)); } @@ -1153,7 +1250,7 @@ construct_virtual_base (tree vbase, tree arguments) exp = convert_to_base_statically (current_class_ref, vbase); expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, - LOOKUP_COMPLAIN, tf_warning_or_error); + 0, tf_warning_or_error); finish_then_clause (inner_if_stmt); finish_if_stmt (inner_if_stmt); @@ -1270,8 +1367,9 @@ expand_member_init (tree name) tree virtual_binfo; int i; - if (current_template_parms) - return basetype; + if (same_type_p (basetype, current_class_type) + || current_template_parms) + return basetype; class_binfo = TYPE_BINFO (current_class_type); direct_binfo = NULL_TREE; @@ -1375,6 +1473,8 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) TREE_THIS_VOLATILE (exp) = 0; if (init && TREE_CODE (init) != TREE_LIST + && !(TREE_CODE (init) == TARGET_EXPR + && TARGET_EXPR_DIRECT_INIT_P (init)) && !(BRACE_ENCLOSED_INITIALIZER_P (init) && CONSTRUCTOR_IS_DIRECT_INIT (init))) flags |= LOOKUP_ONLYCONVERTING; @@ -1457,10 +1557,28 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, if (init && BRACE_ENCLOSED_INITIALIZER_P (init) && CP_AGGREGATE_TYPE_P (type)) + /* A brace-enclosed initializer for an aggregate. In C++0x this can + happen for direct-initialization, too. */ + init = digest_init (type, init, complain); + + /* A CONSTRUCTOR of the target's type is a previously digested + initializer, whether that happened just above or in + cp_parser_late_parsing_nsdmi. + + A TARGET_EXPR with TARGET_EXPR_DIRECT_INIT_P or TARGET_EXPR_LIST_INIT_P + set represents the whole initialization, so we shouldn't build up + another ctor call. */ + if (init + && (TREE_CODE (init) == CONSTRUCTOR + || (TREE_CODE (init) == TARGET_EXPR + && (TARGET_EXPR_DIRECT_INIT_P (init) + || TARGET_EXPR_LIST_INIT_P (init)))) + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init), type)) { - /* A brace-enclosed initializer for an aggregate. In C++0x this can - happen for direct-initialization, too. */ - init = digest_init (type, init, complain); + /* Early initialization via a TARGET_EXPR only works for + complete objects. */ + gcc_assert (TREE_CODE (init) == CONSTRUCTOR || true_exp == exp); + init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); @@ -1480,7 +1598,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain); if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -1510,13 +1629,46 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, else parms = make_tree_vector_single (init); - if (true_exp == exp) - ctor_name = complete_ctor_identifier; - else - ctor_name = base_ctor_identifier; + if (exp == current_class_ref && current_function_decl + && DECL_HAS_IN_CHARGE_PARM_P (current_function_decl)) + { + /* Delegating constructor. */ + tree complete; + tree base; + tree elt; unsigned i; - rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags, - complain); + /* Unshare the arguments for the second call. */ + VEC(tree,gc) *parms2 = make_tree_vector (); + FOR_EACH_VEC_ELT (tree, parms, i, elt) + { + elt = break_out_target_exprs (elt); + VEC_safe_push (tree, gc, parms2, elt); + } + complete = build_special_member_call (exp, complete_ctor_identifier, + &parms2, binfo, flags, + complain); + complete = fold_build_cleanup_point_expr (void_type_node, complete); + release_tree_vector (parms2); + + base = build_special_member_call (exp, base_ctor_identifier, + &parms, binfo, flags, + complain); + base = fold_build_cleanup_point_expr (void_type_node, base); + rval = build3 (COND_EXPR, void_type_node, + build2 (EQ_EXPR, boolean_type_node, + current_in_charge_parm, integer_zero_node), + base, + complete); + } + else + { + if (true_exp == exp) + ctor_name = complete_ctor_identifier; + else + ctor_name = base_ctor_identifier; + rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags, + complain); + } if (parms != NULL) release_tree_vector (parms); @@ -1575,12 +1727,14 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, if (init && TREE_CODE (exp) == VAR_DECL && COMPOUND_LITERAL_P (init)) { + VEC(tree,gc)* cleanups = NULL; /* If store_init_value returns NULL_TREE, the INIT has been recorded as the DECL_INITIAL for EXP. That means there's nothing more we have to do. */ - init = store_init_value (exp, init, flags); + init = store_init_value (exp, init, &cleanups, flags); if (init) finish_expr_stmt (init); + gcc_assert (!cleanups); return; } @@ -1588,8 +1742,10 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, that's value-initialization. */ if (init == void_type_node) { - /* If no user-provided ctor, we need to zero out the object. */ - if (!type_has_user_provided_constructor (type)) + /* If the type has data but no user-provided ctor, we need to zero + out the object. */ + if (!type_has_user_provided_constructor (type) + && !is_really_empty_class (type)) { tree field_size = NULL_TREE; if (exp != true_exp && CLASSTYPE_AS_BASE (type) != type) @@ -1722,9 +1878,11 @@ build_offset_ref (tree type, tree member, bool address_p) (or any class derived from that class). */ if (address_p && DECL_P (t) && DECL_NONSTATIC_MEMBER_P (t)) - perform_or_defer_access_check (TYPE_BINFO (type), t, t); + perform_or_defer_access_check (TYPE_BINFO (type), t, t, + tf_warning_or_error); else - perform_or_defer_access_check (basebinfo, t, t); + perform_or_defer_access_check (basebinfo, t, t, + tf_warning_or_error); if (DECL_STATIC_FUNCTION_P (t)) return t; @@ -1737,7 +1895,8 @@ build_offset_ref (tree type, tree member, bool address_p) /* We need additional test besides the one in check_accessibility_of_qualified_id in case it is a pointer to non-static member. */ - perform_or_defer_access_check (TYPE_BINFO (type), member, member); + perform_or_defer_access_check (TYPE_BINFO (type), member, member, + tf_warning_or_error); if (!address_p) { @@ -2021,6 +2180,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, tree pointer_type; tree non_const_pointer_type; tree outer_nelts = NULL_TREE; + /* For arrays, a bounds checks on the NELTS parameter. */ + tree outer_nelts_check = NULL_TREE; + bool outer_nelts_from_type = false; + double_int inner_nelts_count = double_int_one; tree alloc_call, alloc_expr; /* The address returned by the call to "operator new". This node is a VAR_DECL and is therefore reusable. */ @@ -2055,10 +2218,14 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, } else if (TREE_CODE (type) == ARRAY_TYPE) { + /* Transforms new (T[N]) to new T[N]. The former is a GNU + extension for variable N. (This also covers new T where T is + a VLA typedef.) */ array_p = true; nelts = array_type_nelts_top (type); outer_nelts = nelts; type = TREE_TYPE (type); + outer_nelts_from_type = true; } /* If our base type is an array, then make sure we know how many elements @@ -2066,10 +2233,61 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, for (elt_type = type; TREE_CODE (elt_type) == ARRAY_TYPE; elt_type = TREE_TYPE (elt_type)) - nelts = cp_build_binary_op (input_location, - MULT_EXPR, nelts, - array_type_nelts_top (elt_type), - complain); + { + tree inner_nelts = array_type_nelts_top (elt_type); + tree inner_nelts_cst = maybe_constant_value (inner_nelts); + if (TREE_CONSTANT (inner_nelts_cst) + && TREE_CODE (inner_nelts_cst) == INTEGER_CST) + { + double_int result; + if (mul_double (TREE_INT_CST_LOW (inner_nelts_cst), + TREE_INT_CST_HIGH (inner_nelts_cst), + inner_nelts_count.low, inner_nelts_count.high, + &result.low, &result.high)) + { + if (complain & tf_error) + error ("integer overflow in array size"); + nelts = error_mark_node; + } + inner_nelts_count = result; + } + else + { + if (complain & tf_error) + { + error_at (EXPR_LOC_OR_HERE (inner_nelts), + "array size in operator new must be constant"); + cxx_constant_value(inner_nelts); + } + nelts = error_mark_node; + } + if (nelts != error_mark_node) + nelts = cp_build_binary_op (input_location, + MULT_EXPR, nelts, + inner_nelts_cst, + complain); + } + + if (variably_modified_type_p (elt_type, NULL_TREE) && (complain & tf_error)) + { + error ("variably modified type not allowed in operator new"); + return error_mark_node; + } + + if (nelts == error_mark_node) + return error_mark_node; + + /* Warn if we performed the (T[N]) to T[N] transformation and N is + variable. */ + if (outer_nelts_from_type + && !TREE_CONSTANT (maybe_constant_value (outer_nelts))) + { + if (complain & tf_warning_or_error) + pedwarn(EXPR_LOC_OR_HERE (outer_nelts), OPT_Wvla, + "ISO C++ does not support variable-length array types"); + else + return error_mark_node; + } if (TREE_CODE (elt_type) == VOID_TYPE) { @@ -2123,7 +2341,56 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, size = size_in_bytes (elt_type); if (array_p) - size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); + { + /* Maximum available size in bytes. Half of the address space + minus the cookie size. */ + double_int max_size + = double_int_lshift (double_int_one, TYPE_PRECISION (sizetype) - 1, + HOST_BITS_PER_DOUBLE_INT, false); + /* Size of the inner array elements. */ + double_int inner_size; + /* Maximum number of outer elements which can be allocated. */ + double_int max_outer_nelts; + tree max_outer_nelts_tree; + + gcc_assert (TREE_CODE (size) == INTEGER_CST); + cookie_size = targetm.cxx.get_cookie_size (elt_type); + gcc_assert (TREE_CODE (cookie_size) == INTEGER_CST); + gcc_checking_assert (double_int_ucmp + (TREE_INT_CST (cookie_size), max_size) < 0); + /* Unconditionally substract the cookie size. This decreases the + maximum object size and is safe even if we choose not to use + a cookie after all. */ + max_size = double_int_sub (max_size, TREE_INT_CST (cookie_size)); + if (mul_double (TREE_INT_CST_LOW (size), TREE_INT_CST_HIGH (size), + inner_nelts_count.low, inner_nelts_count.high, + &inner_size.low, &inner_size.high) + || double_int_ucmp (inner_size, max_size) > 0) + { + if (complain & tf_error) + error ("size of array is too large"); + return error_mark_node; + } + max_outer_nelts = double_int_udiv (max_size, inner_size, TRUNC_DIV_EXPR); + /* Only keep the top-most seven bits, to simplify encoding the + constant in the instruction stream. */ + { + unsigned shift = HOST_BITS_PER_DOUBLE_INT - 7 + - (max_outer_nelts.high ? clz_hwi (max_outer_nelts.high) + : (HOST_BITS_PER_WIDE_INT + clz_hwi (max_outer_nelts.low))); + max_outer_nelts + = double_int_lshift (double_int_rshift + (max_outer_nelts, shift, + HOST_BITS_PER_DOUBLE_INT, false), + shift, HOST_BITS_PER_DOUBLE_INT, false); + } + max_outer_nelts_tree = double_int_to_tree (sizetype, max_outer_nelts); + + size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); + outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node, + outer_nelts, + max_outer_nelts_tree); + } alloc_fn = NULL_TREE; @@ -2186,10 +2453,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, /* Use a class-specific operator new. */ /* If a cookie is required, add some extra space. */ if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type)) - { - cookie_size = targetm.cxx.get_cookie_size (elt_type); - size = size_binop (PLUS_EXPR, size, cookie_size); - } + size = size_binop (PLUS_EXPR, size, cookie_size); + else + cookie_size = NULL_TREE; + /* Perform the overflow check. */ + if (outer_nelts_check != NULL_TREE) + size = fold_build3 (COND_EXPR, sizetype, outer_nelts_check, + size, TYPE_MAX_VALUE (sizetype)); /* Create the argument list. */ VEC_safe_insert (tree, gc, *placement, 0, size); /* Do name-lookup to find the appropriate operator. */ @@ -2220,14 +2490,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, { /* Use a global operator new. */ /* See if a cookie might be required. */ - if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type)) - cookie_size = targetm.cxx.get_cookie_size (elt_type); - else + if (!(array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))) cookie_size = NULL_TREE; alloc_call = build_operator_new_call (fnname, placement, &size, &cookie_size, - &alloc_fn); + outer_nelts_check, + &alloc_fn, complain); } } @@ -2503,7 +2772,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, size, globally_qualified_p, placement_allocation_fn_p ? alloc_call : NULL_TREE, - alloc_fn)); + alloc_fn, + complain)); if (!cleanup) /* We're done. */; @@ -2578,7 +2848,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, { tree ifexp = cp_build_binary_op (input_location, NE_EXPR, alloc_node, - integer_zero_node, + nullptr_node, complain); rval = build_conditional_expr (ifexp, rval, alloc_node, complain); @@ -2620,7 +2890,9 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts, if (type == error_mark_node) return error_mark_node; - if (nelts == NULL_TREE && VEC_length (tree, *init) == 1) + if (nelts == NULL_TREE && VEC_length (tree, *init) == 1 + /* Don't do auto deduction where it might affect mangling. */ + && (!processing_template_decl || at_function_scope_p ())) { tree auto_node = type_uses_auto (type); if (auto_node) @@ -2660,7 +2932,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts, return error_mark_node; } nelts = mark_rvalue_use (nelts); - nelts = cp_save_expr (cp_convert (sizetype, nelts)); + nelts = cp_save_expr (cp_convert (sizetype, nelts, complain)); } /* ``A reference cannot be created by the new operator. A reference @@ -2857,12 +3129,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, base_tbd = cp_build_binary_op (input_location, MINUS_EXPR, cp_convert (string_type_node, - base), + base, complain), cookie_size, complain); if (base_tbd == error_mark_node) return error_mark_node; - base_tbd = cp_convert (ptype, base_tbd); + base_tbd = cp_convert (ptype, base_tbd, complain); /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size); } @@ -2871,7 +3143,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, base_tbd, virtual_size, use_global_delete & 1, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } body = loop; @@ -2890,7 +3163,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, fold_build2_loc (input_location, NE_EXPR, boolean_type_node, base, convert (TREE_TYPE (base), - integer_zero_node)), + nullptr_node)), body, integer_zero_node); body = build1 (NOP_EXPR, void_type_node, body); @@ -3034,11 +3307,14 @@ build_vec_init (tree base, tree maxindex, tree init, return stmt_expr; } - maxindex = cp_convert (ptrdiff_type_node, maxindex); + maxindex = cp_convert (ptrdiff_type_node, maxindex, complain); if (TREE_CODE (atype) == ARRAY_TYPE) { ptype = build_pointer_type (type); - base = cp_convert (ptype, decay_conversion (base)); + base = decay_conversion (base, complain); + if (base == error_mark_node) + return error_mark_node; + base = cp_convert (ptype, base, complain); } else ptype = atype; @@ -3087,7 +3363,9 @@ build_vec_init (tree base, tree maxindex, tree init, { if (lvalue_kind (init) & clk_rvalueref) xvalue = true; - base2 = decay_conversion (init); + base2 = decay_conversion (init, complain); + if (base2 == error_mark_node) + return error_mark_node; itype = TREE_TYPE (base2); base2 = get_temp_regvar (itype, base2); itype = TREE_TYPE (itype); @@ -3128,6 +3406,9 @@ build_vec_init (tree base, tree maxindex, tree init, bool try_const = (TREE_CODE (atype) == ARRAY_TYPE && (literal_type_p (inner_elt_type) || TYPE_HAS_CONSTEXPR_CTOR (inner_elt_type))); + /* If the constructor already has the array type, it's been through + digest_init, so we shouldn't try to do anything more. */ + bool digested = same_type_p (atype, TREE_TYPE (init)); bool saw_non_const = false; bool saw_const = false; /* If we're initializing a static array, we want to do static @@ -3150,7 +3431,9 @@ build_vec_init (tree base, tree maxindex, tree init, num_initialized_elts++; current_stmt_tree ()->stmts_are_full_exprs_p = 1; - if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) + if (digested) + one_init = build2 (INIT_EXPR, type, baseref, elt); + else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) one_init = build_aggr_init (baseref, elt, 0, complain); else one_init = cp_build_modify_expr (baseref, NOP_EXPR, @@ -3500,7 +3783,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, addr = save_expr (addr); /* Throw away const and volatile on target type of addr. */ - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3526,7 +3809,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } gcc_assert (MAYBE_CLASS_TYPE_P (type)); @@ -3540,7 +3823,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, cxx_sizeof_nowarn (type), use_global_delete, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } else { @@ -3579,7 +3863,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); /* Call the complete object destructor. */ auto_delete = sfk_complete_destructor; } @@ -3591,7 +3876,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain), @@ -3612,7 +3898,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, { /* Handle deleting a null pointer. */ ifexp = fold (cp_build_binary_op (input_location, - NE_EXPR, addr, integer_zero_node, + NE_EXPR, addr, nullptr_node, complain)); if (ifexp == error_mark_node) return error_mark_node;