From patchwork Thu May 30 19:19:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 247677 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 004562C0090 for ; Fri, 31 May 2013 05:19:54 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=KwAp0INkybG/WwASTdUzzb8AjcUumQSYDU2YBzQdUrnTwN P1YX0i+egIN5a7Ie7mPSbSS28NIXUoJYGh34miCGU31CERRwMsvWsCgp2Z0Jn0rP shCgIdsdVoC9DNzSu2i3IWYyT+udLJhLUfm03nm/iH4DslSf5X6XxibFOOelA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=u/ltykwHpt5uzerQkasIxIB4770=; b=iVxv2PUluJMCUQEw+u3c k4J6odpa9bMDJXxDARP2iQoJMnzivl0bHRmsbqO0rEj47OF73KCn03x3cy84sgNB OGBroHwTrbjndDo5EU/k7rTnfPb37QIpA1PV+JgU3zaUDVK1xkUmR69gI+e5Y8xm BoORDbUtply2rl9/sVENMtI= Received: (qmail 5636 invoked by alias); 30 May 2013 19:19:48 -0000 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 Received: (qmail 5627 invoked by uid 89); 30 May 2013 19:19:48 -0000 X-Spam-SWARE-Status: No, score=-6.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 30 May 2013 19:19:48 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r4UJJkpQ022969 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 30 May 2013 15:19:46 -0400 Received: from [10.3.113.8] ([10.3.113.8]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r4UJJgp7028239 for ; Thu, 30 May 2013 15:19:43 -0400 Message-ID: <51A7A64E.9020601@redhat.com> Date: Thu, 30 May 2013 15:19:42 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:23.0) Gecko/20100101 Thunderbird/23.0a2 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/52377 (NSDMI and unions) X-Virus-Found: No sort_mem_initializers was skipping over all fields without a mem-initializer, even ones with an NSDMI. Tested x86_64-pc-linux-gnu, applying to trunk. commit 25b01320a7aefae42d9e14f3807247ca8f88ae40 Author: Jason Merrill Date: Sat May 25 17:28:15 2013 -0400 PR c++/52377 * class.c (common_enclosing_class): New. * cp-tree.h: Declare it. * init.c (sort_mem_initializers): Don't splice out a union member with an NSDMI. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 90b31bf..64918c6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -9261,4 +9261,30 @@ publicly_uniquely_derived_p (tree parent, tree type) return base && base != error_mark_node; } +/* CTX1 and CTX2 are declaration contexts. Return the innermost common + class between them, if any. */ + +tree +common_enclosing_class (tree ctx1, tree ctx2) +{ + if (!TYPE_P (ctx1) || !TYPE_P (ctx2)) + return NULL_TREE; + gcc_assert (ctx1 == TYPE_MAIN_VARIANT (ctx1) + && ctx2 == TYPE_MAIN_VARIANT (ctx2)); + if (ctx1 == ctx2) + return ctx1; + for (tree t = ctx1; TYPE_P (t); t = TYPE_CONTEXT (t)) + TYPE_MARKED_P (t) = true; + tree found = NULL_TREE; + for (tree t = ctx2; TYPE_P (t); t = TYPE_CONTEXT (t)) + if (TYPE_MARKED_P (t)) + { + found = t; + break; + } + for (tree t = ctx1; TYPE_P (t); t = TYPE_CONTEXT (t)) + TYPE_MARKED_P (t) = false; + return found; +} + #include "gt-cp-class.h" diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1f85ca7..aebc440 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5112,6 +5112,7 @@ extern void deduce_noexcept_on_destructor (tree); extern void insert_late_enum_def_into_classtype_sorted_fields (tree, tree); extern bool uniquely_derived_from_p (tree, tree); extern bool publicly_uniquely_derived_p (tree, tree); +extern tree common_enclosing_class (tree, tree); /* in cvt.c */ extern tree convert_to_reference (tree, tree, int, int, tree, diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 671c774..4edd150 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -914,13 +914,12 @@ sort_mem_initializers (tree t, tree mem_inits) Here we also splice out uninitialized union members. */ if (uses_unions_p) { - tree last_field = NULL_TREE; + tree *last_p = NULL; tree *p; for (p = &sorted_inits; *p; ) { tree field; tree ctx; - int done; init = *p; @@ -940,22 +939,25 @@ sort_mem_initializers (tree t, tree mem_inits) for (ctx = DECL_CONTEXT (field); !same_type_p (ctx, t); ctx = TYPE_CONTEXT (ctx)) - if (TREE_CODE (ctx) == UNION_TYPE) + if (TREE_CODE (ctx) == UNION_TYPE + || !ANON_AGGR_TYPE_P (ctx)) break; /* If this field is not a member of a union, skip it. */ if (TREE_CODE (ctx) != UNION_TYPE) goto next; - /* If this union member has no explicit initializer, splice - it out. */ - if (!TREE_VALUE (init)) + /* If this union member has no explicit initializer and no NSDMI, + splice it out. */ + if (TREE_VALUE (init) || DECL_INITIAL (field)) + /* OK. */; + else goto splice; /* It's only an error if we have two initializers for the same union type. */ - if (!last_field) + if (!last_p) { - last_field = field; + last_p = p; goto next; } @@ -967,41 +969,23 @@ sort_mem_initializers (tree t, tree mem_inits) union { struct { int i; int j; }; }; initializing both `i' and `j' makes sense. */ - ctx = DECL_CONTEXT (field); - done = 0; - do + ctx = common_enclosing_class (DECL_CONTEXT (field), + DECL_CONTEXT (TREE_PURPOSE (*last_p))); + + if (ctx && TREE_CODE (ctx) == UNION_TYPE) { - tree last_ctx; - - last_ctx = DECL_CONTEXT (last_field); - while (1) - { - if (same_type_p (last_ctx, ctx)) - { - if (TREE_CODE (ctx) == UNION_TYPE) - error_at (DECL_SOURCE_LOCATION (current_function_decl), - "initializations for multiple members of %qT", - last_ctx); - done = 1; - break; - } - - if (same_type_p (last_ctx, t)) - break; - - last_ctx = TYPE_CONTEXT (last_ctx); - } - - /* If we've reached the outermost class, then we're - done. */ - if (same_type_p (ctx, t)) - break; - - ctx = TYPE_CONTEXT (ctx); + /* A mem-initializer hides an NSDMI. */ + if (TREE_VALUE (init) && !TREE_VALUE (*last_p)) + *last_p = TREE_CHAIN (*last_p); + else if (TREE_VALUE (*last_p) && !TREE_VALUE (init)) + goto splice; + else + error_at (DECL_SOURCE_LOCATION (current_function_decl), + "initializations for multiple members of %qT", + ctx); } - while (!done); - last_field = field; + last_p = p; next: p = &TREE_CHAIN (*p); diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C new file mode 100644 index 0000000..11bdd88 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C @@ -0,0 +1,25 @@ +// PR c++/52377 +// { dg-do run { target c++11 } } + +union Test +{ + int a{4}; +}; + +union B +{ + int i = 42; + double d; + B() = default; + B(double d): d(d) { } +}; + +int main() +{ + Test t; + B b; + B b2(4.2); + + if (t.a != 4 || b.i != 42 || b2.d != 4.2) + __builtin_abort(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union2.C new file mode 100644 index 0000000..b45fe83 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union2.C @@ -0,0 +1,18 @@ +// PR c++/52377 +// { dg-do run { target c++11 } } + +union A // { dg-error "multiple" } +{ + int i = 4; + int j = 2; +}; + +A a; + +union B +{ + int i,j; + B(): i(1), j(2) {} // { dg-error "multiple" } +}; + +B b;