From patchwork Thu Sep 5 07:27:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1981114 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=JQOjOX++; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WzrYw4wNbz1yg7 for ; Thu, 5 Sep 2024 17:28:20 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CCDB1386480F for ; Thu, 5 Sep 2024 07:28:16 +0000 (GMT) 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 [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 4C8393858406 for ; Thu, 5 Sep 2024 07:27:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4C8393858406 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 4C8393858406 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725521274; cv=none; b=wG5Bb299h4sRartfNiKgUBDX7ROQxSuzj9HK35m7mbvMV7gIYlKBIYOcE4FQ+XOkGrl6lFzg1dR631v7NsIugdWUNisMx8cgbOuIQyWYbGhEuAfttQTUyXh3o5P0uiBdoMDbuYQA8qlBHEZxCiNYRL3mHaOO+4U/7aMI4LNdVJ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725521274; c=relaxed/simple; bh=e4epZxodkWVKk39nAdk7lT8yye0lOry+5+X+Gp2TMG0=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=E+odx8Rrarf3fJ8JA72SUSw7pU1Ys6Bhdtqz4AKppQ2qXK8fp+SW2Ohttk63pwU8KqpV1OFsPfzAZ56NNbUc7K70Fy+G+3ItuNv0KNDw1mHvb2W5ewbkaokrJvJjACA3F+wS1JEoX9H5lvbXGllxKVYD/63ZqAG2PkslPhQ5dOo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1725521272; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=l9UXgkxeY7FwUY6d5DaEbhXXTArUn5b0byNSpGXW8Ms=; b=JQOjOX++yIhfyKPy7nfX9klqJw4iNehXDJRHXfDXGr8H1904Ml3zTl7FE2Eood7yfRQkeV b74KO+o5jj2bo0B3b61SY17JPqHFd9Jcs/u8TrBIsUsvDRinlsYb9LqswrW7662/JDEQeQ tH1GF3eDyXQ6Cs06vQocw4IjL4/8WmE= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-107-VWcr97LiMVGQWhS3NEaw9g-1; Thu, 05 Sep 2024 03:27:50 -0400 X-MC-Unique: VWcr97LiMVGQWhS3NEaw9g-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EAC6819560B8 for ; Thu, 5 Sep 2024 07:27:49 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.29]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4693A1956086; Thu, 5 Sep 2024 07:27:49 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 4857RkSq1837231 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 5 Sep 2024 09:27:46 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 4857RkSp1837230; Thu, 5 Sep 2024 09:27:46 +0200 Date: Thu, 5 Sep 2024 09:27:46 +0200 From: Jakub Jelinek To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: Fix up maybe_unused attribute handling [PR110345] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, RCVD_IN_SBL_CSS, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=no 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Hi! When adding test coverage for maybe_unused attribute, I've run into several things: 1) similarly to deprecated attribute, the attribute shouldn't pedantically appertain to types other than class/enumeration definitions 2) similarly to deprecated attribute, the attribute shouldn't pedantically appertain to unnamed bit-fields 3) the standard says that it can appertain to identifier labels, but we handled it silently also on case and default labels 4) I've run into a weird spurious error on int f [[maybe_unused]]; int & [[maybe_unused]] i = f; int && [[maybe_unused]] j = 0; The problem was that we create an attribute variant for the int & type, then create an attribute variant for the int && type, and the type_canon_hash hashing just thought those 2 are the same, so used int & [[maybe_unused]] type for j rather than int && [[maybe_unused]]. As TYPE_REF_IS_RVALUE is a flag in the generic code, it was easily possible to hash that flag and compare it Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2024-09-05 Jakub Jelinek PR c++/110345 gcc/ * tree.cc (type_hash_canon_hash): Hash TYPE_REF_IS_RVALUE for REFERENCE_TYPE. (type_cache_hasher::equal): Compare TYPE_REF_IS_RVALUE for REFERENCE_TYPE. gcc/cp/ * tree.cc (handle_maybe_unused_attribute): New function. (std_attributes): Use handle_maybe_unused_attribute instead of handle_unused_attribute for maybe_unused attribute. gcc/testsuite/ * g++.dg/cpp0x/attr-maybe_unused1.C: New test. Jakub --- gcc/tree.cc.jj 2024-08-30 16:41:34.712367197 +0200 +++ gcc/tree.cc 2024-09-04 18:52:37.792157965 +0200 @@ -6085,6 +6085,10 @@ type_hash_canon_hash (tree type) hstate.add_poly_int (TYPE_VECTOR_SUBPARTS (type)); break; + case REFERENCE_TYPE: + hstate.add_flag (TYPE_REF_IS_RVALUE (type)); + break; + default: break; } @@ -6127,7 +6131,6 @@ type_cache_hasher::equal (type_hash *a, case OPAQUE_TYPE: case COMPLEX_TYPE: case POINTER_TYPE: - case REFERENCE_TYPE: case NULLPTR_TYPE: return true; @@ -6217,6 +6220,9 @@ type_cache_hasher::equal (type_hash *a, break; return false; + case REFERENCE_TYPE: + return TYPE_REF_IS_RVALUE (a->type) == TYPE_REF_IS_RVALUE (b->type); + default: return false; } --- gcc/cp/tree.cc.jj 2024-09-04 12:36:51.904244104 +0200 +++ gcc/cp/tree.cc 2024-09-04 17:56:08.946371353 +0200 @@ -5106,6 +5106,27 @@ handle_std_deprecated_attribute (tree *n return ret; } +/* The C++17 [[maybe_unused]] attribute mostly maps to the GNU unused + attribute. */ + +static tree +handle_maybe_unused_attribute (tree *node, tree name, tree args, int flags, + bool *no_add_attrs) +{ + tree t = *node; + tree ret = handle_unused_attribute (node, name, args, flags, no_add_attrs); + if (TYPE_P (*node) && t != *node) + pedwarn (input_location, OPT_Wattributes, + "%qE on a type other than class or enumeration definition", name); + else if (TREE_CODE (*node) == FIELD_DECL && DECL_UNNAMED_BIT_FIELD (*node)) + pedwarn (input_location, OPT_Wattributes, "%qE on unnamed bit-field", + name); + else if (TREE_CODE (*node) == LABEL_DECL && DECL_NAME (*node) == NULL_TREE) + pedwarn (input_location, OPT_Wattributes, + "%qE on % or % label", name); + return ret; +} + /* Table of valid C++ attributes. */ static const attribute_spec cxx_gnu_attributes[] = { @@ -5132,7 +5153,7 @@ static const attribute_spec std_attribut { "deprecated", 0, 1, false, false, false, false, handle_std_deprecated_attribute, NULL }, { "maybe_unused", 0, 0, false, false, false, false, - handle_unused_attribute, NULL }, + handle_maybe_unused_attribute, NULL }, { "nodiscard", 0, 1, false, false, false, false, handle_nodiscard_attribute, NULL }, { "no_unique_address", 0, 0, true, false, false, false, --- gcc/testsuite/g++.dg/cpp0x/attr-maybe_unused1.C.jj 2024-09-04 17:28:44.552574792 +0200 +++ gcc/testsuite/g++.dg/cpp0x/attr-maybe_unused1.C 2024-09-04 18:54:14.207069672 +0200 @@ -0,0 +1,148 @@ +// C++ 26 P2552R3 - On the ignorability of standard attributes +// { dg-do compile { target c++11 } } + +int arr[2]; +struct S { int a, b; }; +S arr2[2]; + +void +foo (int n) +{ + [[maybe_unused]] int x1; + [[maybe_unused ("foobar")]] int x2; // { dg-error "'maybe_unused' attribute does not take any arguments" } + // { dg-error "expected primary-expression before 'int'" "" { target *-*-* } .-1 } + [[maybe_unused (0)]] int x3; // { dg-error "'maybe_unused' attribute does not take any arguments" } + // { dg-error "expected primary-expression before 'int'" "" { target *-*-* } .-1 } + + auto a = [] [[maybe_unused]] () {}; + auto b = [] constexpr [[maybe_unused]] {}; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } + // { dg-error "parameter declaration before lambda declaration specifiers only optional with" "" { target c++20_down } .-1 } + // { dg-error "'constexpr' lambda only available with" "" { target c++14_down } .-2 } + auto c = [] noexcept [[maybe_unused]] {}; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } + // { dg-error "parameter declaration before lambda exception specification only optional with" "" { target c++20_down } .-1 } + auto d = [] () [[maybe_unused]] {}; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } + auto e = new int [n] [[maybe_unused]]; // { dg-warning "attributes ignored on outermost array type in new expression" } + auto e2 = new int [n] [[maybe_unused]] [42]; // { dg-warning "attributes ignored on outermost array type in new expression" } + auto f = new int [n][42] [[maybe_unused]]; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } + [[maybe_unused]]; // { dg-warning "attributes at the beginning of statement are ignored" } + [[maybe_unused]] {} // { dg-warning "attributes at the beginning of statement are ignored" } + [[maybe_unused]] if (true) {} // { dg-warning "attributes at the beginning of statement are ignored" } + [[maybe_unused]] while (false) {} // { dg-warning "attributes at the beginning of statement are ignored" } + [[maybe_unused]] goto lab; // { dg-warning "attributes at the beginning of statement are ignored" } + [[maybe_unused]] lab:; + [[maybe_unused]] try {} catch (int) {} // { dg-warning "attributes at the beginning of statement are ignored" } + if ([[maybe_unused]] int x = 0) {} + switch (n) + { + [[maybe_unused]] case 1: // { dg-error "'maybe_unused' on 'case' or 'default' label" } + [[maybe_unused]] break; // { dg-warning "attributes at the beginning of statement are ignored" } + [[maybe_unused]] default: // { dg-error "'maybe_unused' on 'case' or 'default' label" } + break; + } + for ([[maybe_unused]] auto a : arr) {} + for ([[maybe_unused]] auto [a, b] : arr2) {} // { dg-error "structured bindings only available with" "" { target c++14_down } } + [[maybe_unused]] asm (""); // { dg-warning "attributes ignored on 'asm' declaration" } + try {} catch ([[maybe_unused]] int x) {} + try {} catch ([[maybe_unused]] int) {} + try {} catch (int [[maybe_unused]] x) {} // { dg-warning "attribute ignored" } + try {} catch (int [[maybe_unused]]) {} // { dg-warning "attribute ignored" } + try {} catch (int x [[maybe_unused]]) {} +} + +[[maybe_unused]] int bar (); +using foobar [[maybe_unused]] = int; +[[maybe_unused]] int a; +[[maybe_unused]] auto [b, c] = arr; // { dg-error "structured bindings only available with" "" { target c++14_down } } +[[maybe_unused]]; // { dg-warning "attribute ignored" } +inline [[maybe_unused]] void baz () {} // { dg-warning "attribute ignored" } + // { dg-error "standard attributes in middle of decl-specifiers" "" { target *-*-* } .-1 } +constexpr [[maybe_unused]] int qux () { return 0; } // { dg-warning "attribute ignored" } + // { dg-error "standard attributes in middle of decl-specifiers" "" { target *-*-* } .-1 } +int [[maybe_unused]] d; // { dg-warning "attribute ignored" } +int const [[maybe_unused]] e = 1; // { dg-warning "attribute ignored" } +struct A {} [[maybe_unused]]; // { dg-warning "attribute ignored in declaration of 'struct A'" } +struct A [[maybe_unused]]; // { dg-warning "attribute ignored" } +struct A [[maybe_unused]] a1; // { dg-warning "attribute ignored" } +A [[maybe_unused]] a2; // { dg-warning "attribute ignored" } +enum B { B0 } [[maybe_unused]]; // { dg-warning "attribute ignored in declaration of 'enum B'" } +enum B [[maybe_unused]]; // { dg-warning "attribute ignored" } +enum B [[maybe_unused]] b1; // { dg-warning "attribute ignored" } +B [[maybe_unused]] b2; // { dg-warning "attribute ignored" } +struct [[maybe_unused]] C {}; +int f [[maybe_unused]]; +int g[2] [[maybe_unused]]; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } +int g2 [[maybe_unused]] [2]; +int corge () [[maybe_unused]]; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } +int *[[maybe_unused]] h; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } +int & [[maybe_unused]] i = f; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } +int && [[maybe_unused]] j = 0; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } +int S::* [[maybe_unused]] k; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } +auto l = sizeof (int [2] [[maybe_unused]]); // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } +int freddy ([[maybe_unused]] int a, + [[maybe_unused]] int, + [[maybe_unused]] int c = 0, + [[maybe_unused]] int = 0); +void +corge ([[maybe_unused]] int a, + [[maybe_unused]] int, + [[maybe_unused]] int c = 0, + [[maybe_unused]] int = 0) +{ +} +[[maybe_unused]] void +garply () +{ +} +int grault (int [[maybe_unused]] a, // { dg-warning "attribute ignored" } + int [[maybe_unused]], // { dg-warning "attribute ignored" } + int [[maybe_unused]] c = 0, // { dg-warning "attribute ignored" } + int [[maybe_unused]] = 0); // { dg-warning "attribute ignored" } +void +waldo (int [[maybe_unused]] a, // { dg-warning "attribute ignored" } + int [[maybe_unused]], // { dg-warning "attribute ignored" } + int [[maybe_unused]] c = 0, // { dg-warning "attribute ignored" } + int [[maybe_unused]] = 0) // { dg-warning "attribute ignored" } +{ +} +int plugh (int a [[maybe_unused]], + int b [[maybe_unused]] = 0); +void +thud (int a [[maybe_unused]], + int b [[maybe_unused]] = 0) +{ +} +enum [[maybe_unused]] D { D0 }; +enum class [[maybe_unused]] E { E0 }; +enum F {}; +enum [[maybe_unused]] F; // { dg-warning "type attributes ignored after type is already defined" } +enum G { + G0 [[maybe_unused]], + G1 [[maybe_unused]] = 2 +}; +namespace [[maybe_unused]] H { using H0 = int; }// { dg-warning "'maybe_unused' attribute directive ignored" } +namespace [[maybe_unused]] {} // { dg-warning "'maybe_unused' attribute directive ignored" } +[[maybe_unused]] using namespace H; // { dg-warning "'maybe_unused' attribute directive ignored" } +struct [[maybe_unused]] I +{ + [[maybe_unused]]; // { dg-error "declaration does not declare anything" } + [[maybe_unused]] int i; + [[maybe_unused]] int foo (); + [[maybe_unused]] int bar () { return 1; } + [[maybe_unused]] int : 0; // { dg-error "'maybe_unused' on unnamed bit-field" } + [[maybe_unused]] int i2 : 5; + [[maybe_unused]] static int i3; + static int i4; +}; +[[maybe_unused]] int I::i4 = 0; +struct J : [[maybe_unused]] C {}; // { dg-warning "attributes on base specifiers are ignored" } +#if __cpp_concepts >= 201907L +template +concept K [[maybe_unused]] = requires { true; };// { dg-warning "'maybe_unused' attribute ignored" "" { target c++20 } } +#endif +typedef int L [[maybe_unused]]; +template +struct M {}; +template <> +struct [[maybe_unused]] M { int m; }; +typedef int N[2] [[maybe_unused]]; // { dg-error "'maybe_unused' on a type other than class or enumeration definition" } +typedef int O [[maybe_unused]] [2];