From patchwork Wed May 12 02:45:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1477383 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=QoR4pVjv; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Ffzfq4Ww4z9sX2 for ; Wed, 12 May 2021 12:45:22 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 347F1384A029; Wed, 12 May 2021 02:45:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 347F1384A029 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1620787518; bh=cnvMCFT9+3OrZvjOVpjL2USnk4TcfJTckB+WXTJWYGc=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=QoR4pVjviru8282UxyJhlP4qPZIwXH14RK4QwNuBWl5DEVYEvklAdzHmAJwIUgvq6 MdztDi/B0bmcdRJ5n/k82WqPSUEbUetWiY/b4hOCxcs4NXK4tYwlCCWoAkv6H0wDH/ 1qhTqVkGenhvzYePW/zbNmaWM+D7cKPJMXtppFjA= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id AC6E03857C7E for ; Wed, 12 May 2021 02:45:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org AC6E03857C7E Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-473-D_kBjFqfN7W_a70XPFMFHw-1; Tue, 11 May 2021 22:45:12 -0400 X-MC-Unique: D_kBjFqfN7W_a70XPFMFHw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B8D6A1005582 for ; Wed, 12 May 2021 02:45:11 +0000 (UTC) Received: from pdp-11.redhat.com (ovpn-117-221.rdu2.redhat.com [10.10.117.221]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5A5E17DBC6; Wed, 12 May 2021 02:45:11 +0000 (UTC) To: Jason Merrill , GCC Patches Subject: [PATCH] c++: Check attributes on friend declarations [PR99032] Date: Tue, 11 May 2021 22:45:03 -0400 Message-Id: <20210512024503.398582-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" This patch implements [dcl.attr.grammar]/5: "If an attribute-specifier-seq appertains to a friend declaration ([class.friend]), that declaration shall be a definition." This restriction only applies to C++11-style attributes. There are various forms of friend declarations, we have friend templates, C++11 extended friend declarations, and so on. In some cases we already ignore the attribute and warn that it was ignored. But certain cases weren't diagnosed, and with this patch we'll give a hard error. I tried hard not to emit both a warning and error and I think it worked out. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? gcc/cp/ChangeLog: PR c++/99032 * decl.c (grokdeclarator): Diagnose when an attribute appertains to a friend declaration that is not a definition. * parser.c (cp_parser_elaborated_type_specifier): Likewise. (cp_parser_member_declaration): Likewise. gcc/testsuite/ChangeLog: PR c++/99032 * g++.dg/cpp0x/friend7.C: New test. --- gcc/cp/decl.c | 4 +++ gcc/cp/parser.c | 15 +++++++++- gcc/testsuite/g++.dg/cpp0x/friend7.C | 41 ++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/friend7.C base-commit: 71d38ec80008afdbb9a059253407d80598b765c0 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index bc3928d7f85..687a59d49e3 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13741,6 +13741,10 @@ grokdeclarator (const cp_declarator *declarator, if (friendp) { + if (attrlist && !funcdef_flag + && cxx11_attribute_p (*attrlist)) + error_at (id_loc, "attribute appertains to a friend declaration " + "that is not a definition"); /* Friends are treated specially. */ if (ctype == current_class_type) ; /* We already issued a permerror. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0fe29c658d2..612ca4598b9 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -19764,11 +19764,15 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, && ! processing_explicit_instantiation) warning (OPT_Wattributes, "attributes ignored on template instantiation"); + else if (is_friend && cxx11_attribute_p (attributes)) + error ("attribute appertains to a friend declaration that is not " + "a definition"); else if (is_declaration && cp_parser_declares_only_class_p (parser)) cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); else warning (OPT_Wattributes, - "attributes ignored on elaborated-type-specifier that is not a forward declaration"); + "attributes ignored on elaborated-type-specifier that is " + "not a forward declaration"); } if (tag_type == enum_type) @@ -26054,6 +26058,15 @@ cp_parser_member_declaration (cp_parser* parser) error_at (decl_spec_token_start->location, "friend declaration does not name a class or " "function"); + /* Give an error if an attribute cannot appear here, as per + [dcl.attr.grammar]/5. But not when declares_class_or_enum: + we ignore attributes in elaborated-type-specifiers. */ + else if (!declares_class_or_enum + && (cxx11_attribute_p (decl_specifiers.std_attributes) + || cxx11_attribute_p (decl_specifiers.attributes))) + error_at (decl_spec_token_start->location, + "attribute appertains to a friend declaration " + "that is not a definition"); else make_friend_class (current_class_type, type, /*complain=*/true); diff --git a/gcc/testsuite/g++.dg/cpp0x/friend7.C b/gcc/testsuite/g++.dg/cpp0x/friend7.C new file mode 100644 index 00000000000..4aa7b14cf7d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/friend7.C @@ -0,0 +1,41 @@ +// PR c++/99032 +// { dg-do compile { target c++11 } } + +class X { }; +template +void foo (T1, T2); + +struct S { + [[deprecated]] friend void f(); // { dg-error "attribute appertains" } + [[deprecated]] friend void f2() { } + __attribute__((deprecated)) friend void f3(); + friend void f3 [[deprecated]] (); // { dg-error "attribute appertains" } + friend void f4 [[deprecated]] () { } + [[deprecated]] friend void; // { dg-error "attribute appertains" } + friend [[deprecated]] void; // { dg-error "attribute appertains" } + __attribute__((deprecated)) friend int; + friend __attribute__((deprecated)) int; + friend int __attribute__((deprecated)); + [[deprecated]] friend X; // { dg-error "attribute appertains" } + [[deprecated]] friend class N; // { dg-warning "attribute ignored" } + friend class [[deprecated]] N2; // { dg-error "attribute appertains" } + friend class __attribute__((deprecated)) N3; + [[deprecated]] friend void foo<>(int, int); // { dg-error "attribute appertains" } + // FIXME: Add dg error when PR100339 is resolved. + //[[deprecated]] friend void ::foo(int, int); +}; + +template +class node { }; + +template +struct A { + [[deprecated]] friend T; // { dg-error "attribute appertains" } + [[deprecated]] friend class node; // { dg-warning "attribute ignored" } + template + [[deprecated]] friend class A; // { dg-warning "attribute ignored" } + template + [[deprecated]] friend void bar () { } + template + [[deprecated]] friend void baz (); // { dg-error "attribute appertains" } +};