From: jason Date: Mon, 12 Apr 2010 19:58:27 +0000 (+0000) Subject: PR c++/25811 X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=2bc64004224123a8b204d5562368acdb78983c2c PR c++/25811 * cp-tree.h (diagnose_uninitialized_cst_or_ref_member): Declare. * init.c (build_new_1): Check for uninitialized const members and uninitialized reference members, when using new without new-initializer. Call diagnose_uninitialized_cst_or_ref_member. (diagnose_uninitialized_cst_or_ref_member): Define, call diagnose_uninitialized_cst_or_ref_member_1. (diagnose_uninitialized_cst_or_ref_member_1): New function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158239 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e56c77c35a5..c32e19fcb73 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2010-04-12 Fabien Chene + + PR c++/25811 + * cp-tree.h (diagnose_uninitialized_cst_or_ref_member): Declare. + * init.c (build_new_1): Check for uninitialized const members and + uninitialized reference members, when using new without + new-initializer. Call diagnose_uninitialized_cst_or_ref_member. + (diagnose_uninitialized_cst_or_ref_member): Define, call + diagnose_uninitialized_cst_or_ref_member_1. + (diagnose_uninitialized_cst_or_ref_member_1): New function. + 2010-04-12 Richard Guenther PR c++/43611 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 941c49acb54..91f2a9e9883 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1,6 +1,6 @@ /* Definitions for C++ parsing and type checking. Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) @@ -4852,6 +4852,7 @@ extern tree create_temporary_var (tree); extern void initialize_vtbl_ptrs (tree); extern tree build_java_class_ref (tree); extern tree integral_constant_value (tree); +extern void diagnose_uninitialized_cst_or_ref_member (tree, bool); /* in lex.c */ extern void cxx_dup_lang_specific_decl (tree); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 1bd80ffa0f8..c1f1cbf4a38 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 @@ -1753,6 +1754,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 @@ -1839,6 +1893,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)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f6fb943000e..4b79ce0a0cf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-04-12 Fabien Chene + + PR c++/25811 + * g++.dg/init/pr25811.C: New test. + 2010-04-12 Rainer Orth * g++.dg/warn/miss-format-1.C: Removed *-*-solaris2.7 from diff --git a/gcc/testsuite/g++.dg/init/pr25811.C b/gcc/testsuite/g++.dg/init/pr25811.C new file mode 100644 index 00000000000..c906a9bbd35 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/pr25811.C @@ -0,0 +1,195 @@ +// PR c++/25811 +// { dg-do compile } + +struct A1 +{ + int const j; // { dg-message "should be initialized" } +}; + +struct A2 +{ + int const volatile i; // { dg-message "should be initialized" } +}; + +struct A3 +{ + int& ref; // { dg-message "should be initialized" } +}; + +struct A4 +{ + int const& ref; // { dg-message "should be initialized" } +}; + +struct A5 +{ + int& ref; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" } +}; + +template struct S1 +{ + T const i; // { dg-message "should be initialized" } +}; + +template struct S2 +{ + T const volatile i; // { dg-message "should be initialized" } +}; + +template struct S3 +{ + T& ref; // { dg-message "should be initialized" } +}; + +template struct S4 +{ + T const i; // { dg-message "should be initialized" } + T& ref; // { dg-message "should be initialized" } +}; + +struct X +{ + X () : c (0), r (c) {} + int const c; + int const& r; +}; + +struct Y11 +{ + int const i; // { dg-message "should be initialized" } +}; + +struct Y1 +{ + Y11 a[1]; +}; + +struct Y22 +{ + int& ref; // { dg-message "should be initialized" } +}; + +struct Y2 +{ + Y22 a[1]; +}; + +struct Z1 +{ + int const i; // { dg-message "should be initialized" } +}; + +struct Z2 +{ + int& ref; // { dg-message "should be initialized" } +}; + +struct Z3 +{ + int const i; // { dg-message "should be initialized" } +}; + +struct Z4 +{ + int& ref; // { dg-message "should be initialized" } +}; + +struct Z5 +{ + int i; +}; + +struct Z +{ + Z1 z1; + Z2 z2; + Z3 z3; + Z4 z4; + Z5 z5; +}; + +union U +{ + int const i; // { dg-message "should be initialized" } +}; + +void f1 () +{ + new A1; // { dg-error "uninitialized const member" } +} + +void f2 () +{ + new A2; // { dg-error "uninitialized const member" } +} + +void f3 () +{ + new A3; // { dg-error "uninitialized reference member" } +} + +void f4 () +{ + new A4; // { dg-error "uninitialized reference member" } +} + +void f5 () +{ + new A5; // { dg-error "uninitialized reference member|uninitialized const member" } +} + +void f6 () +{ + new S1; // { dg-error "uninitialized const member" } +} + +void f7 () +{ + new S2; // { dg-error "uninitialized const member" } +} + +void f8 () +{ + new S3; // { dg-error "uninitialized reference member" } +} + +void f9 () +{ + new S4; // { dg-error "uninitialized reference member|uninitialized const member" } +} + +void f10 () +{ + new X; +} + +void f11 () +{ + new A1[1]; // { dg-error "uninitialized const member" } +} + +void f12 () +{ + new A3[1]; // { dg-error "uninitialized reference member" } +} + +void f13 () +{ + new Y1; // { dg-error "uninitialized const member" } +} + +void f14 () +{ + new Y2; // { dg-error "uninitialized reference member" } +} + +void f15 () +{ + new Z; // { dg-error "uninitialized reference member|uninitialized const member" } +} + +void f16 () +{ + new U; // { dg-error "uninitialized const member" } +}