diff options
author | Fabien Chêne <fabien.chene@gmail.com> | 2010-05-07 15:52:06 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-05-07 11:52:06 -0400 |
commit | 40bb78ad246919ee068382c3a2cdf6f299e412c9 (patch) | |
tree | 509ac9f873d8887b78813e37442448aa6d8215b2 /gcc | |
parent | 48cf395bdb30be10a283c3ac4d6217c322f39070 (diff) | |
download | gcc-40bb78ad246919ee068382c3a2cdf6f299e412c9.zip gcc-40bb78ad246919ee068382c3a2cdf6f299e412c9.tar.gz gcc-40bb78ad246919ee068382c3a2cdf6f299e412c9.tar.bz2 |
re PR c++/43951 (Revision 158918 miscompiled 483.xalancbmk in SPEC CPU 2006)
PR c++/43951
* init.c (diagnose_uninitialized_cst_or_ref_member_1): Returns the
error count. Emit errors only if compain is true.
(build_new_1): Do not return error_mark_node if
diagnose_uninitialized_cst_or_ref_member_1 does not diagnose any
errors. Delay the check for user-provided constructor.
(perform_member_init): Adjust.
* cp-tree.h (diagnose_uninitialized_cst_or_ref_member): Change the
prototype.
From-SVN: r159158
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/init.c | 83 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/new29.C | 33 |
5 files changed, 98 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 860f4e7..d41a95f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2010-05-07 Fabien Chêne <fabien.chene@gmail.com> + + PR c++/43951 + * init.c (diagnose_uninitialized_cst_or_ref_member_1): Returns the + error count. Emit errors only if compain is true. + (build_new_1): Do not return error_mark_node if + diagnose_uninitialized_cst_or_ref_member_1 does not diagnose any + errors. Delay the check for user-provided constructor. + (perform_member_init): Adjust. + * cp-tree.h (diagnose_uninitialized_cst_or_ref_member): Change the + prototype. + 2010-05-06 Magnus Fromreide <magfr@lysator.liu.se> Jason Merrill <jason@redhat.com> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 22a7487..0528289 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4857,7 +4857,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); +extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, 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 a2d9837..e45d2b8 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -54,7 +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); +static int diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool, bool); /* We are about to generate some complex initialization code. Conceptually, it is all a single expression. However, we may want @@ -522,7 +522,8 @@ perform_member_init (tree member, tree init) && (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); + /*using_new=*/false, + /*complain=*/true); } else if (TREE_CODE (init) == TREE_LIST) /* There was an explicit member initialization. Do some work @@ -1771,16 +1772,18 @@ build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts, /* 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 */ + new expression without a new-initializer and a declaration. Returns + the error count. */ -static void +static int diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin, - bool using_new) + bool using_new, bool complain) { tree field; + int error_count = 0; if (type_has_user_provided_constructor (type)) - return; + return 0; for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { @@ -1793,36 +1796,46 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin, if (TREE_CODE (field_type) == REFERENCE_TYPE) { - if (using_new) - error ("uninitialized reference member in %q#T " - "using %<new%> without new-initializer", origin); - else - error ("uninitialized reference member in %q#T", origin); - inform (DECL_SOURCE_LOCATION (field), - "%qD should be initialized", field); + ++ error_count; + if (complain) + { + if (using_new) + error ("uninitialized reference member in %q#T " + "using %<new%> 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 %<new%> without new-initializer", origin); - else - error ("uninitialized const member in %q#T", origin); - inform (DECL_SOURCE_LOCATION (field), - "%qD should be initialized", field); + ++ error_count; + if (complain) + { + if (using_new) + error ("uninitialized const member in %q#T " + "using %<new%> 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); + error_count + += diagnose_uninitialized_cst_or_ref_member_1 (field_type, origin, + using_new, complain); } + return error_count; } -void -diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new) +int +diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new, bool complain) { - diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new); + return diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new, complain); } /* Generate code for a new-expression, including calling the "operator @@ -1911,13 +1924,13 @@ 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)) + if (*init == NULL) { - bool uninitialized_error = false; + bool maybe_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; + maybe_uninitialized_error = true; /* A new-expression that creates an object of type T initializes that object as follows: @@ -1932,15 +1945,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, const-qualified type, the program is ill-formed; */ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type)) - uninitialized_error = true; + maybe_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 (maybe_uninitialized_error + && diagnose_uninitialized_cst_or_ref_member (elt_type, + /*using_new=*/true, + complain & tf_error)) + return error_mark_node; } if (CP_TYPE_CONST_P (elt_type) && *init == NULL diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 297ae76..08da4e6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-07 Fabien Chêne <fabien.chene@gmail.com> + + PR c++/43951 + * g++.dg/init/new29.C: New. + 2010-05-07 Daniel Franke <franke.daniel@gmail.com> PR fortran/40728 diff --git a/gcc/testsuite/g++.dg/init/new29.C b/gcc/testsuite/g++.dg/init/new29.C new file mode 100644 index 0000000..1ca8ca0 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/new29.C @@ -0,0 +1,33 @@ +// PR c++/43951 +// { dg-do run } +// { dg-options "-O2" } + +extern "C" void abort (); + +class Foo +{ +public: + Foo () : xxx (1) {}; + const int xxx; +}; + +struct Foo2 +{ + Foo foo; +}; + +Foo2 * +bar () +{ + return new Foo2; +} + +int +main () +{ + Foo2 *p = bar (); + + if (p->foo.xxx != 1) + abort (); + return 0; +} |