From patchwork Sat Jun 2 03:59:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 162398 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 E0770B7008 for ; Sat, 2 Jun 2012 14:00:19 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1339214420; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Message-ID:Date:From:User-Agent:MIME-Version:To:Subject: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=4T57mJI QaFzlrdKJm8IxiSsF9Nk=; b=B1R5Bg1D8QHAWQF5m6WgUvj7LxAhUMXUfx/U+r4 a7n5ERJ5ZmdLa9CAlS/RjCsm74UZnDRaZG2nA8BNY1jzc1ryb5jD7n6gKB4XXoI1 FLnLhfeh+k9wjJFcmPdWTqs7KbTl8MjbMEKG9LHqgLdzOdckAvcPiOrSLldO7Gf4 77LY= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Message-ID:Date:From:User-Agent:MIME-Version:To:Subject:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=y5VF5Xb3JOVXZgxWnNe31hXwunm53Y+23Uaa+GJ04mU7fOX/X/+hgrP8+OmuT/ kAu0Vvercd2Cdupx76FxMsmRxH1KLGFwCdYPcez4lCJRgk/5G6HJBzVtWErjqnIU BHAr0/F9EmvxdmedKoM/xLXodQyK80ee+p0HuonSbLmI0=; Received: (qmail 31703 invoked by alias); 2 Jun 2012 04:00:14 -0000 Received: (qmail 31664 invoked by uid 22791); 2 Jun 2012 04:00:10 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, SPF_HELO_PASS, 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; Sat, 02 Jun 2012 03:59:51 +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 q523xpGw021772 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 1 Jun 2012 23:59:51 -0400 Received: from [10.3.112.17] ([10.3.112.17]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q523xnHl028254 for ; Fri, 1 Jun 2012 23:59:50 -0400 Message-ID: <4FC98FB5.10308@redhat.com> Date: Fri, 01 Jun 2012 23:59:49 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20120430 Thunderbird/12.0.1 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/52973 (wrong visibility with template base) 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 The change in 4.7 to properly restrict visibility of a class based on its template arguments exposed this bug: we were waiting until after the base list is parsed to apply attributes, so if a class is used as a template argument in its own base list, it has the wrong visibility in that context. Fixed by applying infix attributes before parsing the base list. Happily, this also allows us to stop passing attributes around so much. Tested x86_64-pc-linux-gnu, applying to trunk and 4.7. commit c9c80ae94d625b4bddb767441a90543db077127f Author: Jason Merrill Date: Fri Jun 1 23:24:36 2012 -0400 PR c++/52973 * parser.c (cp_parser_class_head): Apply attributes here. * semantics.c (begin_class_definition): Not here. * cp-tree.h: Adjust. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 626c61f..d21c2bf 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5585,7 +5585,7 @@ extern tree finish_fname (tree); extern void finish_translation_unit (void); extern tree finish_template_type_parm (tree, tree); extern tree finish_template_template_parm (tree, tree); -extern tree begin_class_definition (tree, tree); +extern tree begin_class_definition (tree); extern void finish_template_decl (tree); extern tree finish_template_type (tree, tree, int); extern tree finish_base_specifier (tree, tree, bool); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7f9a94b..16139d6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2008,7 +2008,7 @@ static tree cp_parser_class_name static tree cp_parser_class_specifier (cp_parser *); static tree cp_parser_class_head - (cp_parser *, bool *, tree *, tree *); + (cp_parser *, bool *, tree *); static enum tag_types cp_parser_class_key (cp_parser *); static void cp_parser_member_specification_opt @@ -17908,7 +17908,6 @@ cp_parser_class_specifier_1 (cp_parser* parser) /* Parse the class-head. */ type = cp_parser_class_head (parser, &nested_name_specifier_p, - &attributes, &bases); /* If the class-head was a semantic disaster, skip the entire body of the class. */ @@ -17967,7 +17966,7 @@ cp_parser_class_specifier_1 (cp_parser* parser) scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); old_scope = push_inner_scope (scope); } - type = begin_class_definition (type, attributes); + type = begin_class_definition (type); if (type == error_mark_node) /* If the type is erroneous, skip the entire body of the class. */ @@ -18224,7 +18223,6 @@ cp_parser_class_specifier (cp_parser* parser) static tree cp_parser_class_head (cp_parser* parser, bool* nested_name_specifier_p, - tree *attributes_p, tree *bases) { tree nested_name_specifier; @@ -18592,6 +18590,14 @@ cp_parser_class_head (cp_parser* parser, else if (type == error_mark_node) type = NULL_TREE; + if (type) + { + /* Apply attributes now, before any use of the class as a template + argument in its base list. */ + cplus_decl_attributes (&type, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE); + fixup_attribute_variants (type); + } + /* We will have entered the scope containing the class; the names of base classes should be looked up in that context. For example: @@ -18618,7 +18624,6 @@ cp_parser_class_head (cp_parser* parser, if (type) DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; - *attributes_p = attributes; if (type && (virt_specifiers & VIRT_SPEC_FINAL)) CLASSTYPE_FINAL (type) = 1; out: diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 263ebc2..8fefce0 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2516,7 +2516,7 @@ check_template_template_default_arg (tree argument) /* Begin a class definition, as indicated by T. */ tree -begin_class_definition (tree t, tree attributes) +begin_class_definition (tree t) { if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t))) return error_mark_node; @@ -2573,9 +2573,6 @@ begin_class_definition (tree t, tree attributes) pushclass (t); TYPE_BEING_DEFINED (t) = 1; - cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); - fixup_attribute_variants (t); - if (flag_pack_struct) { tree v; @@ -8696,7 +8693,7 @@ begin_lambda_type (tree lambda) xref_basetypes (type, /*bases=*/NULL_TREE); /* Start the class. */ - type = begin_class_definition (type, /*attributes=*/NULL_TREE); + type = begin_class_definition (type); if (type == error_mark_node) return error_mark_node; diff --git a/gcc/objcp/objcp-decl.c b/gcc/objcp/objcp-decl.c index ecc2b2b..8040469 100644 --- a/gcc/objcp/objcp-decl.c +++ b/gcc/objcp/objcp-decl.c @@ -49,7 +49,7 @@ objcp_start_struct (location_t loc ATTRIBUTE_UNUSED, CLASSTYPE_DECLARED_CLASS (s) = 0; /* this is a 'struct', not a 'class'. */ xref_basetypes (s, NULL_TREE); /* no base classes here! */ - return begin_class_definition (s, NULL_TREE); + return begin_class_definition (s); } tree diff --git a/gcc/testsuite/g++.dg/ext/attrib14.C b/gcc/testsuite/g++.dg/ext/attrib14.C index c7e5f7a..ebe0456 100644 --- a/gcc/testsuite/g++.dg/ext/attrib14.C +++ b/gcc/testsuite/g++.dg/ext/attrib14.C @@ -2,8 +2,8 @@ // The bogus attribute is ignored, but was in TYPE_ATTRIBUTES during // parsing of the class, causing some variants to have it and some not. -struct __attribute__((bogus)) A -{ // { dg-warning "ignored" "" } +struct __attribute__((bogus)) A // { dg-warning "ignored" "" } +{ virtual ~A(); void foo(const A&); void bar(const A&); diff --git a/gcc/testsuite/g++.dg/ext/visibility/template12.C b/gcc/testsuite/g++.dg/ext/visibility/template12.C new file mode 100644 index 0000000..b9219d5 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/visibility/template12.C @@ -0,0 +1,13 @@ +// { dg-require-visibility "" } +// { dg-options "-fvisibility=hidden" } +// { dg-final { scan-not-hidden "_ZN1aI1bE1cE" } } + +template class __attribute__((visibility("default"))) a +{ +public: + /* A */ static int c; +}; + +class __attribute__((visibility("default"))) b : a {}; + +template<> /* B */ int a::c = 0;