From patchwork Fri Dec 16 22:31:59 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 131927 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 84F3B1007D7 for ; Sat, 17 Dec 2011 09:32:42 +1100 (EST) Received: (qmail 22111 invoked by alias); 16 Dec 2011 22:32:29 -0000 Received: (qmail 22092 invoked by uid 22791); 16 Dec 2011 22:32:22 -0000 X-SWARE-Spam-Status: No, hits=-5.2 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS 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; Fri, 16 Dec 2011 22:32:01 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pBGMW0jH015902 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 16 Dec 2011 17:32:01 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pBGMW0Bl004588; Fri, 16 Dec 2011 17:32:00 -0500 Received: from [0.0.0.0] (ovpn-113-21.phx2.redhat.com [10.3.113.21]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id pBGMVxAT031742; Fri, 16 Dec 2011 17:31:59 -0500 Message-ID: <4EEBC6DF.8060401@redhat.com> Date: Fri, 16 Dec 2011 17:31:59 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20111112 Thunderbird/8.0 MIME-Version: 1.0 To: gcc-patches List CC: Jakub Jelinek Subject: C++ PATCH for c++/51331 (wrong-code with virtual bases and zero-initialization) 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 For PR 48035, Jakub factored build_zero_init_1 out of build_zero_init to avoid clobbering the area occupied by virtual bases in the complete type, but not part of a base subobject. For 50618, I changed build_aggr_init_1 to use it. This testcase shows another case of the same problem: in this case, we're dealing with a virtual base of a virtual base. Building the smaller CONSTRUCTOR doesn't help in this case because an empty CONSTRUCTOR means zero-initializing the whole object. The reason the 48035/50618 patches work is that in expand_assignment, when we're dealing with a COMPONENT_REF to a particular base field, we use the DECL_SIZE of the field to know how much space to zero out. In this case we don't have a COMPONENT_REF, so we still zero out the full size of the type. This patch fixes the PR by building a COMPONENT_REF in this case as well. A proper fix depends on 22488. Tested x86_64-pc-linux-gnu, applying to trunk and 4.6. commit e3c92cd26597fea326d06a17e029d5b2c72e0e6c Author: Jason Merrill Date: Fri Dec 16 13:54:35 2011 -0500 PR c++/51331 * class.c (convert_to_base_statically): Just call build_simple_base_path. (build_simple_base_path): Check field offset. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 3cb76de..c96f7bf 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -471,7 +471,14 @@ build_simple_base_path (tree expr, tree binfo) /* Is this the base field created by build_base_field? */ if (TREE_CODE (field) == FIELD_DECL && DECL_FIELD_IS_BASE (field) - && TREE_TYPE (field) == type) + && TREE_TYPE (field) == type + /* If we're looking for a field in the most-derived class, + also check the field offset; we can have two base fields + of the same type if one is an indirect virtual base and one + is a direct non-virtual base. */ + && (BINFO_INHERITANCE_CHAIN (d_binfo) + || tree_int_cst_equal (byte_position (field), + BINFO_OFFSET (binfo)))) { /* We don't use build_class_member_access_expr here, as that has unnecessary checks, and more importantly results in @@ -546,6 +553,10 @@ convert_to_base_statically (tree expr, tree base) expr_type = TREE_TYPE (expr); if (!SAME_BINFO_TYPE_P (BINFO_TYPE (base), expr_type)) { + /* If this is a non-empty base, use a COMPONENT_REF. */ + if (!is_empty_class (BINFO_TYPE (base))) + return build_simple_base_path (expr, base); + /* We use fold_build2 and fold_convert below to simplify the trees provided to the optimizers. It is not safe to call these functions when processing a template because they do not handle C++-specific diff --git a/gcc/testsuite/g++.dg/init/value10.C b/gcc/testsuite/g++.dg/init/value10.C new file mode 100644 index 0000000..2066410 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/value10.C @@ -0,0 +1,27 @@ +// PR c++/51331 +// { dg-do run } + +struct A { + A(): x(10) {} + virtual ~A() {} + + int x; +}; + +struct B: public virtual A { +}; + +struct C: public virtual A { +}; + +struct D: public B, virtual public C { + D(): B(), C() {} // note an explicit call to C() which is auto-generated +}; + +int main() { + D* d = new D(); + + // Crashes here with the following message: + // *** glibc detected *** ./test: free(): invalid next size (fast) + delete d; +}