diff options
author | Jason Merrill <jason@redhat.com> | 2010-09-06 00:49:07 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-09-06 00:49:07 -0400 |
commit | ea76c60a1660ae449c3071d86ff8a6c3ce0a7ab8 (patch) | |
tree | d6d10d6ac7a5494908a3eea84837299d267cc944 | |
parent | 467649eb698b5276610f8509432eb7a5f721c5f3 (diff) | |
download | gcc-ea76c60a1660ae449c3071d86ff8a6c3ce0a7ab8.zip gcc-ea76c60a1660ae449c3071d86ff8a6c3ce0a7ab8.tar.gz gcc-ea76c60a1660ae449c3071d86ff8a6c3ce0a7ab8.tar.bz2 |
method.c (synthesized_method_walk): In constructors, also check subobject destructors.
* method.c (synthesized_method_walk): In constructors, also check
subobject destructors.
From-SVN: r163894
-rw-r--r-- | gcc/cp/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/cp/method.c | 49 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/implicit9.C | 12 |
4 files changed, 61 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b2da825..357464f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2010-09-06 Jason Merrill <jason@redhat.com> + * method.c (synthesized_method_walk): In constructors, also check + subobject destructors. + * semantics.c (finish_compound_literal): Always build a TARGET_EXPR. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 359e71d..0ec3826 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1052,10 +1052,15 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, int i, quals, flags; tsubst_flags_t complain; const char *msg; + bool ctor_p; + tree cleanup_spec; + bool cleanup_trivial = true; + bool cleanup_deleted = false; + cleanup_spec + = (cxx_dialect >= cxx0x ? noexcept_true_spec : empty_except_spec); if (spec_p) - *spec_p = (cxx_dialect >= cxx0x - ? noexcept_true_spec : empty_except_spec); + *spec_p = cleanup_spec; if (deleted_p) { @@ -1109,6 +1114,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, return; #endif + ctor_p = false; assign_p = false; check_vdtor = false; switch (sfk) @@ -1129,6 +1135,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, case sfk_constructor: case sfk_move_constructor: case sfk_copy_constructor: + ctor_p = true; fnname = complete_ctor_identifier; break; @@ -1176,7 +1183,16 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain); process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p, - msg, BINFO_TYPE (base_binfo)); + msg, basetype); + if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype)) + { + /* In a constructor we also need to check the subobject + destructors for cleanup of partially constructed objects. */ + rval = locate_fn_flags (base_binfo, complete_dtor_identifier, + NULL_TREE, flags, complain); + process_subob_fn (rval, false, &cleanup_spec, &cleanup_trivial, + &cleanup_deleted, NULL, basetype); + } if (check_vdtor && type_has_virtual_destructor (basetype)) { @@ -1186,6 +1202,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, to have a null rval (no class-specific op delete). */ if (rval && rval == error_mark_node && deleted_p) *deleted_p = true; + check_vdtor = false; } } @@ -1206,12 +1223,20 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, "or trivial copy constructor"); FOR_EACH_VEC_ELT (tree, vbases, i, base_binfo) { + tree basetype = BINFO_TYPE (base_binfo); if (copy_arg_p) - argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, move_p); + argtype = build_stub_type (basetype, quals, move_p); rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain); process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p, - msg, BINFO_TYPE (base_binfo)); + msg, basetype); + if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype)) + { + rval = locate_fn_flags (base_binfo, complete_dtor_identifier, + NULL_TREE, flags, complain); + process_subob_fn (rval, false, &cleanup_spec, &cleanup_trivial, + &cleanup_deleted, NULL, basetype); + } } } if (!diag) @@ -1225,12 +1250,26 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, walk_field_subobs (TYPE_FIELDS (ctype), fnname, sfk, quals, copy_arg_p, move_p, assign_p, spec_p, trivial_p, deleted_p, msg, flags, complain); + if (ctor_p) + walk_field_subobs (TYPE_FIELDS (ctype), complete_dtor_identifier, + sfk_destructor, TYPE_UNQUALIFIED, false, + false, false, &cleanup_spec, &cleanup_trivial, + &cleanup_deleted, NULL, flags, complain); pop_scope (scope); --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; + /* If the constructor isn't trivial, consider the subobject cleanups. */ + if (ctor_p && trivial_p && !*trivial_p) + { + if (deleted_p && cleanup_deleted) + *deleted_p = true; + if (spec_p) + *spec_p = merge_exception_specifiers (*spec_p, cleanup_spec); + } + #ifdef ENABLE_CHECKING /* If we expected this to be trivial but it isn't, then either we're in C++0x mode and this is a copy/move ctor/op= or there's an error. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index eb19f0e..e723af4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2010-09-06 Jason Merrill <jason@redhat.com> + * g++.dg/cpp0x/implicit9.C: New. + * g++.dg/cpp0x/initlist43.C: New. 2010-09-05 Giuseppe Scrivano <gscrivano@gnu.org> diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit9.C b/gcc/testsuite/g++.dg/cpp0x/implicit9.C new file mode 100644 index 0000000..3a6dbc5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/implicit9.C @@ -0,0 +1,12 @@ +// Test that private base dtor makes derived ctor deleted +// { dg-options -std=c++0x } + +struct A +{ + A(); +private: + ~A(); // { dg-error "private" } +}; + +struct B: A { }; // { dg-error "implicitly deleted|context" } +B * b = new B; // { dg-error "deleted" } |