From patchwork Wed Sep 4 12:15:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 97045 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E5F80385DDD4 for ; Wed, 4 Sep 2024 12:18:10 +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.133.124]) by sourceware.org (Postfix) with ESMTP id 915DF385C6D2 for ; Wed, 4 Sep 2024 12:17:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 915DF385C6D2 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 915DF385C6D2 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725452239; cv=none; b=OvNa1S2BmrYCxtsru/gfDiwXIf8bPlrXO9jsCAAdNrUPx5MQLVunh2SzOLWCtUVRHpGyNxK3sBWJMgZbtdk/RHHKDjeCi36lgtzNMdJX1b+4BxR3Qow0BCCZntzaw8TQ3cVV6GIN6bh6dqid20ec93FgpAdDTw9wxl/MazNRzeg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725452239; c=relaxed/simple; bh=DiKLtMy+6HKwByyzWEkTvOyAea04/6m7gfkb3y7c/xQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=maUlqFaon3x+0PXMaV/AoqDyXz6OHCiPXxZ06J2y2eK2I6Uw/C0YtGikv1BTYo7Fyi1glPuyXWsJyTgws/TZPxuAEQDCRjh2R8BAWc5veyQ7rAiLQEG+lZ6dN67yxqpqXuKYG89Bkvqb5XUV1FqUj5ntSNbo6RzTQoxVYws261A= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1725452237; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qTc/ZIkkI5a4y3xunY9m/pSJZmwD4fpLuXV2it3U9i0=; b=f4md1IfbIuyTf6UbefoshRBHVPU1I3ECqUD6MJegX84wcD1sOH/FqyIsWswtFKFy/oWpqd LLROE16FlSbJdsuFkao62DtK90RzN52WGsnz5shCd4e4BNsVEL8OUItOGNlmGWspaDy2Fm yq6E025K3dL7/tz+yIClQaycK6zGk00= Received: from mail-il1-f197.google.com (mail-il1-f197.google.com [209.85.166.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-196-ct7yX3aPMKCLepGExPPnsA-1; Wed, 04 Sep 2024 08:17:14 -0400 X-MC-Unique: ct7yX3aPMKCLepGExPPnsA-1 Received: by mail-il1-f197.google.com with SMTP id e9e14a558f8ab-39d2ceca837so81967095ab.2 for ; Wed, 04 Sep 2024 05:17:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725452233; x=1726057033; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=qTc/ZIkkI5a4y3xunY9m/pSJZmwD4fpLuXV2it3U9i0=; b=u9KhkIW14hgEd6IhICKf3WZkFga6odwMBDccGRfdL7NrRWiDCmDzg1PtXiZF86YbeN ORtaKUluyRkY5kjaI0ORT8vp8GGcBzl7a5fIDxCFPFBF1eIWmVpe9gUO2Rfzel1CV61s 3jRGphD4jNWLQR9tpm2c4e4MAC7ZfmQhs8r92labBeL/+gj92FH8G5CqCkuEQU7aCWya FvHJZzIGaf21AfpA5X+SDs+lg8NTi6UM9GNWVcXmK5/QxK2bpOlFNIf9q8rUdEOpnr0k Emz3PmnuHfW+jcx8e60nA/SzK+EEkKQqUUA4utUNX10iLyURf+Fikpp2nmPeLk0z+IbX Qa4A== X-Gm-Message-State: AOJu0YxdeVrMz/Ac4BQ7pXt/75cTKzp9SiYskLG6/PwCI+i+Hrl0VGaW 1LUg5rGl7XMBuOYPqqNxE3zn5HE765u4CG0Rt5tyEUxFTu49zKaGHybP28R34nfc+6+8iqBwL5V H11noxm4cpr3Q5Xgi7P7Yv3A9W6xe953Cygzysaz7nMBvJhYn0p0PY1DiQZ/wHr7JvlzI/PnlEP Ag08y1Q84AXN93eqjlra3zxz5cep32v2a9UEQ= X-Received: by 2002:a05:6e02:b27:b0:398:3b82:4ae2 with SMTP id e9e14a558f8ab-39f377cb90amr251237375ab.5.1725452233343; Wed, 04 Sep 2024 05:17:13 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEu5mEUGJOASsDliyyGatO1xRtzDKuwSfvMJ4gzMwiti+pa4DUoROzB4UVlCPAhNcP7S7v14A== X-Received: by 2002:a05:6e02:b27:b0:398:3b82:4ae2 with SMTP id e9e14a558f8ab-39f377cb90amr251236745ab.5.1725452232692; Wed, 04 Sep 2024 05:17:12 -0700 (PDT) Received: from jason-thinkpadp1gen4i.rmtusma.csb (130-44-146-16.s12558.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.146.16]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-39f3b05bfd3sm36483625ab.85.2024.09.04.05.17.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 05:17:11 -0700 (PDT) From: Jason Merrill To: gcc-patches@gcc.gnu.org Cc: Joseph Myers , Marek Polacek Subject: [PATCH RFC] c-family: add attribute flag_enum [PR46457] Date: Wed, 4 Sep 2024 08:15:25 -0400 Message-ID: <20240904121710.2874535-1-jason@redhat.com> X-Mailer: git-send-email 2.46.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.3 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, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org Tested x86_64-pc-linux-gnu. Any objections? -- 8< -- Several PRs complain about -Wswitch warning about a case for a bitwise combination of enumerators. Clang has an attribute flag_enum to prevent this; let's adopt that approach as well. This also recognizes the attribute as [[clang::flag_enum]], introducing handling of the clang attribute namespace. PR c++/46457 gcc/c-family/ChangeLog: * c-attribs.cc (handle_flag_enum_attribute): New. (c_common_gnu_attributes): Add it. (c_common_clang_attributes, c_common_clang_attribute_table): New. * c-common.h: Declare c_common_clang_attribute_table. * c-warn.cc (c_do_switch_warnings): Handle flag_enum. gcc/c/ChangeLog: * c-objc-common.h (c_objc_attribute_table): Add c_common_clang_attribute_table. gcc/cp/ChangeLog: * cp-objcp-common.h (cp_objcp_attribute_table): Add c_common_clang_attribute_table. gcc/testsuite/ChangeLog: * c-c++-common/attr-flag-enum-1.c: New test. gcc/ChangeLog: * doc/extend.texi: Document flag_enum attribute. * doc/invoke.texi: Mention flag_enum in -Wswitch. libstdc++-v3/ChangeLog: * include/bits/regex_constants.h: Use flag_enum. --- gcc/doc/extend.texi | 7 ++++ gcc/doc/invoke.texi | 11 +++--- gcc/c-family/c-common.h | 1 + gcc/c/c-objc-common.h | 1 + gcc/cp/cp-objcp-common.h | 1 + libstdc++-v3/include/bits/regex_constants.h | 2 +- gcc/c-family/c-attribs.cc | 33 +++++++++++++++++ gcc/c-family/c-warn.cc | 4 ++ gcc/testsuite/c-c++-common/attr-flag-enum-1.c | 37 +++++++++++++++++++ 9 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/attr-flag-enum-1.c base-commit: 3775f71c8909b3531fe002138814fa2504ec2e8b diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 5845bcedf6e..5b9d8c51059 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -9187,6 +9187,13 @@ initialization will result in future breakage. GCC emits warnings based on this attribute by default; use @option{-Wno-designated-init} to suppress them. +@cindex @code{flag_enum} type attribute +@item flag_enum +This attribute may be applied to an enumerated type to indicate that +its enumerators are used in bitwise operations, so e.g. @option{-Wswitch} +should not warn about a @code{case} that corresponds to a bitwise +combination of enumerators. + @cindex @code{hardbool} type attribute @item hardbool @itemx hardbool (@var{false_value}) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 43afb0984e5..7c6175efbc0 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -7672,9 +7672,9 @@ unless C++14 mode (or newer) is active. Warn whenever a @code{switch} statement has an index of enumerated type and lacks a @code{case} for one or more of the named codes of that enumeration. (The presence of a @code{default} label prevents this -warning.) @code{case} labels outside the enumeration range also -provoke warnings when this option is used (even if there is a -@code{default} label). +warning.) @code{case} labels that do not correspond to enumerators also +provoke warnings when this option is used, unless the enumeration is marked +with the @code{flag_enum} attribute. This warning is enabled by @option{-Wall}. @opindex Wswitch-default @@ -7688,8 +7688,9 @@ case. @item -Wswitch-enum Warn whenever a @code{switch} statement has an index of enumerated type and lacks a @code{case} for one or more of the named codes of that -enumeration. @code{case} labels outside the enumeration range also -provoke warnings when this option is used. The only difference +enumeration. @code{case} labels that do not correspond to enumerators also +provoke warnings when this option is used, unless the enumeration is marked +with the @code{flag_enum} attribute. The only difference between @option{-Wswitch} and this option is that this option gives a warning about an omitted enumeration code even if there is a @code{default} label. diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index d3827573a36..027f077d51b 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -821,6 +821,7 @@ extern struct visibility_flags visibility_options; /* Attribute table common to the C front ends. */ extern const struct scoped_attribute_specs c_common_gnu_attribute_table; +extern const struct scoped_attribute_specs c_common_clang_attribute_table; extern const struct scoped_attribute_specs c_common_format_attribute_table; /* Pointer to function to lazily generate the VAR_DECL for __FUNCTION__ etc. diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index 20af5a5bb94..365b5938803 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -79,6 +79,7 @@ static const scoped_attribute_specs *const c_objc_attribute_table[] = { &std_attribute_table, &c_common_gnu_attribute_table, + &c_common_clang_attribute_table, &c_common_format_attribute_table }; diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 0e6664cf9c3..e9c5ac40020 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -128,6 +128,7 @@ static const scoped_attribute_specs *const cp_objcp_attribute_table[] = &std_attribute_table, &cxx_gnu_attribute_table, &c_common_gnu_attribute_table, + &c_common_clang_attribute_table, &c_common_format_attribute_table }; diff --git a/libstdc++-v3/include/bits/regex_constants.h b/libstdc++-v3/include/bits/regex_constants.h index 437895f1dc3..4148093bc4e 100644 --- a/libstdc++-v3/include/bits/regex_constants.h +++ b/libstdc++-v3/include/bits/regex_constants.h @@ -66,7 +66,7 @@ namespace regex_constants * elements @c ECMAScript, @c basic, @c extended, @c awk, @c grep, @c egrep * %set. */ - enum syntax_option_type : unsigned int + enum [[gnu::flag_enum]] syntax_option_type : unsigned int { _S_icase = 1 << 0, _S_nosubs = 1 << 1, diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index cf27cd6d521..f3cf66ffb85 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -184,6 +184,7 @@ static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int, static tree handle_hardbool_attribute (tree *, tree, tree, int, bool *); static tree handle_retain_attribute (tree *, tree, tree, int, bool *); static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *); +static tree handle_flag_enum_attribute (tree *, tree, tree, int, bool *); static tree handle_null_terminated_string_arg_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ @@ -631,6 +632,8 @@ const struct attribute_spec c_common_gnu_attributes[] = handle_fd_arg_attribute, NULL}, { "fd_arg_write", 1, 1, false, true, true, false, handle_fd_arg_attribute, NULL}, + { "flag_enum", 0, 0, false, true, false, false, + handle_flag_enum_attribute, NULL }, { "null_terminated_string_arg", 1, 1, false, true, true, false, handle_null_terminated_string_arg_attribute, NULL} }; @@ -640,6 +643,17 @@ const struct scoped_attribute_specs c_common_gnu_attribute_table = "gnu", { c_common_gnu_attributes } }; +/* Attributes also recognized in the clang:: namespace. */ +const struct attribute_spec c_common_clang_attributes[] = { + { "flag_enum", 0, 0, false, true, false, false, + handle_flag_enum_attribute, NULL } +}; + +const struct scoped_attribute_specs c_common_clang_attribute_table = +{ + "clang", { c_common_clang_attributes } +}; + /* Give the specifications for the format attributes, used by C and all descendants. @@ -5017,6 +5031,25 @@ handle_fd_arg_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Handle the "flag_enum" attribute. */ + +static tree +handle_flag_enum_attribute (tree *node, tree ARG_UNUSED(name), tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (args) + warning (OPT_Wattributes, "%qE attribute arguments ignored", name); + else if (TREE_CODE (*node) != ENUMERAL_TYPE) + warning (OPT_Wattributes, "%qE attribute ignored on non-enum", name); + else + goto ok; + + *no_add_attrs = true; + + ok: + return NULL_TREE; +} + /* Handle the "null_terminated_string_arg" attribute. */ static tree diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc index 5e4fb7f0f0a..47e0a6bfa07 100644 --- a/gcc/c-family/c-warn.cc +++ b/gcc/c-family/c-warn.cc @@ -1808,6 +1808,10 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, TREE_PURPOSE (chain)); } + /* Attribute flag_enum means bitwise combinations are OK. */ + if (lookup_attribute ("flag_enum", TYPE_ATTRIBUTES (type))) + return; + /* Warn if there are case expressions that don't correspond to enumerators. This can occur since C and C++ don't enforce type-checking of assignments to enumeration variables. diff --git a/gcc/testsuite/c-c++-common/attr-flag-enum-1.c b/gcc/testsuite/c-c++-common/attr-flag-enum-1.c new file mode 100644 index 00000000000..4eb78b1d8ee --- /dev/null +++ b/gcc/testsuite/c-c++-common/attr-flag-enum-1.c @@ -0,0 +1,37 @@ +/* { dg-additional-options -Wswitch } */ + +enum E0 { a0 = 1, b0 = 2 }; +void f0 (enum E0 e) { + switch (e) { + case !(a0|b0): /* { dg-warning "not in enumerated type" } */ + case a0|b0: /* { dg-warning "not in enumerated type" } */ + default:; + } +} + +enum __attribute ((flag_enum)) E1 { a1 = 1, b1 = 2 }; +void f1 (enum E1 e) { + switch (e) { + case !(a1|b1): /* { dg-bogus "not in enumerated type" } */ + case a1|b1: /* { dg-bogus "not in enumerated type" } */ + default:; + } +} + +enum [[gnu::flag_enum]] E2 { a2 = 1, b2 = 2 }; +void f2 (enum E2 e) { + switch (e) { + case !(a2|b2): /* { dg-bogus "not in enumerated type" } */ + case a2|b2: /* { dg-bogus "not in enumerated type" } */ + default:; + } +} + +enum [[clang::flag_enum]] E3 { a3 = 1, b3 = 2 }; +void f3 (enum E3 e) { + switch (e) { + case !(a3|b3): /* { dg-bogus "not in enumerated type" } */ + case a3|b3: /* { dg-bogus "not in enumerated type" } */ + default:; + } +}