X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Finit.c;h=7970b9ac476099bb80d5809117c3e15de3eb117c;hb=caa5624919cb3e599844d64a8910ce710ec85b2a;hp=85ad582f2d1ed97e0c6f07bb91470a5feadfd7f1;hpb=ab8002def2756caef8dab23e0fd27c446dbd343e;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 85ad582f2d1..7970b9ac476 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); @@ -65,7 +61,7 @@ static int diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool, bool); static bool begin_init_stmts (tree *stmt_expr_p, tree *compound_stmt_p) { - bool is_global = !building_stmt_tree (); + bool is_global = !building_stmt_list_p (); *stmt_expr_p = begin_stmt_expr (); *compound_stmt_p = begin_compound_stmt (BCS_NO_SCOPE); @@ -83,7 +79,7 @@ finish_init_stmts (bool is_global, tree stmt_expr, tree compound_stmt) stmt_expr = finish_stmt_expr (stmt_expr, true); - gcc_assert (!building_stmt_tree () == is_global); + gcc_assert (!building_stmt_list_p () == is_global); return stmt_expr; } @@ -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; @@ -184,20 +183,37 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) VEC(constructor_elt,gc) *v = NULL; /* Iterate over the fields, building initializations. */ - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) { 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,11 +281,29 @@ 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]. */ tree -build_value_init (tree type) +build_value_init (tree type, tsubst_flags_t complain) { /* [dcl.init] @@ -295,15 +329,25 @@ build_value_init (tree type) zero-initializing the object and then calling the default constructor. */ + /* The AGGR_INIT_EXPR tweaking below breaks in templates. */ + gcc_assert (!processing_template_decl); + if (CLASS_TYPE_P (type)) { - if (type_has_user_provided_constructor (type)) + /* Instead of the above, only consider the user-providedness of the + default constructor itself so value-initializing a class with an + explicitly defaulted default constructor and another user-provided + constructor works properly (c++std-core-19883). */ + if (type_has_user_provided_default_constructor (type) + || (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type) + && type_has_user_provided_constructor (type))) return build_aggr_init_expr (type, build_special_member_call (NULL_TREE, complete_ctor_identifier, NULL, type, LOOKUP_NORMAL, - tf_warning_or_error)); - else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type)) + complain), + complain); + else if (TYPE_HAS_COMPLEX_DFLT (type)) { /* This is a class that needs constructing, but doesn't have a user-provided constructor. So we need to zero-initialize @@ -311,25 +355,29 @@ build_value_init (tree type) 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; + NULL, type, LOOKUP_NORMAL, complain); + if (ctor != error_mark_node) + { + ctor = build_aggr_init_expr (type, ctor, complain); + AGGR_INIT_ZERO_FIRST (ctor) = 1; + } return ctor; } } - return build_value_init_noctor (type); + return build_value_init_noctor (type, complain); } /* Like build_value_init, but don't call the constructor for TYPE. Used for base initializers. */ tree -build_value_init_noctor (tree type) +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_HAS_COMPLEX_DFLT (type)); if (TREE_CODE (type) != UNION_TYPE) { @@ -337,7 +385,7 @@ build_value_init_noctor (tree type) VEC(constructor_elt,gc) *v = NULL; /* Iterate over the fields, building initializations. */ - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) { tree ftype, value; @@ -346,9 +394,6 @@ build_value_init_noctor (tree type) ftype = TREE_TYPE (field); - if (TREE_CODE (ftype) == REFERENCE_TYPE) - error ("value-initialization of reference"); - /* 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 @@ -359,7 +404,10 @@ build_value_init_noctor (tree type) 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 (ftype); + value = build_value_init (ftype, complain); + + if (value == error_mark_node) + return error_mark_node; if (value) CONSTRUCTOR_APPEND_ELT(v, field, value); @@ -379,7 +427,12 @@ build_value_init_noctor (tree type) /* If we have an error_mark here, we should just return error mark as we don't know the size of the array yet. */ if (max_index == error_mark_node) - return error_mark_node; + { + 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); /* A zero-sized array, which is accepted as an extension, will @@ -398,9 +451,14 @@ build_value_init_noctor (tree type) ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index); - ce->value = build_value_init (TREE_TYPE (type)); + 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); } @@ -408,6 +466,18 @@ build_value_init_noctor (tree type) /* 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); } @@ -437,28 +507,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)); - 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 @@ -472,21 +547,33 @@ 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 (BRACE_ENCLOSED_INITIALIZER_P (init)) + init = digest_init (type, init, tf_warning_or_error); + } + 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)) @@ -495,7 +582,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)); } } @@ -515,6 +602,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))) @@ -525,7 +622,8 @@ perform_member_init (tree member, tree init) else if (TREE_CODE (init) == TREE_LIST) /* There was an explicit member initialization. Do some work in that case. */ - init = build_x_compound_expr_from_list (init, ELK_MEM_INIT); + init = build_x_compound_expr_from_list (init, ELK_MEM_INIT, + tf_warning_or_error); if (init) finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init, @@ -541,7 +639,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); @@ -562,27 +661,29 @@ build_field_list (tree t, tree list, int *uses_unions_p) if (TREE_CODE (t) == UNION_TYPE) *uses_unions_p = 1; - for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields)) + for (fields = TYPE_FIELDS (t); fields; fields = DECL_CHAIN (fields)) { + tree fieldtype; + /* Skip CONST_DECLs for enumeration constants and so forth. */ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) continue; + fieldtype = TREE_TYPE (fields); /* Keep track of whether or not any fields are unions. */ - if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE) + if (TREE_CODE (fieldtype) == UNION_TYPE) *uses_unions_p = 1; /* For an anonymous struct or union, we must recursively consider the fields of the anonymous type. They can be directly initialized from the constructor. */ - if (ANON_AGGR_TYPE_P (TREE_TYPE (fields))) + if (ANON_AGGR_TYPE_P (fieldtype)) { /* Add this field itself. Synthesized copy constructors initialize the entire aggregate. */ list = tree_cons (fields, NULL_TREE, list); /* And now add the fields in the anonymous aggregate. */ - list = build_field_list (TREE_TYPE (fields), list, - uses_unions_p); + list = build_field_list (fieldtype, list, uses_unions_p); } /* Add this field. */ else if (DECL_NAME (fields)) @@ -708,38 +809,54 @@ sort_mem_initializers (tree t, tree mem_inits) If a ctor-initializer specifies more than one mem-initializer for multiple members of the same union (including members of - anonymous unions), the ctor-initializer is ill-formed. */ + anonymous unions), the ctor-initializer is ill-formed. + + Here we also splice out uninitialized union members. */ if (uses_unions_p) { tree last_field = NULL_TREE; - for (init = sorted_inits; init; init = TREE_CHAIN (init)) + tree *p; + for (p = &sorted_inits; *p; ) { tree field; - tree field_type; + tree ctx; int done; - /* Skip uninitialized members and base classes. */ - if (!TREE_VALUE (init) - || TREE_CODE (TREE_PURPOSE (init)) != FIELD_DECL) - continue; + init = *p; + + field = TREE_PURPOSE (init); + + /* Skip base classes. */ + if (TREE_CODE (field) != FIELD_DECL) + goto next; + + /* If this is an anonymous union with no explicit initializer, + splice it out. */ + if (!TREE_VALUE (init) && ANON_UNION_TYPE_P (TREE_TYPE (field))) + goto splice; + /* See if this field is a member of a union, or a member of a structure contained in a union, etc. */ - field = TREE_PURPOSE (init); - for (field_type = DECL_CONTEXT (field); - !same_type_p (field_type, t); - field_type = TYPE_CONTEXT (field_type)) - if (TREE_CODE (field_type) == UNION_TYPE) + for (ctx = DECL_CONTEXT (field); + !same_type_p (ctx, t); + ctx = TYPE_CONTEXT (ctx)) + if (TREE_CODE (ctx) == UNION_TYPE) break; /* If this field is not a member of a union, skip it. */ - if (TREE_CODE (field_type) != UNION_TYPE) - continue; + if (TREE_CODE (ctx) != UNION_TYPE) + goto next; + + /* If this union member has no explicit initializer, splice + it out. */ + if (!TREE_VALUE (init)) + goto splice; /* It's only an error if we have two initializers for the same union type. */ if (!last_field) { last_field = field; - continue; + goto next; } /* See if LAST_FIELD and the field initialized by INIT are @@ -750,41 +867,48 @@ sort_mem_initializers (tree t, tree mem_inits) union { struct { int i; int j; }; }; initializing both `i' and `j' makes sense. */ - field_type = DECL_CONTEXT (field); + ctx = DECL_CONTEXT (field); done = 0; do { - tree last_field_type; + tree last_ctx; - last_field_type = DECL_CONTEXT (last_field); + last_ctx = DECL_CONTEXT (last_field); while (1) { - if (same_type_p (last_field_type, field_type)) + if (same_type_p (last_ctx, ctx)) { - if (TREE_CODE (field_type) == UNION_TYPE) + if (TREE_CODE (ctx) == UNION_TYPE) error_at (DECL_SOURCE_LOCATION (current_function_decl), "initializations for multiple members of %qT", - last_field_type); + last_ctx); done = 1; break; } - if (same_type_p (last_field_type, t)) + if (same_type_p (last_ctx, t)) break; - last_field_type = TYPE_CONTEXT (last_field_type); + last_ctx = TYPE_CONTEXT (last_ctx); } /* If we've reached the outermost class, then we're done. */ - if (same_type_p (field_type, t)) + if (same_type_p (ctx, t)) break; - field_type = TYPE_CONTEXT (field_type); + ctx = TYPE_CONTEXT (ctx); } while (!done); last_field = field; + + next: + p = &TREE_CHAIN (*p); + continue; + splice: + *p = TREE_CHAIN (*p); + continue; } } @@ -801,11 +925,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); @@ -819,17 +948,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)) @@ -844,7 +986,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); } @@ -1005,7 +1147,7 @@ construct_virtual_base (tree vbase, tree arguments) in the outer block.) We trust the back end to figure out that the FLAG will not change across initializations, and avoid doing multiple tests. */ - flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)); + flag = DECL_CHAIN (DECL_ARGUMENTS (current_function_decl)); inner_if_stmt = begin_if_stmt (); finish_if_stmt_cond (flag, inner_if_stmt); @@ -1307,12 +1449,23 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, tree rval; VEC(tree,gc) *parms; + /* If we have direct-initialization from an initializer list, pull + it out of the TREE_LIST so the code below can see it. */ + if (init && TREE_CODE (init) == TREE_LIST + && BRACE_ENCLOSED_INITIALIZER_P (TREE_VALUE (init)) + && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init))) + { + gcc_checking_assert ((flags & LOOKUP_ONLYCONVERTING) == 0 + && TREE_CHAIN (init) == NULL_TREE); + init = TREE_VALUE (init); + } + if (init && BRACE_ENCLOSED_INITIALIZER_P (init) && CP_AGGREGATE_TYPE_P (type)) { /* A brace-enclosed initializer for an aggregate. In C++0x this can happen for direct-initialization, too. */ - init = digest_init (type, init); + init = digest_init (type, init, complain); init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); @@ -1373,8 +1526,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_init (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, NULL, complain)); + finish_expr_stmt (rval); } /* This function is responsible for initializing EXP with INIT @@ -1404,7 +1569,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, tree type = TREE_TYPE (exp); gcc_assert (init != error_mark_node && type != error_mark_node); - gcc_assert (building_stmt_tree ()); + gcc_assert (building_stmt_list_p ()); /* Use a function returning the desired type to initialize EXP for us. If the function is a constructor, and its first argument is @@ -1433,7 +1598,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); @@ -1444,7 +1609,8 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, then just zero out the object and we're done. */ else { - init = build2 (INIT_EXPR, type, exp, build_value_init_noctor (type)); + init = build2 (INIT_EXPR, type, exp, + build_value_init_noctor (type, complain)); finish_expr_stmt (init); return; } @@ -1507,18 +1673,9 @@ build_offset_ref (tree type, tree member, bool address_p) if (TREE_CODE (member) == TEMPLATE_DECL) return member; - if (dependent_type_p (type) || type_dependent_expression_p (member)) - { - tree ref, mem_type = NULL_TREE; - if (!dependent_scope_p (type)) - mem_type = TREE_TYPE (member); - ref = build_qualified_name (mem_type, type, member, + if (dependent_scope_p (type) || type_dependent_expression_p (member)) + return build_qualified_name (NULL_TREE, type, member, /*template_p=*/false); - /* Undo convert_from_reference. */ - if (TREE_CODE (ref) == INDIRECT_REF) - ref = TREE_OPERAND (ref, 0); - return ref; - } gcc_assert (TYPE_P (type)); if (! is_class_type (type, 1)) @@ -1528,6 +1685,7 @@ build_offset_ref (tree type, tree member, bool address_p) /* Callers should call mark_used before this point. */ gcc_assert (!DECL_P (member) || TREE_USED (member)); + type = TYPE_MAIN_VARIANT (type); if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type))) { error ("incomplete type %qT does not have member %qD", type, member); @@ -1618,8 +1776,7 @@ build_offset_ref (tree type, tree member, bool address_p) if (flag_ms_extensions) { PTRMEM_OK_P (member) = 1; - return cp_build_unary_op (ADDR_EXPR, member, 0, - tf_warning_or_error); + return cp_build_addr_expr (member, tf_warning_or_error); } error ("invalid use of non-static member function %qD", TREE_OPERAND (member, 1)); @@ -1649,36 +1806,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)) @@ -1699,16 +1838,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); } @@ -1798,7 +1936,7 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin, if (type_has_user_provided_constructor (type)) return 0; - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) { tree field_type; @@ -1807,6 +1945,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; @@ -1932,10 +2073,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) { @@ -2016,10 +2157,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, } alloc_fn = OVL_CURRENT (alloc_fn); class_addr = build1 (ADDR_EXPR, jclass_node, class_decl); - alloc_call = (cp_build_function_call - (alloc_fn, - build_tree_list (NULL_TREE, class_addr), - complain)); + alloc_call = cp_build_function_call_nary (alloc_fn, complain, + class_addr, NULL_TREE); } else if (TYPE_FOR_JAVA (elt_type) && MAYBE_CLASS_TYPE_P (elt_type)) { @@ -2235,31 +2374,53 @@ 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 && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *init, 0)) && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *init, 0))) { - tree arraytype, domain; vecinit = VEC_index (tree, *init, 0); - if (TREE_CONSTANT (nelts)) - domain = compute_array_index_type (NULL_TREE, nelts); + if (CONSTRUCTOR_NELTS (vecinit) == 0) + /* List-value-initialization, leave it alone. */; else { - domain = NULL_TREE; - if (CONSTRUCTOR_NELTS (vecinit) > 0) - warning (0, "non-constant array size in new, unable to " - "verify length of initializer-list"); + tree arraytype, domain; + if (TREE_CONSTANT (nelts)) + domain = compute_array_index_type (NULL_TREE, nelts, + complain); + 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, complain); } - arraytype = build_cplus_array_type (type, domain); - vecinit = digest_init (arraytype, vecinit); } else if (*init) { if (complain & tf_error) - permerror (input_location, "ISO C++ forbids initialization in array new"); + permerror (input_location, + "parenthesized initializer in array new"); else return error_mark_node; vecinit = build_tree_list_vec (*init); @@ -2284,7 +2445,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) + if (type_build_ctor_call (type) && !explicit_value_init_p) { init_expr = build_special_member_call (init_expr, complete_ctor_identifier, @@ -2295,8 +2456,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, else if (explicit_value_init_p) { /* Something like `new int()'. */ - init_expr = build2 (INIT_EXPR, type, - init_expr, build_value_init (type)); + 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 { @@ -2457,8 +2620,12 @@ 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); + type = do_auto_deduction (type, d_init, auto_node); + } } if (processing_template_decl) @@ -2515,7 +2682,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts, /* The type allocated must be complete. If the new-type-id was "T[N]" then we are just checking that "T" is complete here, but that is equivalent, since the value of "N" doesn't matter. */ - if (!complete_type_or_else (type, NULL_TREE)) + if (!complete_type_or_maybe_complain (type, NULL_TREE, complain)) return error_mark_node; rval = build_new_1 (placement, type, nelts, init, use_global_new, complain); @@ -2561,7 +2728,7 @@ build_java_class_ref (tree type) /* Mangle the class$ field. */ { tree field; - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (DECL_NAME (field) == CL_suffix) { mangle_decl (field); @@ -2570,7 +2737,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; } } @@ -2593,7 +2760,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)); @@ -2622,6 +2790,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; @@ -2635,7 +2806,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; @@ -2644,23 +2817,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; @@ -2676,24 +2850,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; @@ -2726,7 +2900,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, /*implicit=*/NULL, tf_warning_or_error); + return convert_to_void (body, ICV_CAST, complain); } /* Create an unnamed variable of the indicated TYPE. */ @@ -2753,7 +2927,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; @@ -2812,6 +2986,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); @@ -2902,6 +3080,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); @@ -2917,32 +3097,115 @@ build_vec_init (tree base, tree maxindex, tree init, try_block = begin_try_block (); } - if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR) + /* If the initializer is {}, then all elements are initialized from {}. + But for non-classes, that's the same as value-initialization. */ + if (init && BRACE_ENCLOSED_INITIALIZER_P (init) + && CONSTRUCTOR_NELTS (init) == 0) + { + if (CLASS_TYPE_P (type)) + /* Leave init alone. */; + else + { + init = NULL_TREE; + explicit_value_init_p = true; + } + } + + /* Maybe pull out constant value when from_array? */ + + else 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 = (TREE_CODE (atype) == ARRAY_TYPE + && (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. */ @@ -2952,13 +3215,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; } } @@ -2969,7 +3231,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) || init || explicit_value_init_p) && ! (host_integerp (maxindex, 0) && (num_initialized_elts == tree_low_cst (maxindex, 0) + 1)))) @@ -2980,14 +3242,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); @@ -2996,14 +3260,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, @@ -3022,14 +3290,28 @@ build_vec_init (tree base, tree maxindex, tree init, 0, complain); } else if (explicit_value_init_p) - elt_init = build2 (INIT_EXPR, type, to, - build_value_init (type)); + { + elt_init = build_value_init (type, complain); + if (elt_init != error_mark_node) + elt_init = build2 (INIT_EXPR, type, to, elt_init); + } else { - gcc_assert (TYPE_NEEDS_CONSTRUCTING (type)); - elt_init = build_aggr_init (to, init, 0, complain); + gcc_assert (type_build_ctor_call (type) || init); + if (CLASS_TYPE_P (type)) + elt_init = build_aggr_init (to, init, 0, complain); + else + { + if (TREE_CODE (init) == TREE_LIST) + init = build_x_compound_expr_from_list (init, ELK_INIT, + complain); + elt_init = build2 (INIT_EXPR, type, to, init); + } } + 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; @@ -3062,8 +3344,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); } @@ -3083,6 +3367,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; } @@ -3090,7 +3379,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; @@ -3117,7 +3407,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. @@ -3131,7 +3421,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; @@ -3166,16 +3456,37 @@ 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; } + else if (auto_delete == sfk_deleting_destructor && warn_delnonvdtor + && MAYBE_CLASS_TYPE_P (type) && !CLASSTYPE_FINAL (type) + && TYPE_POLYMORPHIC_P (type)) + { + tree dtor; + dtor = CLASSTYPE_DESTRUCTORS (type); + if (!dtor || !DECL_VINDEX (dtor)) + { + if (CLASSTYPE_PURE_VIRTUALS (type)) + warning (OPT_Wdelete_non_virtual_dtor, + "deleting object of abstract class type %qT" + " which has non-virtual destructor" + " will cause undefined behaviour", type); + else + warning (OPT_Wdelete_non_virtual_dtor, + "deleting object of polymorphic class type %qT" + " which has non-virtual destructor" + " might cause undefined behaviour", type); + } + } } if (VOID_TYPE_P (type) || !complete_p || !MAYBE_CLASS_TYPE_P (type)) /* Call the builtin operator delete. */ @@ -3192,18 +3503,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_unary_op (ADDR_EXPR, addr, 0, 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); @@ -3275,9 +3589,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); @@ -3289,10 +3604,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, @@ -3361,25 +3680,31 @@ push_base_cleanups (void) finish_decl_cleanup (NULL_TREE, expr); } + /* Don't automatically destroy union members. */ + if (TREE_CODE (current_class_type) == UNION_TYPE) + return; + for (member = TYPE_FIELDS (current_class_type); member; - member = TREE_CHAIN (member)) + member = DECL_CHAIN (member)) { - if (TREE_TYPE (member) == error_mark_node + tree this_type = TREE_TYPE (member); + if (this_type == error_mark_node || TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member)) continue; - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member))) + if (ANON_UNION_TYPE_P (this_type)) + continue; + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type)) { tree this_member = (build_class_member_access_expr (current_class_ref, member, /*access_path=*/NULL_TREE, /*preserve_reference=*/false, tf_warning_or_error)); - tree this_type = TREE_TYPE (member); 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); } } @@ -3403,7 +3728,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; @@ -3429,7 +3755,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) { @@ -3437,7 +3763,9 @@ build_vec_delete (tree base, tree maxindex, bad name. */ maxindex = array_type_nelts_total (type); type = strip_array_types (type); - base = cp_build_unary_op (ADDR_EXPR, base, 1, 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); @@ -3446,14 +3774,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;