From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id EC3543857B95 for ; Sat, 4 Jun 2022 00:05:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EC3543857B95 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-221-BuDEXv4uOEKcyWItX6Pptw-1; Fri, 03 Jun 2022 20:05:16 -0400 X-MC-Unique: BuDEXv4uOEKcyWItX6Pptw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 057EE801228; Sat, 4 Jun 2022 00:05:16 +0000 (UTC) Received: from pdp-11.hsd1.ma.comcast.net (unknown [10.22.8.245]) by smtp.corp.redhat.com (Postfix) with ESMTP id B922B1121314; Sat, 4 Jun 2022 00:05:15 +0000 (UTC) From: Marek Polacek To: Jason Merrill , GCC Patches Cc: Joseph Myers Subject: [PATCH] c++: Allow mixing GNU/std-style attributes [PR69585] Date: Fri, 3 Jun 2022 20:05:11 -0400 Message-Id: <20220604000511.108367-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.4 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_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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-List-Received-Date: Sat, 04 Jun 2022 00:05:21 -0000 cp_parser_attributes_opt doesn't accept GNU attributes followed by [[]] attributes and vice versa; only a sequence of attributes of the same kind. That causes grief for code like: struct __attribute__ ((may_alias)) alignas (2) struct S { }; or #define EXPORT __attribute__((visibility("default"))) struct [[nodiscard]] EXPORT F { }; It doesn't seem to a documented restriction, so this patch fixes the problem. However, the patch does not touch the C FE. The C FE doesn't have a counterpart to C++'s cp_parser_attributes_opt -- it only has c_parser_transaction_attributes (which parses both GNU and [[]] attributes), but that's TM-specific. The C FE seems to use either c_parser_gnu_attributes or c_parser_std_attribute_specifier_sequence. As a consequence, this works: [[maybe_unused]] __attribute__((deprecated)) void f2 (); but this doesn't: __attribute__((deprecated)) [[maybe_unused]] void f1 (); I'm not sure what, if anything, should be done about this. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? PR c++/102399 PR c++/69585 gcc/cp/ChangeLog: * parser.cc (cp_parser_attributes_opt): Accept GNU attributes followed by [[]] attributes and vice versa. gcc/testsuite/ChangeLog: * g++.dg/ext/attrib65.C: New test. * g++.dg/ext/attrib66.C: New test. * g++.dg/ext/attrib67.C: New test. --- gcc/cp/parser.cc | 14 +++++++++++--- gcc/testsuite/g++.dg/ext/attrib65.C | 7 +++++++ gcc/testsuite/g++.dg/ext/attrib66.C | 27 +++++++++++++++++++++++++++ gcc/testsuite/g++.dg/ext/attrib67.C | 27 +++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/attrib65.C create mode 100644 gcc/testsuite/g++.dg/ext/attrib66.C create mode 100644 gcc/testsuite/g++.dg/ext/attrib67.C diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 3fc73442da5..535bf7eedbb 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -28727,9 +28727,17 @@ cp_nth_tokens_can_be_attribute_p (cp_parser *parser, size_t n) static tree cp_parser_attributes_opt (cp_parser *parser) { - if (cp_next_tokens_can_be_gnu_attribute_p (parser)) - return cp_parser_gnu_attributes_opt (parser); - return cp_parser_std_attribute_spec_seq (parser); + tree attrs = NULL_TREE; + while (true) + { + if (cp_next_tokens_can_be_gnu_attribute_p (parser)) + attrs = attr_chainon (attrs, cp_parser_gnu_attributes_opt (parser)); + else if (cp_next_tokens_can_be_std_attribute_p (parser)) + attrs = attr_chainon (attrs, cp_parser_std_attribute_spec_seq (parser)); + else + break; + } + return attrs; } /* Parse an (optional) series of attributes. diff --git a/gcc/testsuite/g++.dg/ext/attrib65.C b/gcc/testsuite/g++.dg/ext/attrib65.C new file mode 100644 index 00000000000..0af138700f6 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attrib65.C @@ -0,0 +1,7 @@ +// PR c++/102399 +// { dg-do compile { target c++11 } } +// Test mixing the GNU and standard forms of attributes. + +#define EXPORT __attribute__((visibility("default"))) + +struct [[nodiscard]] EXPORT Foo { Foo(); }; diff --git a/gcc/testsuite/g++.dg/ext/attrib66.C b/gcc/testsuite/g++.dg/ext/attrib66.C new file mode 100644 index 00000000000..102ed709b1d --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attrib66.C @@ -0,0 +1,27 @@ +// PR c++/69585 +// { dg-do compile { target c++11 } } + +struct __attribute__ ((aligned (2))) __attribute__ ((may_alias)) +S1 { }; + +struct __attribute__ ((aligned (2))) [[gnu::may_alias]] +S2 { }; + +struct alignas (2) __attribute__ ((may_alias)) +S3 { }; + +struct alignas (2) [[gnu::may_alias]] +S4 { }; + + +struct __attribute__ ((may_alias)) __attribute__ ((aligned (2))) +S1_2 { }; + +struct [[gnu::may_alias]] __attribute__ ((aligned (2))) +S2_2 { }; + +struct __attribute__ ((may_alias)) alignas (2) +S3_2 { }; + +struct [[gnu::may_alias]] alignas (2) +S4_2 { }; diff --git a/gcc/testsuite/g++.dg/ext/attrib67.C b/gcc/testsuite/g++.dg/ext/attrib67.C new file mode 100644 index 00000000000..a5107665077 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attrib67.C @@ -0,0 +1,27 @@ +// PR c++/69585 +// { dg-do compile { target c++11 } } +// Test mixing the GNU and standard forms of attributes. + +__attribute__((deprecated)) [[maybe_unused]] void f1 (); +[[maybe_unused]] __attribute__((deprecated)) void f2 (); +[[maybe_unused]] __attribute__((deprecated)) [[nodiscard]] int f3 (); +__attribute__((unused)) [[nodiscard]] __attribute__((deprecated)) int f4 (); + +struct [[maybe_unused]] __attribute__((aligned)) S1 { double d; }; +struct __attribute__((aligned)) [[maybe_unused]] S2 { double d; }; + +enum E { + X [[maybe_unused]] __attribute__((unavailable)), + Y __attribute__((unavailable)) [[maybe_unused]], +}; + +void +g ([[maybe_unused]] __attribute__((unavailable)) int i1, + __attribute__((unavailable)) [[maybe_unused]] int i2) +{ + [[maybe_unused]] __attribute__((aligned)) int i3; + __attribute__((aligned)) [[maybe_unused]] int i4; + +[[maybe_unused]] +lab: __attribute__((cold)); +} base-commit: 891d64721626f45fb95fa47a57a3f396b80f31e9 -- 2.36.1