From patchwork Mon Sep 6 04:39:22 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 63871 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id DCACDB70E1 for ; Mon, 6 Sep 2010 14:39:33 +1000 (EST) Received: (qmail 14181 invoked by alias); 6 Sep 2010 04:39:31 -0000 Received: (qmail 14008 invoked by uid 22791); 6 Sep 2010 04:39:30 -0000 X-SWARE-Spam-Status: No, hits=-5.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_CX, TW_FN, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 06 Sep 2010 04:39:25 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o864dNHd021538 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 6 Sep 2010 00:39:23 -0400 Received: from [127.0.0.1] ([10.3.113.19]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o864dMP5003424 for ; Mon, 6 Sep 2010 00:39:23 -0400 Message-ID: <4C84707A.2050201@redhat.com> Date: Mon, 06 Sep 2010 00:39:22 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.12) Gecko/20100831 Lightning/1.0b1 Shredder/3.0.8pre MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH to synthesized_method_walk Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org My earlier overhaul of implicit declarations to actually do overload resolution forgot to consider that constructors need to call destructors to cleanup the partially constructed object in case something throws an exception. This patch does that unless the constructor is trivial. Tested x86_64-pc-linux-gnu, applied to trunk. commit bb23019874834c4872a0f36bd2c8ee5256d7e86a Author: Jason Merrill Date: Mon Sep 6 00:15:56 2010 -0400 * method.c (synthesized_method_walk): In constructors, also check subobject destructors. 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/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" }