From patchwork Mon Jul 5 20:45:31 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Carlini X-Patchwork-Id: 57930 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 024D9B6EF7 for ; Tue, 6 Jul 2010 06:47:42 +1000 (EST) Received: (qmail 14727 invoked by alias); 5 Jul 2010 20:47:40 -0000 Received: (qmail 14711 invoked by uid 22791); 5 Jul 2010 20:47:38 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from rcsinet10.oracle.com (HELO rcsinet10.oracle.com) (148.87.113.121) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 05 Jul 2010 20:47:30 +0000 Received: from rcsinet13.oracle.com (rcsinet13.oracle.com [148.87.113.125]) by rcsinet10.oracle.com (Switch-3.4.2/Switch-3.4.2) with ESMTP id o65KlQEs008886 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 5 Jul 2010 20:47:27 GMT Received: from acsmt353.oracle.com (acsmt353.oracle.com [141.146.40.153]) by rcsinet13.oracle.com (Switch-3.4.2/Switch-3.4.1) with ESMTP id o65BIihH000909; Mon, 5 Jul 2010 20:47:25 GMT Received: from abhmt018.oracle.com by acsmt353.oracle.com with ESMTP id 399074971278362734; Mon, 05 Jul 2010 13:45:34 -0700 Received: from [192.168.0.4] (/79.52.240.176) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 05 Jul 2010 13:45:33 -0700 Message-ID: <4C32446B.90807@oracle.com> Date: Mon, 05 Jul 2010 22:45:31 +0200 From: Paolo Carlini User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.10) Gecko/20100520 SUSE/3.0.5 Thunderbird/3.0.5 MIME-Version: 1.0 To: Jason Merrill CC: "gcc-patches@gcc.gnu.org" Subject: [C++ Patch] PR 44625, v2 References: <4C31C773.3050000@oracle.com> <4C31D9C7.9000209@redhat.com> <4C31DA00.5070100@oracle.com> In-Reply-To: <4C31DA00.5070100@oracle.com> X-IsSubscribed: yes 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 Hi again, this is my second try: the idea is avoiding completely creating COMPONENT_REFs with a null operand 1, as suggested by Jason. I also tidied a bit the original testcase and added a second for anonymous union inside anonymous union. About error17.C, we now emit one less diagnostic message, similarly to ICC, turns out. Tested x86_64-linux. Is this one better? Mainline only, in my opinion... Paolo. //////////////////// /cp 2010-07-05 Paolo Carlini PR c++/44625 * decl2.c (build_anon_union_vars): Avoid creating COMPONENT_REFs with a null operand 1; tidy, reformat. /testsuite 2010-07-05 Paolo Carlini PR c++/44625 * g++.dg/template/crash102.C: New. * g++.dg/template/crash103.C: Likewise. * g++.dg/template/error17.C: Adjust. Index: testsuite/g++.dg/template/crash102.C =================================================================== --- testsuite/g++.dg/template/crash102.C (revision 0) +++ testsuite/g++.dg/template/crash102.C (revision 0) @@ -0,0 +1,19 @@ +// PR c++/44625 +// { dg-do compile } +// { dg-options "" } + +template struct Vec { + Vec& operator^=(Vec& rhs) { + union { + struct {FP_ x,y,z;}; + }; // { dg-error "anonymous struct" } + y*rhs.z() - z*rhs.y(); // { dg-error "not declared|no member" } + return *this; + } + Vec& operator^(Vec& rhs) { + return Vec(*this)^=rhs; // { dg-message "instantiated" } + } +}; +Vec v; +Vec V; +Vec c = v^V; // { dg-message "instantiated" } Index: testsuite/g++.dg/template/error17.C =================================================================== --- testsuite/g++.dg/template/error17.C (revision 161841) +++ testsuite/g++.dg/template/error17.C (working copy) @@ -4,7 +4,6 @@ template void foo() { - union { struct { }; }; // { dg-error "prohibits anonymous struct" "anon" } + union { struct { }; }; // { dg-error "prohibits anonymous struct" } // { dg-error "not inside" "not inside" { target *-*-* } 7 } - // { dg-warning "no members" "no members" { target *-*-* } 7 } } Index: testsuite/g++.dg/template/crash103.C =================================================================== --- testsuite/g++.dg/template/crash103.C (revision 0) +++ testsuite/g++.dg/template/crash103.C (revision 0) @@ -0,0 +1,19 @@ +// PR c++/44625 +// { dg-do compile } +// { dg-options "" } + +template struct Vec { + Vec& operator^=(Vec& rhs) { + union { + union {FP_ x,y,z;}; + }; + y*rhs.z() - z*rhs.y(); // { dg-error "not declared|no member" } + return *this; + } + Vec& operator^(Vec& rhs) { + return Vec(*this)^=rhs; // { dg-message "instantiated" } + } +}; +Vec v; +Vec V; +Vec c = v^V; // { dg-message "instantiated" } Index: cp/decl2.c =================================================================== --- cp/decl2.c (revision 161844) +++ cp/decl2.c (working copy) @@ -1319,40 +1319,50 @@ build_anon_union_vars (tree type, tree object) if (TREE_CODE (type) != UNION_TYPE) error ("anonymous struct not inside named type"); + if (!object) + return error_mark_node; + for (field = TYPE_FIELDS (type); field != NULL_TREE; field = TREE_CHAIN (field)) { tree decl; - tree ref; + tree ref = NULL_TREE; + tree name; if (DECL_ARTIFICIAL (field)) continue; if (TREE_CODE (field) != FIELD_DECL) { - permerror (input_location, "%q+#D invalid; an anonymous union can only " - "have non-static data members", field); + permerror (input_location, "%q+#D invalid; an anonymous union can " + "only have non-static data members", field); continue; } if (TREE_PRIVATE (field)) - permerror (input_location, "private member %q+#D in anonymous union", field); + permerror (input_location, "private member %q+#D in anonymous union", + field); else if (TREE_PROTECTED (field)) - permerror (input_location, "protected member %q+#D in anonymous union", field); + permerror (input_location, "protected member %q+#D in anonymous union", + field); + name = DECL_NAME (field); + if (processing_template_decl) - ref = build_min_nt (COMPONENT_REF, object, - DECL_NAME (field), NULL_TREE); + { + if (name) + ref = build_min_nt (COMPONENT_REF, object, name, NULL_TREE); + } else ref = build_class_member_access_expr (object, field, NULL_TREE, false, tf_warning_or_error); - if (DECL_NAME (field)) + if (name) { tree base; decl = build_decl (input_location, - VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); + VAR_DECL, name, TREE_TYPE (field)); DECL_ANON_UNION_VAR_P (decl) = 1; DECL_ARTIFICIAL (decl) = 1;