X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Finit.c;h=5f30275ae5bb6d944069b43ff1f77fc072ec778a;hp=5091d4e749eaba3806349ddc1a475e3e013c2d35;hb=9d0d0b57496b31ddbe66490e7cb35031a52aa449;hpb=d6fbd579a13ed232f0d25237c7d661fe00780f83 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 5091d4e749e..5f30275ae5b 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 - Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -30,7 +30,6 @@ along with GCC; see the file COPYING3. If not see #include "cp-tree.h" #include "flags.h" #include "output.h" -#include "toplev.h" #include "target.h" static bool begin_init_stmts (tree *, tree *); @@ -38,7 +37,6 @@ static tree finish_init_stmts (bool, tree, tree); static void construct_virtual_base (tree, tree); static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); -static tree build_vec_delete_1 (tree, tree, tree, special_function_kind, int); static void perform_member_init (tree, tree); static tree build_builtin_delete_call (tree); static int member_init_ok_or_else (tree, tree, tree); @@ -46,9 +44,7 @@ static void expand_virtual_init (tree, tree); static tree sort_mem_initializers (tree, tree); static tree initializing_context (tree); static void expand_cleanup_for_base (tree, tree); -static tree get_temp_regvar (tree, tree); 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 int diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool, bool); @@ -141,10 +137,13 @@ initialize_vtbl_ptrs (tree addr) is the number of elements in the array. If STATIC_STORAGE_P is TRUE, initializers are only generated for entities for which zero-initialization does not simply mean filling the storage with - zero bytes. */ + 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. */ -tree -build_zero_init (tree type, tree nelts, bool static_storage_p) +static tree +build_zero_init_1 (tree type, tree nelts, bool static_storage_p, + tree field_size) { tree init = NULL_TREE; @@ -189,15 +188,32 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) if (TREE_CODE (field) != FIELD_DECL) continue; + /* Don't add virtual bases for base classes if they are beyond + the size of the current field, that means it is present + somewhere else in the object. */ + if (field_size) + { + tree bitpos = bit_position (field); + if (TREE_CODE (bitpos) == INTEGER_CST + && !tree_int_cst_lt (bitpos, field_size)) + continue; + } + /* Note that for class types there will be FIELD_DECLs corresponding to base classes as well. Thus, iterating over TYPE_FIELDs will result in correct initialization of all of the subobjects. */ if (!static_storage_p || !zero_init_p (TREE_TYPE (field))) { - tree value = build_zero_init (TREE_TYPE (field), - /*nelts=*/NULL_TREE, - static_storage_p); + tree new_field_size + = (DECL_FIELD_IS_BASE (field) + && DECL_SIZE (field) + && TREE_CODE (DECL_SIZE (field)) == INTEGER_CST) + ? DECL_SIZE (field) : NULL_TREE; + tree value = build_zero_init_1 (TREE_TYPE (field), + /*nelts=*/NULL_TREE, + static_storage_p, + new_field_size); if (value) CONSTRUCTOR_APPEND_ELT(v, field, value); } @@ -245,16 +261,16 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index); - ce->value = build_zero_init (TREE_TYPE (type), - /*nelts=*/NULL_TREE, - static_storage_p); + ce->value = build_zero_init_1 (TREE_TYPE (type), + /*nelts=*/NULL_TREE, + static_storage_p, NULL_TREE); } /* Build a constructor to contain the initializations. */ init = build_constructor (type, v); } else if (TREE_CODE (type) == VECTOR_TYPE) - init = fold_convert (type, integer_zero_node); + init = build_zero_cst (type); else gcc_assert (TREE_CODE (type) == REFERENCE_TYPE); @@ -265,6 +281,24 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) return init; } +/* Return an expression for the zero-initialization of an object with + type T. This expression will either be a constant (in the case + that T is a scalar), or a CONSTRUCTOR (in the case that T is an + aggregate), or NULL (in the case that T does not require + initialization). In either case, the value can be used as + DECL_INITIAL for a decl of the indicated TYPE; it is a valid static + initializer. If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS + is the number of elements in the array. If STATIC_STORAGE_P is + TRUE, initializers are only generated for entities for which + zero-initialization does not simply mean filling the storage with + zero bytes. */ + +tree +build_zero_init (tree type, tree nelts, bool static_storage_p) +{ + return build_zero_init_1 (type, nelts, static_storage_p, NULL_TREE); +} + /* Return a suitable initializer for value-initializing an object of type TYPE, as described in [dcl.init]. */ @@ -305,8 +339,9 @@ build_value_init (tree type, tsubst_flags_t complain) (type, build_special_member_call (NULL_TREE, complete_ctor_identifier, NULL, type, LOOKUP_NORMAL, - complain)); - else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type)) + complain), + complain); + else if (type_build_ctor_call (type)) { /* This is a class that needs constructing, but doesn't have a user-provided constructor. So we need to zero-initialize @@ -315,9 +350,11 @@ 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); - AGGR_INIT_ZERO_FIRST (ctor) = 1; + if (ctor != error_mark_node) + { + ctor = build_aggr_init_expr (type, ctor, complain); + AGGR_INIT_ZERO_FIRST (ctor) = 1; + } return ctor; } } @@ -330,9 +367,11 @@ build_value_init (tree type, tsubst_flags_t complain) tree build_value_init_noctor (tree type, tsubst_flags_t complain) { + /* FIXME the class and array cases should just use digest_init once it is + SFINAE-enabled. */ if (CLASS_TYPE_P (type)) { - gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type)); + gcc_assert (!type_build_ctor_call (type)); if (TREE_CODE (type) != UNION_TYPE) { @@ -349,14 +388,6 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) ftype = TREE_TYPE (field); - if (TREE_CODE (ftype) == REFERENCE_TYPE) - { - if (complain & tf_error) - error ("value-initialization of reference"); - else - return error_mark_node; - } - /* We could skip vfields and fields of types with user-defined constructors, but I think that won't improve performance at all; it should be simpler in general just @@ -369,6 +400,9 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) all of the subobjects. */ value = build_value_init (ftype, complain); + if (value == error_mark_node) + return error_mark_node; + if (value) CONSTRUCTOR_APPEND_ELT(v, field, value); } @@ -388,7 +422,9 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) as we don't know the size of the array yet. */ if (max_index == error_mark_node) { - error ("cannot value-initialize array of unknown bound %qT", type); + if (complain & tf_error) + error ("cannot value-initialize array of unknown bound %qT", + type); return error_mark_node; } gcc_assert (TREE_CODE (max_index) == INTEGER_CST); @@ -411,7 +447,12 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) ce->value = build_value_init (TREE_TYPE (type), complain); - /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */ + if (ce->value == error_mark_node) + return error_mark_node; + + /* We shouldn't have gotten here for anything that would need + non-trivial initialization, and gimplify_init_ctor_preeval + would need to be fixed to allow it. */ gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR && TREE_CODE (ce->value) != AGGR_INIT_EXPR); } @@ -419,6 +460,18 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) /* Build a constructor to contain the initializations. */ return build_constructor (type, v); } + else if (TREE_CODE (type) == FUNCTION_TYPE) + { + if (complain & tf_error) + error ("value-initialization of function type %qT", type); + return error_mark_node; + } + else if (TREE_CODE (type) == REFERENCE_TYPE) + { + if (complain & tf_error) + error ("value-initialization of reference type %qT", type); + return error_mark_node; + } return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); } @@ -448,29 +501,33 @@ perform_member_init (tree member, tree init) if (decl == error_mark_node) return; + if (warn_init_self && init && TREE_CODE (init) == TREE_LIST + && TREE_CHAIN (init) == NULL_TREE) + { + tree val = TREE_VALUE (init); + if (TREE_CODE (val) == COMPONENT_REF && TREE_OPERAND (val, 1) == member + && TREE_OPERAND (val, 0) == current_class_ref) + warning_at (DECL_SOURCE_LOCATION (current_function_decl), + OPT_Wuninitialized, "%qD is initialized with itself", + member); + } + 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); + init = build_vec_init_expr (type, init, tf_warning_or_error); + init = build2 (INIT_EXPR, type, decl, init); 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, tf_warning_or_error)); - finish_expr_stmt (init); - } + tree value = build_value_init (type, tf_warning_or_error); + if (value == error_mark_node) + return; + init = build2 (INIT_EXPR, type, decl, value); + finish_expr_stmt (init); } } /* Deal with this here, as we will get confused if we try to call the @@ -484,21 +541,31 @@ perform_member_init (tree member, tree init) finish_expr_stmt (init); } } - else if (TYPE_NEEDS_CONSTRUCTING (type)) + else if (type_build_ctor_call (type)) { - if (init != NULL_TREE - && TREE_CODE (type) == ARRAY_TYPE - && TREE_CHAIN (init) == NULL_TREE - && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE) + if (TREE_CODE (type) == ARRAY_TYPE) { - /* Initialization of one array from another. */ - finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init), - /*explicit_value_init_p=*/false, - /* from_array=*/1, - tf_warning_or_error)); + if (init) + { + gcc_assert (TREE_CHAIN (init) == NULL_TREE); + init = TREE_VALUE (init); + } + if (init == NULL_TREE + || same_type_ignoring_top_level_qualifiers_p (type, + TREE_TYPE (init))) + { + init = build_vec_init_expr (type, init, tf_warning_or_error); + init = build2 (INIT_EXPR, type, decl, init); + finish_expr_stmt (init); + } + else + error ("invalid initializer for array member %q#D", member); } else { + int flags = LOOKUP_NORMAL; + if (DECL_DEFAULTED_FN (current_function_decl)) + flags |= LOOKUP_DEFAULTED; if (CP_TYPE_CONST_P (type) && init == NULL_TREE && !type_has_user_provided_default_constructor (type)) @@ -507,7 +574,7 @@ perform_member_init (tree member, tree init) permerror (DECL_SOURCE_LOCATION (current_function_decl), "uninitialized member %qD with % type %qT", member, type); - finish_expr_stmt (build_aggr_init (decl, init, 0, + finish_expr_stmt (build_aggr_init (decl, init, flags, tf_warning_or_error)); } } @@ -527,6 +594,16 @@ perform_member_init (tree member, tree init) member, type); core_type = strip_array_types (type); + + if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) + && !type_has_constexpr_default_constructor (core_type)) + { + if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl)) + error ("uninitialized member %qD in % constructor", + member); + DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false; + } + if (CLASS_TYPE_P (core_type) && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type) || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))) @@ -554,7 +631,8 @@ perform_member_init (tree member, tree init) /*preserve_reference=*/false, tf_warning_or_error); expr = build_delete (type, expr, sfk_complete_destructor, - LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, + tf_warning_or_error); if (expr != error_mark_node) finish_eh_cleanup (expr); @@ -839,11 +917,16 @@ sort_mem_initializers (tree t, tree mem_inits) void emit_mem_initializers (tree mem_inits) { + int flags = LOOKUP_NORMAL; + /* We will already have issued an error message about the fact that the type is incomplete. */ if (!COMPLETE_TYPE_P (current_class_type)) return; + if (DECL_DEFAULTED_FN (current_function_decl)) + flags |= LOOKUP_DEFAULTED; + /* Sort the mem-initializers into the order in which the initializations should be performed. */ mem_inits = sort_mem_initializers (current_class_type, mem_inits); @@ -857,17 +940,30 @@ emit_mem_initializers (tree mem_inits) tree subobject = TREE_PURPOSE (mem_inits); tree arguments = TREE_VALUE (mem_inits); - /* If these initializations are taking place in a copy constructor, - the base class should probably be explicitly initialized if there - is a user-defined constructor in the base class (other than the - default constructor, which will be called anyway). */ - if (extra_warnings && !arguments - && DECL_COPY_CONSTRUCTOR_P (current_function_decl) - && type_has_user_nondefault_constructor (BINFO_TYPE (subobject))) - 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)); + if (arguments == NULL_TREE) + { + /* If these initializations are taking place in a copy constructor, + the base class should probably be explicitly initialized if there + is a user-defined constructor in the base class (other than the + default constructor, which will be called anyway). */ + if (extra_warnings + && DECL_COPY_CONSTRUCTOR_P (current_function_decl) + && type_has_user_nondefault_constructor (BINFO_TYPE (subobject))) + 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)); + + if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) + && !(type_has_constexpr_default_constructor + (BINFO_TYPE (subobject)))) + { + if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl)) + error ("uninitialized base %qT in % constructor", + BINFO_TYPE (subobject)); + DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false; + } + } /* Initialize the base. */ if (BINFO_VIRTUAL_P (subobject)) @@ -882,7 +978,7 @@ emit_mem_initializers (tree mem_inits) cp_build_indirect_ref (base_addr, RO_NULL, tf_warning_or_error), arguments, - LOOKUP_NORMAL, + flags, tf_warning_or_error); expand_cleanup_for_base (subobject, NULL_TREE); } @@ -1350,7 +1446,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, { /* A brace-enclosed initializer for an aggregate. In C++0x this can happen for direct-initialization, too. */ - init = digest_init (type, init); + init = digest_init (type, init, complain); init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); @@ -1411,8 +1507,20 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, if (parms != NULL) release_tree_vector (parms); + if (exp == true_exp && TREE_CODE (rval) == CALL_EXPR) + { + tree fn = get_callee_fndecl (rval); + if (fn && DECL_DECLARED_CONSTEXPR_P (fn)) + { + tree e = maybe_constant_value (rval); + if (TREE_CONSTANT (e)) + rval = build2 (INIT_EXPR, type, exp, e); + } + } + + /* FIXME put back convert_to_void? */ if (TREE_SIDE_EFFECTS (rval)) - finish_expr_stmt (convert_to_void (rval, ICV_CAST, complain)); + finish_expr_stmt (rval); } /* This function is responsible for initializing EXP with INIT @@ -1471,7 +1579,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* 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)) + else if (type_build_ctor_call (type)) { init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); init = build2 (INIT_EXPR, type, exp, init); @@ -1679,36 +1787,18 @@ constant_value_1 (tree decl, bool integral_p) { while (TREE_CODE (decl) == CONST_DECL || (integral_p - ? DECL_INTEGRAL_CONSTANT_VAR_P (decl) + ? decl_constant_var_p (decl) : (TREE_CODE (decl) == VAR_DECL && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))))) { tree init; - /* Static data members in template classes may have - non-dependent initializers. References to such non-static - data members are not value-dependent, so we must retrieve the - initializer here. The DECL_INITIAL will have the right type, - but will not have been folded because that would prevent us - from performing all appropriate semantic checks at - instantiation time. */ - if (DECL_CLASS_SCOPE_P (decl) - && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl)) - && uses_template_parms (CLASSTYPE_TI_ARGS - (DECL_CONTEXT (decl)))) - { - ++processing_template_decl; - init = fold_non_dependent_expr (DECL_INITIAL (decl)); - --processing_template_decl; - } - else - { - /* If DECL is a static data member in a template - specialization, we must instantiate it here. The - initializer for the static data member is not processed - until needed; we need it now. */ - mark_used (decl); - init = DECL_INITIAL (decl); - } + /* If DECL is a static data member in a template + specialization, we must instantiate it here. The + initializer for the static data member is not processed + until needed; we need it now. */ + mark_used (decl); + mark_rvalue_use (decl); + init = DECL_INITIAL (decl); if (init == error_mark_node) { if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) @@ -1729,16 +1819,15 @@ constant_value_1 (tree decl, bool integral_p) init = TREE_VALUE (init); if (!init || !TREE_TYPE (init) - || (integral_p - ? !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init)) - : (!TREE_CONSTANT (init) - /* Do not return an aggregate constant (of which - string literals are a special case), as we do not - want to make inadvertent copies of such entities, - and we must be sure that their addresses are the - same everywhere. */ - || TREE_CODE (init) == CONSTRUCTOR - || TREE_CODE (init) == STRING_CST))) + || !TREE_CONSTANT (init) + || (!integral_p + /* Do not return an aggregate constant (of which + string literals are a special case), as we do not + want to make inadvertent copies of such entities, + and we must be sure that their addresses are the + same everywhere. */ + && (TREE_CODE (init) == CONSTRUCTOR + || TREE_CODE (init) == STRING_CST))) break; decl = unshare_expr (init); } @@ -1837,6 +1926,9 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin, field_type = strip_array_types (TREE_TYPE (field)); + if (type_has_user_provided_constructor (field_type)) + continue; + if (TREE_CODE (field_type) == REFERENCE_TYPE) { ++ error_count; @@ -1962,10 +2054,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, return error_mark_node; } - if (abstract_virtuals_error (NULL_TREE, elt_type)) + if (abstract_virtuals_error_sfinae (NULL_TREE, elt_type, complain)) return error_mark_node; - is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL); + is_initialized = (type_build_ctor_call (elt_type) || *init != NULL); if (*init == NULL) { @@ -2263,7 +2355,22 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, explicit_value_init_p = true; } - if (array_p) + if (processing_template_decl && explicit_value_init_p) + { + /* build_value_init doesn't work in templates, and we don't need + the initializer anyway since we're going to throw it away and + rebuild it at instantiation time, so just build up a single + constructor call to get any appropriate diagnostics. */ + init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain); + if (type_build_ctor_call (elt_type)) + 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 (array_p) { tree vecinit = NULL_TREE; if (*init && VEC_length (tree, *init) == 1 @@ -2273,7 +2380,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, tree arraytype, domain; vecinit = VEC_index (tree, *init, 0); if (TREE_CONSTANT (nelts)) - domain = compute_array_index_type (NULL_TREE, nelts); + domain = compute_array_index_type (NULL_TREE, nelts, complain); else { domain = NULL_TREE; @@ -2282,7 +2389,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, "verify length of initializer-list"); } arraytype = build_cplus_array_type (type, domain); - vecinit = digest_init (arraytype, vecinit); + vecinit = digest_init (arraytype, vecinit, complain); } else if (*init) { @@ -2312,8 +2419,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, { init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain); - if (TYPE_NEEDS_CONSTRUCTING (type) - && (!explicit_value_init_p || processing_template_decl)) + if (type_build_ctor_call (type) && !explicit_value_init_p) { init_expr = build_special_member_call (init_expr, complete_ctor_identifier, @@ -2323,17 +2429,11 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, } else if (explicit_value_init_p) { - if (processing_template_decl) - /* Don't worry about it, we'll handle this properly at - instantiation time. */; - else - { - /* Something like `new int()'. */ - tree val = build_value_init (type, complain); - if (val == error_mark_node) - return error_mark_node; - init_expr = build2 (INIT_EXPR, type, init_expr, val); - } + /* Something like `new int()'. */ + tree val = build_value_init (type, complain); + if (val == error_mark_node) + return error_mark_node; + init_expr = build2 (INIT_EXPR, type, init_expr, val); } else { @@ -2494,8 +2594,13 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts, 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 (auto_node) + { + tree d_init = VEC_index (tree, *init, 0); + d_init = resolve_nondeduced_context (d_init); + if (describable_type (d_init)) + type = do_auto_deduction (type, d_init, auto_node); + } } if (processing_template_decl) @@ -2607,7 +2712,7 @@ build_java_class_ref (tree type) } if (!field) { - error ("can't find % in %qT", type); + error ("can%'t find % in %qT", type); return error_mark_node; } } @@ -2630,7 +2735,8 @@ build_java_class_ref (tree type) static tree build_vec_delete_1 (tree base, tree maxindex, tree type, - special_function_kind auto_delete_vec, int use_global_delete) + special_function_kind auto_delete_vec, + int use_global_delete, tsubst_flags_t complain) { tree virtual_size; tree ptype = build_pointer_type (type = complete_type (type)); @@ -2659,6 +2765,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, /* We should only have 1-D arrays here. */ gcc_assert (TREE_CODE (type) != ARRAY_TYPE); + if (base == error_mark_node || maxindex == error_mark_node) + return error_mark_node; + if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) goto no_destructor; @@ -2672,7 +2781,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, POINTER_PLUS_EXPR, ptype, fold_convert (ptype, base), virtual_size), - tf_warning_or_error); + complain); + if (tbase_init == error_mark_node) + return error_mark_node; controller = build3 (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (controller) = 1; @@ -2681,23 +2792,24 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, build2 (EQ_EXPR, boolean_type_node, tbase, fold_convert (ptype, base))); tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp); - body = build_compound_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 - (input_location, - body, build_delete (ptype, tbase, sfk_complete_destructor, - LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1)); + tmp = build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp); + tmp = cp_build_modify_expr (tbase, NOP_EXPR, tmp, complain); + if (tmp == error_mark_node) + return error_mark_node; + body = build_compound_expr (input_location, body, tmp); + tmp = build_delete (ptype, tbase, sfk_complete_destructor, + LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1, + complain); + if (tmp == error_mark_node) + return error_mark_node; + body = build_compound_expr (input_location, body, tmp); loop = build1 (LOOP_EXPR, void_type_node, body); 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, - delete the storage. */ - if (auto_delete_vec != sfk_base_destructor) + /* Delete the storage if appropriate. */ + if (auto_delete_vec == sfk_deleting_destructor) { tree base_tbd; @@ -2713,24 +2825,24 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, tree cookie_size; cookie_size = targetm.cxx.get_cookie_size (type); - base_tbd - = cp_convert (ptype, - cp_build_binary_op (input_location, - MINUS_EXPR, - cp_convert (string_type_node, - base), - cookie_size, - tf_warning_or_error)); + base_tbd = cp_build_binary_op (input_location, + MINUS_EXPR, + cp_convert (string_type_node, + base), + cookie_size, + complain); + if (base_tbd == error_mark_node) + return error_mark_node; + base_tbd = cp_convert (ptype, base_tbd); /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size); } - if (auto_delete_vec == sfk_deleting_destructor) - deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR, - base_tbd, virtual_size, - use_global_delete & 1, - /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR, + base_tbd, virtual_size, + use_global_delete & 1, + /*placement=*/NULL_TREE, + /*alloc_fn=*/NULL_TREE); } body = loop; @@ -2763,7 +2875,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, /* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR. */ body = build2 (COMPOUND_EXPR, void_type_node, base, body); - return convert_to_void (body, ICV_CAST, tf_warning_or_error); + return convert_to_void (body, ICV_CAST, complain); } /* Create an unnamed variable of the indicated TYPE. */ @@ -2790,7 +2902,7 @@ create_temporary_var (tree type) things when it comes time to do final cleanups (which take place "outside" the binding contour of the function). */ -static tree +tree get_temp_regvar (tree type, tree init) { tree decl; @@ -2849,6 +2961,10 @@ build_vec_init (tree base, tree maxindex, tree init, tree try_block = NULL_TREE; int num_initialized_elts = 0; bool is_global; + tree const_init = NULL_TREE; + tree obase = base; + bool xvalue = false; + bool errors = false; if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype)) maxindex = array_type_nelts (atype); @@ -2939,6 +3055,8 @@ build_vec_init (tree base, tree maxindex, tree init, checking. Evaluate the initializer before entering the try block. */ if (from_array && init && TREE_CODE (init) != CONSTRUCTOR) { + if (lvalue_kind (init) & clk_rvalueref) + xvalue = true; base2 = decay_conversion (init); itype = TREE_TYPE (base2); base2 = get_temp_regvar (itype, base2); @@ -2954,32 +3072,100 @@ build_vec_init (tree base, tree maxindex, tree init, try_block = begin_try_block (); } + /* Maybe pull out constant value when from_array? */ + if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR) { /* Do non-default initialization of non-trivial arrays resulting from brace-enclosed initializers. */ unsigned HOST_WIDE_INT idx; - tree elt; + tree field, elt; + /* Should we try to create a constant initializer? */ + bool try_const = (literal_type_p (inner_elt_type) + || TYPE_HAS_CONSTEXPR_CTOR (inner_elt_type)); + bool saw_non_const = false; + bool saw_const = false; + /* If we're initializing a static array, we want to do static + initialization of any elements with constant initializers even if + some are non-constant. */ + bool do_static_init = (DECL_P (obase) && TREE_STATIC (obase)); + VEC(constructor_elt,gc) *new_vec; from_array = 0; - FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt) + if (try_const) + new_vec = VEC_alloc (constructor_elt, gc, CONSTRUCTOR_NELTS (init)); + else + new_vec = NULL; + + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, field, elt) { tree baseref = build1 (INDIRECT_REF, type, base); + tree one_init; num_initialized_elts++; current_stmt_tree ()->stmts_are_full_exprs_p = 1; if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) - finish_expr_stmt (build_aggr_init (baseref, elt, 0, complain)); + one_init = build_aggr_init (baseref, elt, 0, complain); else - finish_expr_stmt (cp_build_modify_expr (baseref, NOP_EXPR, - elt, complain)); + one_init = cp_build_modify_expr (baseref, NOP_EXPR, + elt, complain); + if (one_init == error_mark_node) + errors = true; + if (try_const) + { + tree e = one_init; + if (TREE_CODE (e) == EXPR_STMT) + e = TREE_OPERAND (e, 0); + if (TREE_CODE (e) == CONVERT_EXPR + && VOID_TYPE_P (TREE_TYPE (e))) + e = TREE_OPERAND (e, 0); + e = maybe_constant_init (e); + if (reduced_constant_expression_p (e)) + { + CONSTRUCTOR_APPEND_ELT (new_vec, field, e); + if (do_static_init) + one_init = NULL_TREE; + else + one_init = build2 (INIT_EXPR, type, baseref, e); + saw_const = true; + } + else + { + if (do_static_init) + CONSTRUCTOR_APPEND_ELT (new_vec, field, + build_zero_init (TREE_TYPE (e), + NULL_TREE, true)); + saw_non_const = true; + } + } + + if (one_init) + finish_expr_stmt (one_init); current_stmt_tree ()->stmts_are_full_exprs_p = 0; - finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base, 0, - complain)); - finish_expr_stmt (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0, - complain)); + one_init = cp_build_unary_op (PREINCREMENT_EXPR, base, 0, complain); + if (one_init == error_mark_node) + errors = true; + else + finish_expr_stmt (one_init); + + one_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0, + complain); + if (one_init == error_mark_node) + errors = true; + else + finish_expr_stmt (one_init); + } + + if (try_const) + { + if (!saw_non_const) + const_init = build_constructor (atype, new_vec); + else if (do_static_init && saw_const) + DECL_INITIAL (obase) = build_constructor (atype, new_vec); + else + VEC_free (constructor_elt, gc, new_vec); } /* Clear out INIT so that we don't get confused below. */ @@ -2989,13 +3175,12 @@ build_vec_init (tree base, tree maxindex, tree init, { if (init) /* OK, we set base2 above. */; - else if (TYPE_LANG_SPECIFIC (type) - && TYPE_NEEDS_CONSTRUCTING (type) + else if (CLASS_TYPE_P (type) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) { if (complain & tf_error) error ("initializer ends prematurely"); - return error_mark_node; + errors = true; } } @@ -3006,7 +3191,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_value_init_p) + || ((type_build_ctor_call (type) || explicit_value_init_p) && ! (host_integerp (maxindex, 0) && (num_initialized_elts == tree_low_cst (maxindex, 0) + 1)))) @@ -3017,14 +3202,16 @@ build_vec_init (tree base, tree maxindex, tree init, tree elt_init; tree to; - for_stmt = begin_for_stmt (); + for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE); finish_for_init_stmt (for_stmt); finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator, build_int_cst (TREE_TYPE (iterator), -1)), for_stmt); - finish_for_expr (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0, - complain), - for_stmt); + elt_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0, + complain); + if (elt_init == error_mark_node) + errors = true; + finish_for_expr (elt_init, for_stmt); to = build1 (INDIRECT_REF, type, base); @@ -3033,14 +3220,18 @@ build_vec_init (tree base, tree maxindex, tree init, tree from; if (base2) - from = build1 (INDIRECT_REF, itype, base2); + { + from = build1 (INDIRECT_REF, itype, base2); + if (xvalue) + from = move (from); + } else from = NULL_TREE; if (from_array == 2) elt_init = cp_build_modify_expr (to, NOP_EXPR, from, complain); - else if (TYPE_NEEDS_CONSTRUCTING (type)) + else if (type_build_ctor_call (type)) elt_init = build_aggr_init (to, from, 0, complain); else if (from) elt_init = cp_build_modify_expr (to, NOP_EXPR, from, @@ -3061,17 +3252,18 @@ build_vec_init (tree base, tree maxindex, tree init, else if (explicit_value_init_p) { elt_init = build_value_init (type, complain); - if (elt_init == error_mark_node) - return error_mark_node; - else + if (elt_init != error_mark_node) elt_init = build2 (INIT_EXPR, type, to, elt_init); } else { - gcc_assert (TYPE_NEEDS_CONSTRUCTING (type)); + gcc_assert (type_build_ctor_call (type)); elt_init = build_aggr_init (to, init, 0, complain); } + if (elt_init == error_mark_node) + errors = true; + current_stmt_tree ()->stmts_are_full_exprs_p = 1; finish_expr_stmt (elt_init); current_stmt_tree ()->stmts_are_full_exprs_p = 0; @@ -3104,8 +3296,10 @@ build_vec_init (tree base, tree maxindex, tree init, finish_cleanup_try_block (try_block); e = build_vec_delete_1 (rval, m, - inner_elt_type, sfk_base_destructor, - /*use_global_delete=*/0); + inner_elt_type, sfk_complete_destructor, + /*use_global_delete=*/0, complain); + if (e == error_mark_node) + errors = true; finish_cleanup (e, try_block); } @@ -3125,6 +3319,11 @@ build_vec_init (tree base, tree maxindex, tree init, } current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps; + + if (const_init) + return build2 (INIT_EXPR, atype, obase, const_init); + if (errors) + return error_mark_node; return stmt_expr; } @@ -3132,7 +3331,8 @@ build_vec_init (tree base, tree maxindex, tree init, build_delete. */ static tree -build_dtor_call (tree exp, special_function_kind dtor_kind, int flags) +build_dtor_call (tree exp, special_function_kind dtor_kind, int flags, + tsubst_flags_t complain) { tree name; tree fn; @@ -3159,7 +3359,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags) /*conversion_path=*/NULL_TREE, flags, /*fn_p=*/NULL, - tf_warning_or_error); + complain); } /* Generate a call to a destructor. TYPE is the type to cast ADDR to. @@ -3173,7 +3373,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags) tree build_delete (tree type, tree addr, special_function_kind auto_delete, - int flags, int use_global_delete) + int flags, int use_global_delete, tsubst_flags_t complain) { tree expr; @@ -3208,13 +3408,14 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, complete_type (type); if (!COMPLETE_TYPE_P (type)) { - if (warning (0, "possible problem detected in invocation of " - "delete operator:")) + if ((complain & tf_warning) + && 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."); + "declared when the class is defined"); } complete_p = false; } @@ -3234,18 +3435,21 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, if (TYPE_DOMAIN (type) == NULL_TREE) { - error ("unknown array size in delete"); + if (complain & tf_error) + error ("unknown array size in delete"); return error_mark_node; } return build_vec_delete (addr, array_type_nelts (type), - auto_delete, use_global_delete); + auto_delete, use_global_delete, complain); } else { /* Don't check PROTECT here; leave that decision to the destructor. If the destructor is accessible, call it, else report error. */ - addr = cp_build_addr_expr (addr, tf_warning_or_error); + addr = cp_build_addr_expr (addr, complain); + if (addr == error_mark_node) + return error_mark_node; if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); @@ -3317,9 +3521,10 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, /*alloc_fn=*/NULL_TREE); } - expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, - tf_warning_or_error), - auto_delete, flags); + expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain), + auto_delete, flags, complain); + if (expr == error_mark_node) + return error_mark_node; if (do_delete) expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete); @@ -3331,10 +3536,14 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, /* Explicit destructor call; don't check for null pointer. */ ifexp = integer_one_node; else - /* Handle deleting a null pointer. */ - ifexp = fold (cp_build_binary_op (input_location, - NE_EXPR, addr, integer_zero_node, - tf_warning_or_error)); + { + /* Handle deleting a null pointer. */ + ifexp = fold (cp_build_binary_op (input_location, + NE_EXPR, addr, integer_zero_node, + complain)); + if (ifexp == error_mark_node) + return error_mark_node; + } if (ifexp != integer_one_node) expr = build3 (COND_EXPR, void_type_node, @@ -3427,7 +3636,7 @@ push_base_cleanups (void) expr = build_delete (this_type, this_member, sfk_complete_destructor, LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, - 0); + 0, tf_warning_or_error); finish_decl_cleanup (NULL_TREE, expr); } } @@ -3451,7 +3660,8 @@ push_base_cleanups (void) tree build_vec_delete (tree base, tree maxindex, - special_function_kind auto_delete_vec, int use_global_delete) + special_function_kind auto_delete_vec, + int use_global_delete, tsubst_flags_t complain) { tree type; tree rval; @@ -3477,7 +3687,7 @@ build_vec_delete (tree base, tree maxindex, size_ptr_type, fold_convert (size_ptr_type, base), cookie_addr); - maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error); + maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, complain); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3485,7 +3695,9 @@ build_vec_delete (tree base, tree maxindex, bad name. */ maxindex = array_type_nelts_total (type); type = strip_array_types (type); - base = cp_build_addr_expr (base, tf_warning_or_error); + base = cp_build_addr_expr (base, complain); + if (base == error_mark_node) + return error_mark_node; if (TREE_SIDE_EFFECTS (base)) { base_init = get_target_expr (base); @@ -3494,14 +3706,14 @@ build_vec_delete (tree base, tree maxindex, } else { - if (base != error_mark_node) + if (base != error_mark_node && !(complain & tf_error)) error ("type to vector delete is neither pointer or array type"); return error_mark_node; } rval = build_vec_delete_1 (base, maxindex, type, auto_delete_vec, - use_global_delete); - if (base_init) + use_global_delete, complain); + if (base_init && rval != error_mark_node) rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), base_init, rval); return rval;