X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Finit.c;h=57b874d5e4a415eecbf9223be3b4d8abaec3698b;hp=9118c61928b4c388b8d2a059e0e63446871dc3a7;hb=790acf29ee2cb89a60fe34a2cfd197093677274d;hpb=c1c67b4f5041c4367842002c81ffe912ff97f2d8 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 9118c61928b..57b874d5e4a 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1,6 +1,6 @@ /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) @@ -54,6 +54,7 @@ static tree dfs_initialize_vtbl_ptrs (tree, void *); static tree build_dtor_call (tree, special_function_kind, int); static tree build_field_list (tree, tree, int *); static tree build_vtbl_address (tree); +static void diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool); /* We are about to generate some complex initialization code. Conceptually, it is all a single expression. However, we may want @@ -219,7 +220,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) /* Iterate over the array elements, building initializations. */ if (nelts) - max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts), + max_index = fold_build2_loc (input_location, + MINUS_EXPR, TREE_TYPE (nelts), nelts, integer_one_node); else max_index = array_type_nelts (type); @@ -504,6 +506,7 @@ perform_member_init (tree member, tree init) { if (init == NULL_TREE) { + tree core_type; /* member traversal: note it leaves init NULL */ if (TREE_CODE (type) == REFERENCE_TYPE) permerror (DECL_SOURCE_LOCATION (current_function_decl), @@ -513,6 +516,11 @@ perform_member_init (tree member, tree init) permerror (DECL_SOURCE_LOCATION (current_function_decl), "uninitialized member %qD with % type %qT", member, type); + + core_type = strip_array_types (type); + if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type) + || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)) + diagnose_uninitialized_cst_or_ref_member (core_type, /*using_new=*/false); } else if (TREE_CODE (init) == TREE_LIST) /* There was an explicit member initialization. Do some work @@ -833,7 +841,7 @@ emit_mem_initializers (tree mem_inits) base_addr = build_base_path (PLUS_EXPR, current_class_ptr, subobject, 1); expand_aggr_init_1 (subobject, NULL_TREE, - cp_build_indirect_ref (base_addr, NULL, + cp_build_indirect_ref (base_addr, RO_NULL, tf_warning_or_error), arguments, LOOKUP_NORMAL, @@ -917,7 +925,7 @@ expand_virtual_init (tree binfo, tree decl) TREE_TYPE (vtt_parm), vtt_parm, vtt_index); - vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error); + vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error); vtbl2 = convert (TREE_TYPE (vtbl), vtbl2); /* The actual initializer is the VTT value only in the subobject @@ -932,7 +940,7 @@ expand_virtual_init (tree binfo, tree decl) } /* Compute the location of the vtpr. */ - vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL, + vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL, tf_warning_or_error), TREE_TYPE (binfo)); gcc_assert (vtbl_ptr != error_mark_node); @@ -965,7 +973,8 @@ expand_cleanup_for_base (tree binfo, tree flag) LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error); if (flag) - expr = fold_build3 (COND_EXPR, void_type_node, + expr = fold_build3_loc (input_location, + COND_EXPR, void_type_node, c_common_truthvalue_conversion (input_location, flag), expr, integer_zero_node); @@ -1246,13 +1255,13 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) /* Must arrange to initialize each element of EXP from elements of INIT. */ itype = init ? TREE_TYPE (init) : NULL_TREE; - if (cp_type_quals (type) != TYPE_UNQUALIFIED) - TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); - if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED) - itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype); + if (cv_qualified_p (type)) + TREE_TYPE (exp) = cv_unqualified (type); + if (itype && cv_qualified_p (itype)) + TREE_TYPE (init) = cv_unqualified (itype); stmt_expr = build_vec_init (exp, NULL_TREE, init, /*explicit_value_init_p=*/false, - itype && same_type_p (itype, + itype && same_type_p (TREE_TYPE (init), TREE_TYPE (exp)), complain); TREE_READONLY (exp) = was_const; @@ -1655,7 +1664,14 @@ constant_value_1 (tree decl, bool integral_p) init = DECL_INITIAL (decl); } if (init == error_mark_node) - return decl; + { + if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + /* Treat the error as a constant to avoid cascading errors on + excessively recursive template instantiation (c++/9335). */ + return init; + else + return decl; + } /* Initializers in templates are generally expanded during instantiation, so before that for const int i(2) INIT is a TREE_LIST with the actual initializer as @@ -1751,6 +1767,59 @@ build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts, return new_expr; } +/* Diagnose uninitialized const members or reference members of type + TYPE. USING_NEW is used to disambiguate the diagnostic between a + new expression without a new-initializer and a declaration */ + +static void +diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin, + bool using_new) +{ + tree field; + + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + tree field_type; + + if (TREE_CODE (field) != FIELD_DECL) + continue; + + field_type = strip_array_types (TREE_TYPE (field)); + + if (TREE_CODE (field_type) == REFERENCE_TYPE) + { + if (using_new) + error ("uninitialized reference member in %q#T using %", + origin); + else + error ("uninitialized reference member in %q#T", origin); + inform (DECL_SOURCE_LOCATION (field), + "%qD should be initialized", field); + } + + if (CP_TYPE_CONST_P (field_type)) + { + if (using_new) + error ("uninitialized const member in %q#T using %", + origin); + else + error ("uninitialized const member in %q#T", origin); + inform (DECL_SOURCE_LOCATION (field), + "%qD should be initialized", field); + } + + if (CLASS_TYPE_P (field_type)) + diagnose_uninitialized_cst_or_ref_member_1 (field_type, + origin, using_new); + } +} + +void +diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new) +{ + diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new); +} + /* Generate code for a new-expression, including calling the "operator new" function, initializing the object, and, if an exception occurs during construction, cleaning up. The arguments are as for @@ -1837,6 +1906,38 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL); + if (*init == NULL && !type_has_user_provided_constructor (elt_type)) + { + bool uninitialized_error = false; + /* A program that calls for default-initialization [...] of an + entity of reference type is ill-formed. */ + if (CLASSTYPE_REF_FIELDS_NEED_INIT (elt_type)) + uninitialized_error = true; + + /* A new-expression that creates an object of type T initializes + that object as follows: + - If the new-initializer is omitted: + -- If T is a (possibly cv-qualified) non-POD class type + (or array thereof), the object is default-initialized (8.5). + [...] + -- Otherwise, the object created has indeterminate + value. If T is a const-qualified type, or a (possibly + cv-qualified) POD class type (or array thereof) + containing (directly or indirectly) a member of + const-qualified type, the program is ill-formed; */ + + if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type)) + uninitialized_error = true; + + if (uninitialized_error) + { + if (complain & tf_error) + diagnose_uninitialized_cst_or_ref_member (elt_type, + /*using_new*/true); + return error_mark_node; + } + } + if (CP_TYPE_CONST_P (elt_type) && *init == NULL && !type_has_user_provided_default_constructor (elt_type)) { @@ -2048,11 +2149,12 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, many elements to destroy later. We use the last sizeof (size_t) bytes to store the number of elements. */ cookie_ptr = size_binop (MINUS_EXPR, cookie_size, size_in_bytes (sizetype)); - cookie_ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (alloc_node), + cookie_ptr = fold_build2_loc (input_location, + POINTER_PLUS_EXPR, TREE_TYPE (alloc_node), alloc_node, cookie_ptr); size_ptr_type = build_pointer_type (sizetype); cookie_ptr = fold_convert (size_ptr_type, cookie_ptr); - cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain); + cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain); cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts); @@ -2060,10 +2162,11 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, { /* Also store the element size. */ cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, cookie_ptr, - fold_build1 (NEGATE_EXPR, sizetype, + fold_build1_loc (input_location, + NEGATE_EXPR, sizetype, size_in_bytes (sizetype))); - cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain); + cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain); cookie = build2 (MODIFY_EXPR, sizetype, cookie, size_in_bytes (elt_type)); cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr), @@ -2150,7 +2253,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, } else { - init_expr = cp_build_indirect_ref (data_addr, NULL, complain); + init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain); if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p) { @@ -2498,11 +2601,11 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, tbase = create_temporary_var (ptype); tbase_init = cp_build_modify_expr (tbase, NOP_EXPR, - fold_build2 (POINTER_PLUS_EXPR, ptype, + fold_build2_loc (input_location, + POINTER_PLUS_EXPR, ptype, fold_convert (ptype, base), virtual_size), tf_warning_or_error); - DECL_REGISTER (tbase) = 1; controller = build3 (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (controller) = 1; @@ -2510,7 +2613,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, body = build1 (EXIT_EXPR, void_type_node, build2 (EQ_EXPR, boolean_type_node, tbase, fold_convert (ptype, base))); - tmp = fold_build1 (NEGATE_EXPR, sizetype, size_exp); + tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp); body = build_compound_expr (input_location, body, cp_build_modify_expr (tbase, NOP_EXPR, @@ -2575,8 +2678,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, body = integer_zero_node; /* Outermost wrapper: If pointer is null, punt. */ - body = fold_build3 (COND_EXPR, void_type_node, - fold_build2 (NE_EXPR, boolean_type_node, base, + body = fold_build3_loc (input_location, COND_EXPR, void_type_node, + fold_build2_loc (input_location, + NE_EXPR, boolean_type_node, base, convert (TREE_TYPE (base), integer_zero_node)), body, integer_zero_node); @@ -2661,7 +2765,6 @@ build_vec_init (tree base, tree maxindex, tree init, { tree rval; tree base2 = NULL_TREE; - tree size; tree itype = NULL_TREE; tree iterator; /* The type of BASE. */ @@ -2690,6 +2793,13 @@ build_vec_init (tree base, tree maxindex, tree init, gcc_assert (!init); inner_elt_type = strip_array_types (type); + + /* Look through the TARGET_EXPR around a compound literal. */ + if (init && TREE_CODE (init) == TARGET_EXPR + && TREE_CODE (TARGET_EXPR_INITIAL (init)) == CONSTRUCTOR + && from_array != 2) + init = TARGET_EXPR_INITIAL (init); + if (init && TREE_CODE (atype) == ARRAY_TYPE && (from_array == 2 @@ -2712,7 +2822,6 @@ build_vec_init (tree base, tree maxindex, tree init, } maxindex = cp_convert (ptrdiff_type_node, maxindex); - size = size_in_bytes (type); if (TREE_CODE (atype) == ARRAY_TYPE) { ptype = build_pointer_type (type); @@ -2758,6 +2867,17 @@ build_vec_init (tree base, tree maxindex, tree init, base = get_temp_regvar (ptype, rval); iterator = get_temp_regvar (ptrdiff_type_node, maxindex); + /* If initializing one array from another, initialize element by + element. We rely upon the below calls to do the argument + checking. Evaluate the initializer before entering the try block. */ + if (from_array && init && TREE_CODE (init) != CONSTRUCTOR) + { + base2 = decay_conversion (init); + itype = TREE_TYPE (base2); + base2 = get_temp_regvar (itype, base2); + itype = TREE_TYPE (itype); + } + /* Protect the entire array initialization so that we can destroy the partially constructed array if an exception is thrown. But don't do this if we're assigning. */ @@ -2800,16 +2920,8 @@ build_vec_init (tree base, tree maxindex, tree init, } else if (from_array) { - /* If initializing one array from another, initialize element by - element. We rely upon the below calls the do argument - checking. */ if (init) - { - base2 = decay_conversion (init); - itype = TREE_TYPE (base2); - base2 = get_temp_regvar (itype, base2); - itype = TREE_TYPE (itype); - } + /* OK, we set base2 above. */; else if (TYPE_LANG_SPECIFIC (type) && TYPE_NEEDS_CONSTRUCTING (type) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) @@ -2936,7 +3048,7 @@ build_vec_init (tree base, tree maxindex, tree init, { atype = build_pointer_type (atype); stmt_expr = build1 (NOP_EXPR, atype, stmt_expr); - stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain); + stmt_expr = cp_build_indirect_ref (stmt_expr, RO_NULL, complain); TREE_NO_WARNING (stmt_expr) = 1; } @@ -3131,7 +3243,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, /*alloc_fn=*/NULL_TREE); } - expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, + expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, tf_warning_or_error), auto_delete, flags); if (do_delete) @@ -3279,12 +3391,13 @@ build_vec_delete (tree base, tree maxindex, base = TARGET_EXPR_SLOT (base_init); } type = strip_array_types (TREE_TYPE (type)); - cookie_addr = fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (sizetype)); + cookie_addr = fold_build1_loc (input_location, NEGATE_EXPR, + sizetype, TYPE_SIZE_UNIT (sizetype)); cookie_addr = build2 (POINTER_PLUS_EXPR, size_ptr_type, fold_convert (size_ptr_type, base), cookie_addr); - maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error); + maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error); } else if (TREE_CODE (type) == ARRAY_TYPE) {