X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Finit.c;h=4fc90e6c276ca8bf5250fc454f2c65a4df7d0744;hb=HEAD;hp=9dac7de400e6a7b0e05f536706b4f549219efb38;hpb=67702eb899864e03a05b9cf0f0ef542533900d7c;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 9dac7de400e..4fc90e6c276 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 @@ -505,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), @@ -514,6 +516,13 @@ 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 (CLASS_TYPE_P (core_type) + && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type) + || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))) + diagnose_uninitialized_cst_or_ref_member (core_type, + /*using_new=*/false); } else if (TREE_CODE (init) == TREE_LIST) /* There was an explicit member initialization. Do some work @@ -834,7 +843,7 @@ emit_mem_initializers (tree mem_inits) base_addr = build_base_path (PLUS_EXPR, current_class_ptr, subobject, 1); expand_aggr_init_1 (subobject, NULL_TREE, - cp_build_indirect_ref (base_addr, NULL, + cp_build_indirect_ref (base_addr, RO_NULL, tf_warning_or_error), arguments, LOOKUP_NORMAL, @@ -918,7 +927,7 @@ expand_virtual_init (tree binfo, tree decl) TREE_TYPE (vtt_parm), vtt_parm, vtt_index); - vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error); + vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error); vtbl2 = convert (TREE_TYPE (vtbl), vtbl2); /* The actual initializer is the VTT value only in the subobject @@ -933,7 +942,7 @@ expand_virtual_init (tree binfo, tree decl) } /* Compute the location of the vtpr. */ - vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL, + vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL, tf_warning_or_error), TREE_TYPE (binfo)); gcc_assert (vtbl_ptr != error_mark_node); @@ -1248,13 +1257,13 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) /* Must arrange to initialize each element of EXP from elements of INIT. */ itype = init ? TREE_TYPE (init) : NULL_TREE; - if (cp_type_quals (type) != TYPE_UNQUALIFIED) - TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); - if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED) - itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype); + if (cv_qualified_p (type)) + TREE_TYPE (exp) = cv_unqualified (type); + if (itype && cv_qualified_p (itype)) + TREE_TYPE (init) = cv_unqualified (itype); stmt_expr = build_vec_init (exp, NULL_TREE, init, /*explicit_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; @@ -1502,7 +1511,7 @@ build_offset_ref (tree type, tree member, bool address_p) gcc_assert (DECL_P (member) || BASELINK_P (member)); /* Callers should call mark_used before this point. */ - gcc_assert (!DECL_P (member) || tree_used_ok (member)); + gcc_assert (!DECL_P (member) || TREE_USED (member)); if (!COMPLETE_TYPE_P (complete_type (type)) && !TYPE_BEING_DEFINED (type)) @@ -1657,7 +1666,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 @@ -1753,6 +1769,62 @@ 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; + + if (type_has_user_provided_constructor (type)) + return; + + 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 % without new-initializer", origin); + else + error ("uninitialized reference member in %q#T", origin); + inform (DECL_SOURCE_LOCATION (field), + "%qD should be initialized", field); + } + + if (CP_TYPE_CONST_P (field_type)) + { + if (using_new) + error ("uninitialized const member in %q#T " + "using % without new-initializer", origin); + else + error ("uninitialized const member in %q#T", origin); + inform (DECL_SOURCE_LOCATION (field), + "%qD should be initialized", field); + } + + 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 @@ -1839,6 +1911,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)) { @@ -2055,7 +2159,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, 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); @@ -2067,7 +2171,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, 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), @@ -2154,7 +2258,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) { @@ -2666,7 +2770,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. */ @@ -2724,7 +2827,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); @@ -2951,7 +3053,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; } @@ -3146,7 +3248,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, /*alloc_fn=*/NULL_TREE); } - expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, + expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, tf_warning_or_error), auto_delete, flags); if (do_delete) @@ -3300,7 +3402,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, 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) {