From 85acc8c4bb45ba0b485117714d51899991232207 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 6 Sep 2010 04:49:07 +0000 Subject: [PATCH] * method.c (synthesized_method_walk): In constructors, also check subobject destructors. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163894 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 3 +++ gcc/cp/method.c | 49 ++++++++++++++++++++++++++++++---- gcc/testsuite/ChangeLog | 2 ++ gcc/testsuite/g++.dg/cpp0x/implicit9.C | 12 +++++++++ 4 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/implicit9.C 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 + * 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 + * g++.dg/cpp0x/implicit9.C: New. + * g++.dg/cpp0x/initlist43.C: New. 2010-09-05 Giuseppe Scrivano 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" } -- 2.7.4