X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Finit.c;h=70e3d387e9e30d4a841254cd6fe8c6ec654f3b64;hb=bc3c3cc82d4b9666acd3ac684ea798e037aabb3b;hp=6b2156d39cc70abead9f01ce241463ce06c707ba;hpb=717ecce9e70fa3c2648e8b160e75f1fb91332181;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 6b2156d39cc..70e3d387e9e 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1,6 +1,6 @@ /* 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 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) @@ -54,6 +54,7 @@ static tree dfs_initialize_vtbl_ptrs (tree, void *); static tree build_dtor_call (tree, special_function_kind, int); static tree build_field_list (tree, tree, int *); static tree build_vtbl_address (tree); +static void diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool); /* We are about to generate some complex initialization code. Conceptually, it is all a single expression. However, we may want @@ -219,7 +220,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) /* Iterate over the array elements, building initializations. */ if (nelts) - max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts), + max_index = fold_build2_loc (input_location, + MINUS_EXPR, TREE_TYPE (nelts), nelts, integer_one_node); else max_index = array_type_nelts (type); @@ -261,67 +263,16 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) /* In all cases, the initializer is a constant. */ if (init) - { - TREE_CONSTANT (init) = 1; - TREE_INVARIANT (init) = 1; - } + TREE_CONSTANT (init) = 1; return init; } -/* Build an expression for the default-initialization of an object of - the indicated TYPE. If NELTS is non-NULL, and TYPE is an - ARRAY_TYPE, NELTS is the number of elements in the array. If - initialization of TYPE requires calling constructors, this function - returns NULL_TREE; the caller is responsible for arranging for the - constructors to be called. */ - -tree -build_default_init (tree type, tree nelts) -{ - /* [dcl.init]: - - To default-initialize an object of type T means: - - --if T is a non-POD class type (clause _class_), the default construc- - tor for T is called (and the initialization is ill-formed if T has - no accessible default constructor); - - --if T is an array type, each element is default-initialized; - - --otherwise, the storage for the object is zero-initialized. - - A program that calls for default-initialization of an entity of refer- - ence type is ill-formed. */ - - /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for - performing the initialization. This is confusing in that some - non-PODs do not have TYPE_NEEDS_CONSTRUCTING set. (For example, - a class with a pointer-to-data member as a non-static data member - does not have TYPE_NEEDS_CONSTRUCTING set.) Therefore, we end up - passing non-PODs to build_zero_init below, which is contrary to - the semantics quoted above from [dcl.init]. - - It happens, however, that the behavior of the constructor the - standard says we should have generated would be precisely the - same as that obtained by calling build_zero_init below, so things - work out OK. */ - if (TYPE_NEEDS_CONSTRUCTING (type) - || (nelts && TREE_CODE (nelts) != INTEGER_CST)) - return NULL_TREE; - - /* At this point, TYPE is either a POD class type, an array of POD - classes, or something even more innocuous. */ - return build_zero_init (type, nelts, /*static_storage_p=*/false); -} - /* Return a suitable initializer for value-initializing an object of type - TYPE, as described in [dcl.init]. If HAVE_CTOR is true, the initializer - for an enclosing object is already calling the constructor for this - object. */ + TYPE, as described in [dcl.init]. */ -static tree -build_value_init_1 (tree type, bool have_ctor) +tree +build_value_init (tree type) { /* [dcl.init] @@ -349,17 +300,44 @@ build_value_init_1 (tree type, bool have_ctor) if (CLASS_TYPE_P (type)) { - if (TYPE_HAS_USER_CONSTRUCTOR (type) && !have_ctor) - return build_cplus_new + if (type_has_user_provided_constructor (type)) + return build_aggr_init_expr (type, build_special_member_call (NULL_TREE, complete_ctor_identifier, - NULL_TREE, type, LOOKUP_NORMAL, + NULL, type, LOOKUP_NORMAL, tf_warning_or_error)); - else if (TREE_CODE (type) != UNION_TYPE) + else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type)) + { + /* This is a class that needs constructing, but doesn't have + a user-provided constructor. So we need to zero-initialize + the object and then call the implicitly defined ctor. + This will be handled in simplify_aggr_init_expr. */ + tree ctor = build_special_member_call + (NULL_TREE, complete_ctor_identifier, + NULL, type, LOOKUP_NORMAL, tf_warning_or_error); + + ctor = build_aggr_init_expr (type, ctor); + AGGR_INIT_ZERO_FIRST (ctor) = 1; + return ctor; + } + } + return build_value_init_noctor (type); +} + +/* Like build_value_init, but don't call the constructor for TYPE. Used + for base initializers. */ + +tree +build_value_init_noctor (tree type) +{ + if (CLASS_TYPE_P (type)) + { + gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type)); + + if (TREE_CODE (type) != UNION_TYPE) { - tree field, init; + tree field; VEC(constructor_elt,gc) *v = NULL; - bool call_ctor = !have_ctor && TYPE_NEEDS_CONSTRUCTING (type); /* Iterate over the fields, building initializations. */ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) @@ -384,35 +362,14 @@ build_value_init_1 (tree type, bool have_ctor) corresponding to base classes as well. Thus, iterating over TYPE_FIELDs will result in correct initialization of all of the subobjects. */ - value = build_value_init_1 (ftype, have_ctor || call_ctor); + value = build_value_init (ftype); if (value) CONSTRUCTOR_APPEND_ELT(v, field, value); } /* Build a constructor to contain the zero- initializations. */ - init = build_constructor (type, v); - if (call_ctor) - { - /* This is a class that needs constructing, but doesn't have - a user-defined constructor. So we need to zero-initialize - the object and then call the implicitly defined ctor. - Implement this by sticking the zero-initialization inside - the TARGET_EXPR for the constructor call; - cp_gimplify_init_expr will know how to handle it. */ - tree ctor = build_special_member_call - (NULL_TREE, complete_ctor_identifier, - NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error); - - ctor = build_cplus_new (type, ctor); - init = build2 (INIT_EXPR, void_type_node, - TARGET_EXPR_SLOT (ctor), init); - init = build2 (COMPOUND_EXPR, void_type_node, init, - TARGET_EXPR_INITIAL (ctor)); - TARGET_EXPR_INITIAL (ctor) = init; - return ctor; - } - return init; + return build_constructor (type, v); } } else if (TREE_CODE (type) == ARRAY_TYPE) @@ -444,7 +401,11 @@ build_value_init_1 (tree type, bool have_ctor) ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index); - ce->value = build_value_init_1 (TREE_TYPE (type), have_ctor); + ce->value = build_value_init (TREE_TYPE (type)); + + /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */ + gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR + && TREE_CODE (ce->value) != AGGR_INIT_EXPR); } /* Build a constructor to contain the initializations. */ @@ -454,15 +415,6 @@ build_value_init_1 (tree type, bool have_ctor) return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); } -/* Return a suitable initializer for value-initializing an object of type - TYPE, as described in [dcl.init]. */ - -tree -build_value_init (tree type) -{ - return build_value_init_1 (type, false); -} - /* 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. */ @@ -472,18 +424,13 @@ perform_member_init (tree member, tree init) { tree decl; tree type = TREE_TYPE (member); - bool explicit; - - explicit = (init != NULL_TREE); /* Effective C++ rule 12 requires that all data members be initialized. */ - if (warn_ecpp && !explicit && TREE_CODE (type) != ARRAY_TYPE) - warning (OPT_Weffc__, "%J%qD should be initialized in the member initialization " - "list", current_function_decl, member); - - if (init == void_type_node) - init = NULL_TREE; + if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE) + warning_at (DECL_SOURCE_LOCATION (current_function_decl), OPT_Weffc__, + "%qD should be initialized in the member initialization list", + member); /* Get an lvalue for the data member. */ decl = build_class_member_access_expr (current_class_ref, member, @@ -493,10 +440,34 @@ perform_member_init (tree member, tree init) if (decl == error_mark_node) return; + if (init == void_type_node) + { + /* mem() means value-initialization. */ + if (TREE_CODE (type) == ARRAY_TYPE) + { + init = build_vec_init (decl, NULL_TREE, NULL_TREE, + /*explicit_value_init_p=*/true, + /* from_array=*/0, + tf_warning_or_error); + finish_expr_stmt (init); + } + else + { + if (TREE_CODE (type) == REFERENCE_TYPE) + permerror (DECL_SOURCE_LOCATION (current_function_decl), + "value-initialization of %q#D, which has reference type", + member); + else + { + init = build2 (INIT_EXPR, type, decl, build_value_init (type)); + finish_expr_stmt (init); + } + } + } /* Deal with this here, as we will get confused if we try to call the assignment op for an anonymous union. This can happen in a synthesized copy constructor. */ - if (ANON_AGGR_TYPE_P (type)) + else if (ANON_AGGR_TYPE_P (type)) { if (init) { @@ -506,41 +477,52 @@ perform_member_init (tree member, tree init) } else if (TYPE_NEEDS_CONSTRUCTING (type)) { - if (explicit + if (init != NULL_TREE && TREE_CODE (type) == ARRAY_TYPE - && init != NULL_TREE && TREE_CHAIN (init) == NULL_TREE && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE) { /* Initialization of one array from another. */ finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init), - /*explicit_default_init_p=*/false, + /*explicit_value_init_p=*/false, /* from_array=*/1, tf_warning_or_error)); } else - finish_expr_stmt (build_aggr_init (decl, init, 0, - tf_warning_or_error)); + { + if (CP_TYPE_CONST_P (type) + && init == NULL_TREE + && !type_has_user_provided_default_constructor (type)) + /* TYPE_NEEDS_CONSTRUCTING can be set just because we have a + vtable; still give this diagnostic. */ + permerror (DECL_SOURCE_LOCATION (current_function_decl), + "uninitialized member %qD with % type %qT", + member, type); + finish_expr_stmt (build_aggr_init (decl, init, 0, + tf_warning_or_error)); + } } else { if (init == NULL_TREE) { - if (explicit) - { - init = build_default_init (type, /*nelts=*/NULL_TREE); - if (TREE_CODE (type) == REFERENCE_TYPE) - warning (0, "%Jdefault-initialization of %q#D, " - "which has reference type", - current_function_decl, member); - } + tree core_type; /* member traversal: note it leaves init NULL */ - else if (TREE_CODE (type) == REFERENCE_TYPE) - pedwarn ("%Juninitialized reference member %qD", - current_function_decl, member); + if (TREE_CODE (type) == REFERENCE_TYPE) + permerror (DECL_SOURCE_LOCATION (current_function_decl), + "uninitialized reference member %qD", + member); else if (CP_TYPE_CONST_P (type)) - pedwarn ("%Juninitialized member %qD with % type %qT", - current_function_decl, member, type); + permerror (DECL_SOURCE_LOCATION (current_function_decl), + "uninitialized member %qD with % type %qT", + member, type); + + core_type = strip_array_types (type); + if (CLASS_TYPE_P (core_type) + && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type) + || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))) + diagnose_uninitialized_cst_or_ref_member (core_type, + /*using_new=*/false); } else if (TREE_CODE (init) == TREE_LIST) /* There was an explicit member initialization. Do some work @@ -693,7 +675,8 @@ sort_mem_initializers (tree t, tree mem_inits) warning (OPT_Wreorder, " %q+#D", subobject); else warning (OPT_Wreorder, " base %qT", subobject); - warning (OPT_Wreorder, "%J when initialized here", current_function_decl); + warning_at (DECL_SOURCE_LOCATION (current_function_decl), + OPT_Wreorder, " when initialized here"); } /* Look again, from the beginning of the list. */ @@ -709,11 +692,13 @@ sort_mem_initializers (tree t, tree mem_inits) if (TREE_VALUE (subobject_init)) { if (TREE_CODE (subobject) == FIELD_DECL) - error ("%Jmultiple initializations given for %qD", - current_function_decl, subobject); + error_at (DECL_SOURCE_LOCATION (current_function_decl), + "multiple initializations given for %qD", + subobject); else - error ("%Jmultiple initializations given for base %qT", - current_function_decl, subobject); + error_at (DECL_SOURCE_LOCATION (current_function_decl), + "multiple initializations given for base %qT", + subobject); } /* Record the initialization. */ @@ -779,8 +764,9 @@ sort_mem_initializers (tree t, tree mem_inits) if (same_type_p (last_field_type, field_type)) { if (TREE_CODE (field_type) == UNION_TYPE) - error ("%Jinitializations for multiple members of %qT", - current_function_decl, last_field_type); + error_at (DECL_SOURCE_LOCATION (current_function_decl), + "initializations for multiple members of %qT", + last_field_type); done = 1; break; } @@ -842,14 +828,10 @@ emit_mem_initializers (tree mem_inits) if (extra_warnings && !arguments && DECL_COPY_CONSTRUCTOR_P (current_function_decl) && type_has_user_nondefault_constructor (BINFO_TYPE (subobject))) - warning (OPT_Wextra, "%Jbase class %q#T should be explicitly initialized in the " - "copy constructor", - current_function_decl, BINFO_TYPE (subobject)); - - /* If an explicit -- but empty -- initializer list was present, - treat it just like default initialization at this point. */ - if (arguments == void_type_node) - arguments = NULL_TREE; + warning_at (DECL_SOURCE_LOCATION (current_function_decl), OPT_Wextra, + "base class %q#T should be explicitly initialized in the " + "copy constructor", + BINFO_TYPE (subobject)); /* Initialize the base. */ if (BINFO_VIRTUAL_P (subobject)) @@ -861,7 +843,7 @@ emit_mem_initializers (tree mem_inits) base_addr = build_base_path (PLUS_EXPR, current_class_ptr, subobject, 1); expand_aggr_init_1 (subobject, NULL_TREE, - cp_build_indirect_ref (base_addr, NULL, + cp_build_indirect_ref (base_addr, RO_NULL, tf_warning_or_error), arguments, LOOKUP_NORMAL, @@ -906,7 +888,6 @@ build_vtbl_address (tree binfo) /* Figure out what vtable BINFO's vtable is based on, and mark it as used. */ vtbl = get_vtbl_decl_for_binfo (binfo_for); - assemble_external (vtbl); TREE_USED (vtbl) = 1; /* Now compute the address to use when initializing the vptr. */ @@ -946,7 +927,7 @@ expand_virtual_init (tree binfo, tree decl) TREE_TYPE (vtt_parm), vtt_parm, vtt_index); - vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error); + vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error); vtbl2 = convert (TREE_TYPE (vtbl), vtbl2); /* The actual initializer is the VTT value only in the subobject @@ -961,7 +942,7 @@ expand_virtual_init (tree binfo, tree decl) } /* Compute the location of the vtpr. */ - vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL, + vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL, tf_warning_or_error), TREE_TYPE (binfo)); gcc_assert (vtbl_ptr != error_mark_node); @@ -989,13 +970,14 @@ expand_cleanup_for_base (tree binfo, tree flag) /* Call the destructor. */ expr = build_special_member_call (current_class_ref, base_dtor_identifier, - NULL_TREE, + NULL, binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error); if (flag) - expr = fold_build3 (COND_EXPR, void_type_node, - c_common_truthvalue_conversion (flag), + expr = fold_build3_loc (input_location, + COND_EXPR, void_type_node, + c_common_truthvalue_conversion (input_location, flag), expr, integer_zero_node); finish_eh_cleanup (expr); @@ -1275,13 +1257,13 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) /* Must arrange to initialize each element of EXP from elements of INIT. */ itype = init ? TREE_TYPE (init) : NULL_TREE; - if (cp_type_quals (type) != TYPE_UNQUALIFIED) - TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); - if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED) - itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype); + if (cv_qualified_p (type)) + TREE_TYPE (exp) = cv_unqualified (type); + if (itype && cv_qualified_p (itype)) + TREE_TYPE (init) = cv_unqualified (itype); stmt_expr = build_vec_init (exp, NULL_TREE, init, - /*explicit_default_init_p=*/false, - itype && same_type_p (itype, + /*explicit_value_init_p=*/false, + itype && same_type_p (TREE_TYPE (init), TREE_TYPE (exp)), complain); TREE_READONLY (exp) = was_const; @@ -1323,7 +1305,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, followed by initialization by X. If neither of these work out, then look hard. */ tree rval; - tree parms; + VEC(tree,gc) *parms; if (init && TREE_CODE (init) != TREE_LIST && (flags & LOOKUP_ONLYCONVERTING)) @@ -1337,10 +1319,10 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, to run a new constructor; and catching an exception, where we have already built up the constructor call so we could wrap it in an exception region. */; - else if (BRACE_ENCLOSED_INITIALIZER_P (init)) + else if (BRACE_ENCLOSED_INITIALIZER_P (init) + && CP_AGGREGATE_TYPE_P (type)) { /* A brace-enclosed initializer for an aggregate. */ - gcc_assert (CP_AGGREGATE_TYPE_P (type)); init = digest_init (type, init); } else @@ -1363,23 +1345,28 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, return; } - if (init == NULL_TREE - || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init))) + if (init == NULL_TREE) + parms = NULL; + else if (TREE_CODE (init) == TREE_LIST && !TREE_TYPE (init)) { - parms = init; - if (parms) - init = TREE_VALUE (parms); + parms = make_tree_vector (); + for (; init != NULL_TREE; init = TREE_CHAIN (init)) + VEC_safe_push (tree, gc, parms, TREE_VALUE (init)); } else - parms = build_tree_list (NULL_TREE, init); + parms = make_tree_vector_single (init); 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, + rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags, complain); + + if (parms != NULL) + release_tree_vector (parms); + if (TREE_SIDE_EFFECTS (rval)) finish_expr_stmt (convert_to_void (rval, NULL, complain)); } @@ -1425,12 +1412,39 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* 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); + init = store_init_value (exp, init, flags); if (init) finish_expr_stmt (init); return; } + /* If an explicit -- but empty -- initializer list was present, + that's value-initialization. */ + if (init == void_type_node) + { + /* If there's a user-provided constructor, we just call that. */ + if (type_has_user_provided_constructor (type)) + /* Fall through. */; + /* If there isn't, but we still need to call the constructor, + zero out the object first. */ + else if (TYPE_NEEDS_CONSTRUCTING (type)) + { + init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); + init = build2 (INIT_EXPR, type, exp, init); + finish_expr_stmt (init); + /* And then call the constructor. */ + } + /* If we don't need to mess with the constructor at all, + then just zero out the object and we're done. */ + else + { + init = build2 (INIT_EXPR, type, exp, build_value_init_noctor (type)); + finish_expr_stmt (init); + return; + } + init = NULL_TREE; + } + /* We know that expand_default_init can handle everything we want at this point. */ expand_default_init (binfo, true_exp, exp, init, flags, complain); @@ -1581,7 +1595,7 @@ build_offset_ref (tree type, tree member, bool address_p) a class derived from that class (_class.base.init_). */ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member)) { - /* Build a representation of a the qualified name suitable + /* Build a representation of the qualified name suitable for use as the operand to "&" -- even though the "&" is not actually present. */ member = build2 (OFFSET_REF, TREE_TYPE (member), decl, member); @@ -1652,7 +1666,23 @@ constant_value_1 (tree decl, bool integral_p) init = DECL_INITIAL (decl); } if (init == error_mark_node) - return decl; + { + if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + /* Treat the error as a constant to avoid cascading errors on + excessively recursive template instantiation (c++/9335). */ + return init; + else + return decl; + } + /* Initializers in templates are generally expanded during + instantiation, so before that for const int i(2) + INIT is a TREE_LIST with the actual initializer as + TREE_VALUE. */ + if (processing_template_decl + && init + && TREE_CODE (init) == TREE_LIST + && TREE_CHAIN (init) == NULL_TREE) + init = TREE_VALUE (init); if (!init || !TREE_TYPE (init) || (integral_p @@ -1708,103 +1738,116 @@ build_builtin_delete_call (tree addr) the type of the object being allocated; otherwise, it's just TYPE. INIT is the initializer, if any. USE_GLOBAL_NEW is true if the user explicitly wrote "::operator new". PLACEMENT, if non-NULL, is - the TREE_LIST of arguments to be provided as arguments to a - placement new operator. This routine performs no semantic checks; - it just creates and returns a NEW_EXPR. */ + a vector of arguments to be provided as arguments to a placement + new operator. This routine performs no semantic checks; it just + creates and returns a NEW_EXPR. */ static tree -build_raw_new_expr (tree placement, tree type, tree nelts, tree init, - int use_global_new) +build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts, + VEC(tree,gc) *init, int use_global_new) { + tree init_list; tree new_expr; - new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type, - nelts, init); + /* If INIT is NULL, the we want to store NULL_TREE in the NEW_EXPR. + If INIT is not NULL, then we want to store VOID_ZERO_NODE. This + permits us to distinguish the case of a missing initializer "new + int" from an empty initializer "new int()". */ + if (init == NULL) + init_list = NULL_TREE; + else if (VEC_empty (tree, init)) + init_list = void_zero_node; + else + init_list = build_tree_list_vec (init); + + new_expr = build4 (NEW_EXPR, build_pointer_type (type), + build_tree_list_vec (placement), type, nelts, + init_list); NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new; TREE_SIDE_EFFECTS (new_expr) = 1; return new_expr; } -/* Make sure that there are no aliasing issues with T, a placement new - expression applied to PLACEMENT, by recording the change in dynamic - type. If placement new is inlined, as it is with libstdc++, and if - the type of the placement new differs from the type of the - placement location itself, then alias analysis may think it is OK - to interchange writes to the location from before the placement new - and from after the placement new. We have to prevent type-based - alias analysis from applying. PLACEMENT may be NULL, which means - that we couldn't capture it in a temporary variable, in which case - we use a memory clobber. */ +/* Diagnose uninitialized const members or reference members of type + TYPE. USING_NEW is used to disambiguate the diagnostic between a + new expression without a new-initializer and a declaration */ -static tree -avoid_placement_new_aliasing (tree t, tree placement) +static void +diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin, + bool using_new) { - tree type_change; + tree field; - if (processing_template_decl) - return t; - - /* If we are not using type based aliasing, we don't have to do - anything. */ - if (!flag_strict_aliasing) - return t; - - /* If we have a pointer and a location, record the change in dynamic - type. Otherwise we need a general memory clobber. */ - if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE - && placement != NULL_TREE - && TREE_CODE (TREE_TYPE (placement)) == POINTER_TYPE) - type_change = build_stmt (CHANGE_DYNAMIC_TYPE_EXPR, - TREE_TYPE (t), - placement); - else + if (type_has_user_provided_constructor (type)) + return; + + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { - /* Build a memory clobber. */ - type_change = build_stmt (ASM_EXPR, - build_string (0, ""), - NULL_TREE, - NULL_TREE, - tree_cons (NULL_TREE, - build_string (6, "memory"), - NULL_TREE)); + tree field_type; + + if (TREE_CODE (field) != FIELD_DECL) + continue; + + field_type = strip_array_types (TREE_TYPE (field)); + + if (TREE_CODE (field_type) == REFERENCE_TYPE) + { + if (using_new) + error ("uninitialized reference member in %q#T " + "using % without new-initializer", origin); + else + error ("uninitialized reference member in %q#T", origin); + inform (DECL_SOURCE_LOCATION (field), + "%qD should be initialized", field); + } + + if (CP_TYPE_CONST_P (field_type)) + { + if (using_new) + error ("uninitialized const member in %q#T " + "using % without new-initializer", origin); + else + error ("uninitialized const member in %q#T", origin); + inform (DECL_SOURCE_LOCATION (field), + "%qD should be initialized", field); + } - ASM_VOLATILE_P (type_change) = 1; + if (CLASS_TYPE_P (field_type)) + diagnose_uninitialized_cst_or_ref_member_1 (field_type, + origin, using_new); } +} - return build2 (COMPOUND_EXPR, TREE_TYPE (t), type_change, t); +void +diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new) +{ + diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new); } /* 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 - build_raw_new_expr. */ + build_raw_new_expr. This may change PLACEMENT and INIT. */ static tree -build_new_1 (tree placement, tree type, tree nelts, tree init, - bool globally_qualified_p, tsubst_flags_t complain) +build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, + VEC(tree,gc) **init, bool globally_qualified_p, + tsubst_flags_t complain) { tree size, rval; /* True iff this is a call to "operator new[]" instead of just "operator new". */ bool array_p = false; - /* True iff ARRAY_P is true and the bound of the array type is - not necessarily a compile time constant. For example, VLA_P is - true for "new int[f()]". */ - bool vla_p = false; - /* The type being allocated. If ARRAY_P is true, this will be an - ARRAY_TYPE. */ - tree full_type; - /* If ARRAY_P is true, the element type of the array. This is an - never ARRAY_TYPE; for something like "new int[3][4]", the + /* If ARRAY_P is true, the element type of the array. This is never + an ARRAY_TYPE; for something like "new int[3][4]", the ELT_TYPE is "int". If ARRAY_P is false, this is the same type as - FULL_TYPE. */ + TYPE. */ tree elt_type; /* The type of the new-expression. (This type is always a pointer type.) */ tree pointer_type; - /* A pointer type pointing to the FULL_TYPE. */ - tree full_pointer_type; + tree non_const_pointer_type; tree outer_nelts = NULL_TREE; tree alloc_call, alloc_expr; /* The address returned by the call to "operator new". This node is @@ -1818,11 +1861,11 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, beginning of the storage allocated for an array-new expression in order to store the number of elements. */ tree cookie_size = NULL_TREE; + tree placement_first; tree placement_expr = NULL_TREE; /* True if the function we are calling is a placement allocation function. */ bool placement_allocation_fn_p; - tree args = NULL_TREE; /* True if the storage must be initialized, either by a constructor or due to an explicit new-initializer. */ bool is_initialized; @@ -1835,35 +1878,15 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (nelts) { - tree index; - outer_nelts = nelts; array_p = true; - - /* ??? The middle-end will error on us for building a VLA outside a - function context. Methinks that's not it's purvey. So we'll do - our own VLA layout later. */ - vla_p = true; - index = convert (sizetype, nelts); - index = size_binop (MINUS_EXPR, index, size_one_node); - index = build_index_type (index); - full_type = build_cplus_array_type (type, NULL_TREE); - /* We need a copy of the type as build_array_type will return a shared copy - of the incomplete array type. */ - full_type = build_distinct_type_copy (full_type); - TYPE_DOMAIN (full_type) = index; - SET_TYPE_STRUCTURAL_EQUALITY (full_type); } - else + else if (TREE_CODE (type) == ARRAY_TYPE) { - full_type = type; - if (TREE_CODE (type) == ARRAY_TYPE) - { - array_p = true; - nelts = array_type_nelts_top (type); - outer_nelts = nelts; - type = TREE_TYPE (type); - } + array_p = true; + nelts = array_type_nelts_top (type); + outer_nelts = nelts; + type = TREE_TYPE (type); } /* If our base type is an array, then make sure we know how many elements @@ -1871,7 +1894,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, for (elt_type = type; TREE_CODE (elt_type) == ARRAY_TYPE; elt_type = TREE_TYPE (elt_type)) - nelts = cp_build_binary_op (MULT_EXPR, nelts, + nelts = cp_build_binary_op (input_location, + MULT_EXPR, nelts, array_type_nelts_top (elt_type), complain); @@ -1885,8 +1909,42 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (abstract_virtuals_error (NULL_TREE, elt_type)) return error_mark_node; - is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init); - if (CP_TYPE_CONST_P (elt_type) && !is_initialized) + is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL); + + if (*init == NULL) + { + bool maybe_uninitialized_error = false; + /* A program that calls for default-initialization [...] of an + entity of reference type is ill-formed. */ + if (CLASSTYPE_REF_FIELDS_NEED_INIT (elt_type)) + maybe_uninitialized_error = true; + + /* A new-expression that creates an object of type T initializes + that object as follows: + - If the new-initializer is omitted: + -- If T is a (possibly cv-qualified) non-POD class type + (or array thereof), the object is default-initialized (8.5). + [...] + -- Otherwise, the object created has indeterminate + value. If T is a const-qualified type, or a (possibly + cv-qualified) POD class type (or array thereof) + containing (directly or indirectly) a member of + const-qualified type, the program is ill-formed; */ + + if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type)) + maybe_uninitialized_error = true; + + if (maybe_uninitialized_error) + { + if (complain & tf_error) + diagnose_uninitialized_cst_or_ref_member (elt_type, + /*using_new*/true); + return error_mark_node; + } + } + + if (CP_TYPE_CONST_P (elt_type) && *init == NULL + && !type_has_user_provided_default_constructor (elt_type)) { if (complain & tf_error) error ("uninitialized const in % of %q#T", elt_type); @@ -1895,26 +1953,21 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, size = size_in_bytes (elt_type); if (array_p) - { - size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); - if (vla_p) - { - tree n, bitsize; - - /* Do our own VLA layout. Setting TYPE_SIZE/_UNIT is - necessary in order for the > to be valid. */ - TYPE_SIZE_UNIT (full_type) = size; - n = convert (bitsizetype, nelts); - bitsize = size_binop (MULT_EXPR, TYPE_SIZE (elt_type), n); - TYPE_SIZE (full_type) = bitsize; - } - } + size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); alloc_fn = NULL_TREE; + /* If PLACEMENT is a single simple pointer type not passed by + reference, prepare to capture it in a temporary variable. Do + this now, since PLACEMENT will change in the calls below. */ + placement_first = NULL_TREE; + if (VEC_length (tree, *placement) == 1 + && (TREE_CODE (TREE_TYPE (VEC_index (tree, *placement, 0))) + == POINTER_TYPE)) + placement_first = VEC_index (tree, *placement, 0); + /* Allocate the object. */ - if (! placement && TYPE_FOR_JAVA (elt_type)) + if (VEC_empty (tree, *placement) && TYPE_FOR_JAVA (elt_type)) { tree class_addr; tree class_decl = build_java_class_ref (elt_type); @@ -1970,7 +2023,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, size = size_binop (PLUS_EXPR, size, cookie_size); } /* Create the argument list. */ - args = tree_cons (NULL_TREE, size, placement); + VEC_safe_insert (tree, gc, *placement, 0, size); /* Do name-lookup to find the appropriate operator. */ fns = lookup_fnfields (elt_type, fnname, /*protect=*/2); if (fns == NULL_TREE) @@ -1989,7 +2042,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, return error_mark_node; } alloc_call = build_new_method_call (build_dummy_object (elt_type), - fns, args, + fns, placement, /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL, &alloc_fn, @@ -2015,12 +2068,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, gcc_assert (alloc_fn != NULL_TREE); - /* If PLACEMENT is a simple pointer type and is not passed by reference, - then copy it into PLACEMENT_EXPR. */ + /* If we found a simple case of PLACEMENT_EXPR above, then copy it + into a temporary variable. */ if (!processing_template_decl - && placement != NULL_TREE - && TREE_CHAIN (placement) == NULL_TREE - && TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) == POINTER_TYPE + && placement_first != NULL_TREE && TREE_CODE (alloc_call) == CALL_EXPR && call_expr_nargs (alloc_call) == 2 && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 0))) == INTEGER_TYPE @@ -2028,10 +2079,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, { tree placement_arg = CALL_EXPR_ARG (alloc_call, 1); - if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg))) + if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg))) || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))) { - placement_expr = get_target_expr (TREE_VALUE (placement)); + placement_expr = get_target_expr (placement_first); CALL_EXPR_ARG (alloc_call, 1) = convert (TREE_TYPE (placement_arg), placement_expr); } @@ -2040,18 +2091,11 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, /* In the simple case, we can stop now. */ pointer_type = build_pointer_type (type); if (!cookie_size && !is_initialized) - { - rval = build_nop (pointer_type, alloc_call); - if (placement != NULL) - rval = avoid_placement_new_aliasing (rval, placement_expr); - return rval; - } + return build_nop (pointer_type, alloc_call); - /* While we're working, use a pointer to the type we've actually - allocated. Store the result of the call in a variable so that we - can use it more than once. */ - full_pointer_type = build_pointer_type (full_type); - alloc_expr = get_target_expr (build_nop (full_pointer_type, alloc_call)); + /* Store the result of the allocation call in a variable so that we can + use it more than once. */ + alloc_expr = get_target_expr (alloc_call); alloc_node = TARGET_EXPR_SLOT (alloc_expr); /* Strip any COMPOUND_EXPRs from ALLOC_CALL. */ @@ -2103,17 +2147,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, tree size_ptr_type; /* Adjust so we're pointing to the start of the object. */ - data_addr = get_target_expr (build2 (POINTER_PLUS_EXPR, full_pointer_type, - alloc_node, cookie_size)); + data_addr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (alloc_node), + alloc_node, cookie_size); /* Store the number of bytes allocated so that we can know how many elements to destroy later. We use the last sizeof (size_t) bytes to store the number of elements. */ - cookie_ptr = fold_build1 (NEGATE_EXPR, sizetype, size_in_bytes (sizetype)); + cookie_ptr = size_binop (MINUS_EXPR, cookie_size, size_in_bytes (sizetype)); + cookie_ptr = fold_build2_loc (input_location, + POINTER_PLUS_EXPR, TREE_TYPE (alloc_node), + alloc_node, cookie_ptr); size_ptr_type = build_pointer_type (sizetype); - cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, - fold_convert (size_ptr_type, data_addr), cookie_ptr); - cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain); + cookie_ptr = fold_convert (size_ptr_type, cookie_ptr); + cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain); cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts); @@ -2121,16 +2167,16 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, { /* Also store the element size. */ cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, cookie_ptr, - fold_build1 (NEGATE_EXPR, sizetype, + fold_build1_loc (input_location, + NEGATE_EXPR, sizetype, size_in_bytes (sizetype))); - cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain); + cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain); cookie = build2 (MODIFY_EXPR, sizetype, cookie, - size_in_bytes(elt_type)); + size_in_bytes (elt_type)); cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr), cookie, cookie_expr); } - data_addr = TARGET_EXPR_SLOT (data_addr); } else { @@ -2138,6 +2184,17 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, data_addr = alloc_node; } + /* Now use a pointer to the type we've actually allocated. */ + + /* But we want to operate on a non-const version to start with, + since we'll be modifying the elements. */ + non_const_pointer_type = build_pointer_type + (cp_build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_CONST)); + + data_addr = fold_convert (non_const_pointer_type, data_addr); + /* Any further uses of alloc_node will want this type, too. */ + alloc_node = fold_convert (non_const_pointer_type, alloc_node); + /* Now initialize the allocated object. Note that we preevaluate the initialization expression, apart from the actual constructor call or assignment--we do this because we want to delay the allocation as long @@ -2146,32 +2203,51 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (is_initialized) { bool stable; + bool explicit_value_init_p = false; - init_expr = cp_build_indirect_ref (data_addr, NULL, complain); + if (*init != NULL && VEC_empty (tree, *init)) + { + *init = NULL; + explicit_value_init_p = true; + } if (array_p) { - bool explicit_default_init_p = false; - - if (init == void_zero_node) + tree vecinit = NULL_TREE; + if (*init && VEC_length (tree, *init) == 1 + && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *init, 0)) + && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *init, 0))) { - init = NULL_TREE; - explicit_default_init_p = true; + tree arraytype, domain; + vecinit = VEC_index (tree, *init, 0); + if (TREE_CONSTANT (nelts)) + domain = compute_array_index_type (NULL_TREE, nelts); + else + { + domain = NULL_TREE; + if (CONSTRUCTOR_NELTS (vecinit) > 0) + warning (0, "non-constant array size in new, unable to " + "verify length of initializer-list"); + } + arraytype = build_cplus_array_type (type, domain); + vecinit = digest_init (arraytype, vecinit); } - else if (init) + else if (*init) { if (complain & tf_error) - pedwarn ("ISO C++ forbids initialization in array new"); + permerror (input_location, "ISO C++ forbids initialization in array new"); else return error_mark_node; + vecinit = build_tree_list_vec (*init); } init_expr - = build_vec_init (init_expr, - cp_build_binary_op (MINUS_EXPR, outer_nelts, + = build_vec_init (data_addr, + cp_build_binary_op (input_location, + MINUS_EXPR, outer_nelts, integer_one_node, complain), - init, - explicit_default_init_p, + vecinit, + explicit_value_init_p, /*from_array=*/0, complain); @@ -2182,34 +2258,34 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, } else { - if (init == void_zero_node) - init = build_default_init (full_type, nelts); + init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain); - if (TYPE_NEEDS_CONSTRUCTING (type)) + if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p) { init_expr = build_special_member_call (init_expr, complete_ctor_identifier, init, elt_type, LOOKUP_NORMAL, complain); - stable = stabilize_init (init_expr, &init_preeval_expr); + } + else if (explicit_value_init_p) + { + /* Something like `new int()'. */ + init_expr = build2 (INIT_EXPR, type, + init_expr, build_value_init (type)); } else { + tree ie; + /* We are processing something like `new int (10)', which means allocate an int, and initialize it with 10. */ - if (TREE_CODE (init) == TREE_LIST) - init = build_x_compound_expr_from_list (init, - "new initializer"); - else - gcc_assert (TREE_CODE (init) != CONSTRUCTOR - || TREE_TYPE (init) != NULL_TREE); - - init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init, + ie = build_x_compound_expr_from_vec (*init, "new initializer"); + init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, ie, complain); - stable = stabilize_init (init_expr, &init_preeval_expr); } + stable = stabilize_init (init_expr, &init_preeval_expr); } if (init_expr == error_mark_node) @@ -2231,19 +2307,27 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, /* The Standard is unclear here, but the right thing to do is to use the same method for finding deallocation functions that we use for finding allocation functions. */ - cleanup = build_op_delete_call (dcode, alloc_node, size, - globally_qualified_p, - (placement_allocation_fn_p - ? alloc_call : NULL_TREE), - alloc_fn); + cleanup = (build_op_delete_call + (dcode, + alloc_node, + size, + globally_qualified_p, + placement_allocation_fn_p ? alloc_call : NULL_TREE, + alloc_fn)); if (!cleanup) /* We're done. */; else if (stable) /* This is much simpler if we were able to preevaluate all of the arguments to the constructor call. */ - init_expr = build2 (TRY_CATCH_EXPR, void_type_node, - init_expr, cleanup); + { + /* CLEANUP is compiler-generated, so no diagnostics. */ + TREE_NO_WARNING (cleanup) = true; + init_expr = build2 (TRY_CATCH_EXPR, void_type_node, + init_expr, cleanup); + /* Likewise, this try-catch is compiler-generated. */ + TREE_NO_WARNING (init_expr) = true; + } else /* Ack! First we allocate the memory. Then we set our sentry variable to true, and expand a cleanup that deletes the @@ -2263,6 +2347,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, sentry = TARGET_EXPR_SLOT (begin); + /* CLEANUP is compiler-generated, so no diagnostics. */ + TREE_NO_WARNING (cleanup) = true; + TARGET_EXPR_CLEANUP (begin) = build3 (COND_EXPR, void_type_node, sentry, cleanup, void_zero_node); @@ -2274,8 +2361,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, = build2 (COMPOUND_EXPR, void_type_node, begin, build2 (COMPOUND_EXPR, void_type_node, init_expr, end)); + /* Likewise, this is compiler-generated. */ + TREE_NO_WARNING (init_expr) = true; } - } } else @@ -2290,7 +2378,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (cookie_expr) rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval); - if (rval == alloc_node) + if (rval == data_addr) /* If we don't have an initializer or a cookie, strip the TARGET_EXPR and return the call (which doesn't need to be adjusted). */ rval = TARGET_EXPR_INITIAL (alloc_expr); @@ -2298,7 +2386,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, { if (check_new) { - tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node, + tree ifexp = cp_build_binary_op (input_location, + NE_EXPR, alloc_node, integer_zero_node, complain); rval = build_conditional_expr (ifexp, rval, alloc_node, @@ -2313,59 +2402,58 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (init_preeval_expr) rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval); - /* Convert to the final type. */ - rval = build_nop (pointer_type, rval); - /* A new-expression is never an lvalue. */ gcc_assert (!lvalue_p (rval)); - if (placement != NULL) - rval = avoid_placement_new_aliasing (rval, placement_expr); - - return rval; + return convert (pointer_type, rval); } -/* Generate a representation for a C++ "new" expression. PLACEMENT is - a TREE_LIST of placement-new arguments (or NULL_TREE if none). If - NELTS is NULL, TYPE is the type of the storage to be allocated. If - NELTS is not NULL, then this is an array-new allocation; TYPE is - the type of the elements in the array and NELTS is the number of - elements in the array. INIT, if non-NULL, is the initializer for - the new object, or void_zero_node to indicate an initializer of - "()". If USE_GLOBAL_NEW is true, then the user explicitly wrote - "::new" rather than just "new". */ +/* Generate a representation for a C++ "new" expression. *PLACEMENT + is a vector of placement-new arguments (or NULL if none). If NELTS + is NULL, TYPE is the type of the storage to be allocated. If NELTS + is not NULL, then this is an array-new allocation; TYPE is the type + of the elements in the array and NELTS is the number of elements in + the array. *INIT, if non-NULL, is the initializer for the new + object, or an empty vector to indicate an initializer of "()". If + USE_GLOBAL_NEW is true, then the user explicitly wrote "::new" + rather than just "new". This may change PLACEMENT and INIT. */ tree -build_new (tree placement, tree type, tree nelts, tree init, - int use_global_new, tsubst_flags_t complain) +build_new (VEC(tree,gc) **placement, tree type, tree nelts, + VEC(tree,gc) **init, int use_global_new, tsubst_flags_t complain) { tree rval; - tree orig_placement; - tree orig_nelts; - tree orig_init; + VEC(tree,gc) *orig_placement = NULL; + tree orig_nelts = NULL_TREE; + VEC(tree,gc) *orig_init = NULL; - if (placement == error_mark_node || type == error_mark_node - || init == error_mark_node) + if (type == error_mark_node) return error_mark_node; - orig_placement = placement; - orig_nelts = nelts; - orig_init = init; + if (nelts == NULL_TREE && VEC_length (tree, *init) == 1) + { + tree auto_node = type_uses_auto (type); + if (auto_node && describable_type (VEC_index (tree, *init, 0))) + type = do_auto_deduction (type, VEC_index (tree, *init, 0), auto_node); + } if (processing_template_decl) { if (dependent_type_p (type) - || any_type_dependent_arguments_p (placement) + || any_type_dependent_arguments_p (*placement) || (nelts && type_dependent_expression_p (nelts)) - || (init != void_zero_node - && any_type_dependent_arguments_p (init))) - return build_raw_new_expr (placement, type, nelts, init, + || any_type_dependent_arguments_p (*init)) + return build_raw_new_expr (*placement, type, nelts, *init, use_global_new); - placement = build_non_dependent_args (placement); + + orig_placement = make_tree_vector_copy (*placement); + orig_nelts = nelts; + orig_init = make_tree_vector_copy (*init); + + make_args_non_dependent (*placement); if (nelts) nelts = build_non_dependent_expr (nelts); - if (init != void_zero_node) - init = build_non_dependent_args (init); + make_args_non_dependent (*init); } if (nelts) @@ -2373,7 +2461,7 @@ build_new (tree placement, tree type, tree nelts, tree init, if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false)) { if (complain & tf_error) - pedwarn ("size in array new must have integral type"); + permerror (input_location, "size in array new must have integral type"); else return error_mark_node; } @@ -2410,8 +2498,13 @@ build_new (tree placement, tree type, tree nelts, tree init, return error_mark_node; if (processing_template_decl) - return build_raw_new_expr (orig_placement, type, orig_nelts, orig_init, - use_global_new); + { + tree ret = build_raw_new_expr (orig_placement, type, orig_nelts, + orig_init, use_global_new); + release_tree_vector (orig_placement); + release_tree_vector (orig_init); + return ret; + } /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */ rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval); @@ -2460,7 +2553,8 @@ build_java_class_ref (tree type) class_decl = IDENTIFIER_GLOBAL_VALUE (name); if (class_decl == NULL_TREE) { - class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node)); + class_decl = build_decl (input_location, + VAR_DECL, name, TREE_TYPE (jclass_node)); TREE_STATIC (class_decl) = 1; DECL_EXTERNAL (class_decl) = 1; TREE_PUBLIC (class_decl) = 1; @@ -2512,11 +2606,11 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, tbase = create_temporary_var (ptype); tbase_init = cp_build_modify_expr (tbase, NOP_EXPR, - fold_build2 (POINTER_PLUS_EXPR, ptype, + fold_build2_loc (input_location, + POINTER_PLUS_EXPR, ptype, fold_convert (ptype, base), virtual_size), tf_warning_or_error); - DECL_REGISTER (tbase) = 1; controller = build3 (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (controller) = 1; @@ -2524,17 +2618,19 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, body = build1 (EXIT_EXPR, void_type_node, build2 (EQ_EXPR, boolean_type_node, tbase, fold_convert (ptype, base))); - tmp = fold_build1 (NEGATE_EXPR, sizetype, size_exp); + tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp); body = build_compound_expr - (body, cp_build_modify_expr (tbase, NOP_EXPR, + (input_location, + body, cp_build_modify_expr (tbase, NOP_EXPR, build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp), tf_warning_or_error)); body = build_compound_expr - (body, build_delete (ptype, tbase, sfk_complete_destructor, + (input_location, + body, build_delete (ptype, tbase, sfk_complete_destructor, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1)); loop = build1 (LOOP_EXPR, void_type_node, body); - loop = build_compound_expr (tbase_init, loop); + loop = build_compound_expr (input_location, tbase_init, loop); no_destructor: /* If the delete flag is one, or anything else with the low bit set, @@ -2557,7 +2653,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, cookie_size = targetm.cxx.get_cookie_size (type); base_tbd = cp_convert (ptype, - cp_build_binary_op (MINUS_EXPR, + cp_build_binary_op (input_location, + MINUS_EXPR, cp_convert (string_type_node, base), cookie_size, @@ -2580,14 +2677,15 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, else if (!body) body = deallocate_expr; else - body = build_compound_expr (body, deallocate_expr); + body = build_compound_expr (input_location, body, deallocate_expr); if (!body) body = integer_zero_node; /* Outermost wrapper: If pointer is null, punt. */ - body = fold_build3 (COND_EXPR, void_type_node, - fold_build2 (NE_EXPR, boolean_type_node, base, + body = fold_build3_loc (input_location, COND_EXPR, void_type_node, + fold_build2_loc (input_location, + NE_EXPR, boolean_type_node, base, convert (TREE_TYPE (base), integer_zero_node)), body, integer_zero_node); @@ -2613,11 +2711,11 @@ create_temporary_var (tree type) { tree decl; - decl = build_decl (VAR_DECL, NULL_TREE, type); + decl = build_decl (input_location, + VAR_DECL, NULL_TREE, type); TREE_USED (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; - DECL_SOURCE_LOCATION (decl) = input_location; DECL_CONTEXT (decl) = current_function_decl; return decl; @@ -2647,15 +2745,16 @@ get_temp_regvar (tree type, tree init) /* `build_vec_init' returns tree structure that performs initialization of a vector of aggregate types. - BASE is a reference to the vector, of ARRAY_TYPE. + BASE is a reference to the vector, of ARRAY_TYPE, or a pointer + to the first element, of POINTER_TYPE. MAXINDEX is the maximum index of the array (one less than the - number of elements). It is only used if + number of elements). It is only used if BASE is a pointer or TYPE_DOMAIN (TREE_TYPE (BASE)) == NULL_TREE. INIT is the (possibly NULL) initializer. - If EXPLICIT_DEFAULT_INIT_P is true, then INIT must be NULL. All - elements in the array are default-initialized. + If EXPLICIT_VALUE_INIT_P is true, then INIT must be NULL. All + elements in the array are value-initialized. FROM_ARRAY is 0 if we should init everything with INIT (i.e., every element initialized from INIT). @@ -2666,15 +2765,14 @@ get_temp_regvar (tree type, tree init) tree build_vec_init (tree base, tree maxindex, tree init, - bool explicit_default_init_p, + bool explicit_value_init_p, int from_array, tsubst_flags_t complain) { tree rval; tree base2 = NULL_TREE; - tree size; tree itype = NULL_TREE; tree iterator; - /* The type of the array. */ + /* The type of BASE. */ tree atype = TREE_TYPE (base); /* The type of an element in the array. */ tree type = TREE_TYPE (atype); @@ -2690,17 +2788,25 @@ build_vec_init (tree base, tree maxindex, tree init, int num_initialized_elts = 0; bool is_global; - if (TYPE_DOMAIN (atype)) + if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype)) maxindex = array_type_nelts (atype); if (maxindex == NULL_TREE || maxindex == error_mark_node) return error_mark_node; - if (explicit_default_init_p) + if (explicit_value_init_p) gcc_assert (!init); - inner_elt_type = strip_array_types (atype); + inner_elt_type = strip_array_types (type); + + /* Look through the TARGET_EXPR around a compound literal. */ + if (init && TREE_CODE (init) == TARGET_EXPR + && TREE_CODE (TARGET_EXPR_INITIAL (init)) == CONSTRUCTOR + && from_array != 2) + init = TARGET_EXPR_INITIAL (init); + if (init + && TREE_CODE (atype) == ARRAY_TYPE && (from_array == 2 ? (!CLASS_TYPE_P (inner_elt_type) || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type)) @@ -2712,7 +2818,7 @@ build_vec_init (tree base, tree maxindex, tree init, || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type))) || from_array)) { - /* Do non-default initialization of POD arrays resulting from + /* Do non-default initialization of trivial arrays resulting from brace-enclosed initializers. In this case, digest_init and store_constructor will handle the semantics for us. */ @@ -2721,10 +2827,13 @@ build_vec_init (tree base, tree maxindex, tree init, } maxindex = cp_convert (ptrdiff_type_node, maxindex); - ptype = build_pointer_type (type); - size = size_in_bytes (type); - if (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE) - base = cp_convert (ptype, decay_conversion (base)); + if (TREE_CODE (atype) == ARRAY_TYPE) + { + ptype = build_pointer_type (type); + base = cp_convert (ptype, decay_conversion (base)); + } + else + ptype = atype; /* The code we are generating looks like: ({ @@ -2763,6 +2872,17 @@ build_vec_init (tree base, tree maxindex, tree init, base = get_temp_regvar (ptype, rval); iterator = get_temp_regvar (ptrdiff_type_node, maxindex); + /* If initializing one array from another, initialize element by + element. We rely upon the below calls to do the argument + checking. Evaluate the initializer before entering the try block. */ + if (from_array && init && TREE_CODE (init) != CONSTRUCTOR) + { + base2 = decay_conversion (init); + itype = TREE_TYPE (base2); + base2 = get_temp_regvar (itype, base2); + itype = TREE_TYPE (itype); + } + /* Protect the entire array initialization so that we can destroy the partially constructed array if an exception is thrown. But don't do this if we're assigning. */ @@ -2774,7 +2894,7 @@ build_vec_init (tree base, tree maxindex, tree init, if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR) { - /* Do non-default initialization of non-POD arrays resulting from + /* Do non-default initialization of non-trivial arrays resulting from brace-enclosed initializers. */ unsigned HOST_WIDE_INT idx; tree elt; @@ -2805,16 +2925,8 @@ build_vec_init (tree base, tree maxindex, tree init, } else if (from_array) { - /* If initializing one array from another, initialize element by - element. We rely upon the below calls the do argument - checking. */ if (init) - { - base2 = decay_conversion (init); - itype = TREE_TYPE (base2); - base2 = get_temp_regvar (itype, base2); - itype = TREE_TYPE (itype); - } + /* OK, we set base2 above. */; else if (TYPE_LANG_SPECIFIC (type) && TYPE_NEEDS_CONSTRUCTING (type) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) @@ -2832,7 +2944,7 @@ build_vec_init (tree base, tree maxindex, tree init, We do need to keep going if we're copying an array. */ if (from_array - || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_default_init_p) + || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p) && ! (host_integerp (maxindex, 0) && (num_initialized_elts == tree_low_cst (maxindex, 0) + 1)))) @@ -2881,17 +2993,17 @@ build_vec_init (tree base, tree maxindex, tree init, ("cannot initialize multi-dimensional array with initializer"); elt_init = build_vec_init (build1 (INDIRECT_REF, type, base), 0, 0, - /*explicit_default_init_p=*/false, + explicit_value_init_p, 0, complain); } - else if (!TYPE_NEEDS_CONSTRUCTING (type)) - elt_init = (cp_build_modify_expr - (to, INIT_EXPR, - build_zero_init (type, size_one_node, - /*static_storage_p=*/false), - complain)); + else if (explicit_value_init_p) + elt_init = build2 (INIT_EXPR, type, to, + build_value_init (type)); else - elt_init = build_aggr_init (to, init, 0, complain); + { + gcc_assert (TYPE_NEEDS_CONSTRUCTING (type)); + elt_init = build_aggr_init (to, init, 0, complain); + } current_stmt_tree ()->stmts_are_full_exprs_p = 1; finish_expr_stmt (elt_init); @@ -2911,13 +3023,15 @@ build_vec_init (tree base, tree maxindex, tree init, && from_array != 2) { tree e; - tree m = cp_build_binary_op (MINUS_EXPR, maxindex, iterator, + tree m = cp_build_binary_op (input_location, + MINUS_EXPR, maxindex, iterator, complain); /* Flatten multi-dimensional array since build_vec_delete only expects one-dimensional array. */ if (TREE_CODE (type) == ARRAY_TYPE) - m = cp_build_binary_op (MULT_EXPR, m, + m = cp_build_binary_op (input_location, + MULT_EXPR, m, array_type_nelts_total (type), complain); @@ -2934,10 +3048,14 @@ build_vec_init (tree base, tree maxindex, tree init, stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); - /* Now convert make the result have the correct type. */ - atype = build_pointer_type (atype); - stmt_expr = build1 (NOP_EXPR, atype, stmt_expr); - stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain); + /* Now make the result have the correct type. */ + if (TREE_CODE (atype) == ARRAY_TYPE) + { + atype = build_pointer_type (atype); + stmt_expr = build1 (NOP_EXPR, atype, stmt_expr); + stmt_expr = cp_build_indirect_ref (stmt_expr, RO_NULL, complain); + TREE_NO_WARNING (stmt_expr) = 1; + } current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps; return stmt_expr; @@ -2970,7 +3088,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags) } fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2); return build_new_method_call (exp, fn, - /*args=*/NULL_TREE, + /*args=*/NULL, /*conversion_path=*/NULL_TREE, flags, /*fn_p=*/NULL, @@ -3021,12 +3139,14 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, complete_type (type); if (!COMPLETE_TYPE_P (type)) { - warning (0, "possible problem detected in invocation of " - "delete operator:"); - cxx_incomplete_type_diagnostic (addr, type, 1); - inform ("neither the destructor nor the class-specific " - "operator delete will be called, even if they are " - "declared when the class is defined."); + if (warning (0, "possible problem detected in invocation of " + "delete operator:")) + { + cxx_incomplete_type_diagnostic (addr, type, DK_WARNING); + inform (input_location, "neither the destructor nor the class-specific " + "operator delete will be called, even if they are " + "declared when the class is defined."); + } complete_p = false; } } @@ -3128,7 +3248,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, /*alloc_fn=*/NULL_TREE); } - expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, + expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, tf_warning_or_error), auto_delete, flags); if (do_delete) @@ -3143,7 +3263,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, ifexp = integer_one_node; else /* Handle deleting a null pointer. */ - ifexp = fold (cp_build_binary_op (NE_EXPR, addr, integer_zero_node, + ifexp = fold (cp_build_binary_op (input_location, + NE_EXPR, addr, integer_zero_node, tf_warning_or_error)); if (ifexp != integer_one_node) @@ -3185,7 +3306,7 @@ push_base_cleanups (void) { expr = build_special_member_call (current_class_ref, base_dtor_identifier, - NULL_TREE, + NULL, base_binfo, (LOOKUP_NORMAL | LOOKUP_NONVIRTUAL), @@ -3207,7 +3328,7 @@ push_base_cleanups (void) expr = build_special_member_call (current_class_ref, base_dtor_identifier, - NULL_TREE, base_binfo, + NULL, base_binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error); finish_decl_cleanup (NULL_TREE, expr); @@ -3267,6 +3388,7 @@ build_vec_delete (tree base, tree maxindex, { /* Step back one from start of vector, and read dimension. */ tree cookie_addr; + tree size_ptr_type = build_pointer_type (sizetype); if (TREE_SIDE_EFFECTS (base)) { @@ -3274,12 +3396,13 @@ build_vec_delete (tree base, tree maxindex, base = TARGET_EXPR_SLOT (base_init); } type = strip_array_types (TREE_TYPE (type)); - cookie_addr = fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (sizetype)); + cookie_addr = fold_build1_loc (input_location, NEGATE_EXPR, + sizetype, TYPE_SIZE_UNIT (sizetype)); cookie_addr = build2 (POINTER_PLUS_EXPR, - build_pointer_type (sizetype), - base, + size_ptr_type, + fold_convert (size_ptr_type, base), cookie_addr); - maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error); + maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error); } else if (TREE_CODE (type) == ARRAY_TYPE) {