From patchwork Wed May 18 14:48:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 54167 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 15BF0383941F for ; Wed, 18 May 2022 14:49:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 15BF0383941F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1652885354; bh=GePo3AmqVhiG5T7uM16g5m2R1L8y9s9wrX3oqHEWL38=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=qkQibHkzN/3ZG+4fdcSltfhlRfCcQofMfPlWIzCZ6GxRcBOurQK2Qndo6/kRdGGfE y33yyzwyicwj9hLuCRh5+ZRt8nYGNm5MF4juroFsIEe/IuwtmuBmN4pJ5nH4l4XHc6 +svo/uKK9P/YtLhUEF311q6D6od0NFR6ZSit8Eow= 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 ESMTPS id 7F1583857401 for ; Wed, 18 May 2022 14:48:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7F1583857401 Received: from mail-qt1-f199.google.com (mail-qt1-f199.google.com [209.85.160.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-1-pZ1tTYsBPkWTMSVXuZAnXQ-1; Wed, 18 May 2022 10:48:42 -0400 X-MC-Unique: pZ1tTYsBPkWTMSVXuZAnXQ-1 Received: by mail-qt1-f199.google.com with SMTP id ay35-20020a05622a22a300b002f3fdcb1bb1so1832342qtb.8 for ; Wed, 18 May 2022 07:48:41 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=GePo3AmqVhiG5T7uM16g5m2R1L8y9s9wrX3oqHEWL38=; b=YjezMQM0hR/+Rnfx/gP1skCZm52kIpIii3cJHhzQhkt0KkhkxIWJnPl70hrqK3qsAH HwaSgoaCZ4d2ZnU9+5L8xLNwo+KDfSld21kAP5mVTHpL9Rlg/5onvj71Cf6i5TW4lXWF XvYh3k6TFMAIZY/tEWRfutOgXB+58k1ttXoVMglPDWZLGr9ZqjTLTnDBJ6kViegiIxUv 2UDWVuaW6DBgDU7jmfPR3kzI5iCv5ITr5Et4MOOG6bwefYxHDh1vWjy1Jn03zT/kOV66 woy0MPbyS+2vFpIOydqDrfXLz28uX32J8qVzEgZwJggVML3M1x4wpFLt2UYPE38WYrEV daKg== X-Gm-Message-State: AOAM5319v5GHDCR1jsO8seM98Kx3Qrv79umb8x2Qsvmo3R0wgxmAGku+ /W6I0uFWWLJSNHrjC+qxTHSoN5kObZs1jKJTPuI38umx6laRWPTOOi9NksI3CLHoUm7Ai+HShz7 M42BxhP0Lvdp9BsuO3Q== X-Received: by 2002:ac8:5988:0:b0:2f3:decb:6b6b with SMTP id e8-20020ac85988000000b002f3decb6b6bmr53405qte.289.1652885320921; Wed, 18 May 2022 07:48:40 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx+TSM+4mA6gG6QgJ0MnHriXPBL5vBuW0ewcGiBNLFTbuUMgxpiTRWH2dKa6phMSloDJ4Do3A== X-Received: by 2002:ac8:5988:0:b0:2f3:decb:6b6b with SMTP id e8-20020ac85988000000b002f3decb6b6bmr53379qte.289.1652885320515; Wed, 18 May 2022 07:48:40 -0700 (PDT) Received: from redhat.com ([2601:184:4780:4310::e811]) by smtp.gmail.com with ESMTPSA id a22-20020a376616000000b0069fe1dfbeffsm1650928qkc.92.2022.05.18.07.48.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 07:48:39 -0700 (PDT) Date: Wed, 18 May 2022 10:48:38 -0400 To: Pedro Alves Subject: [PATCH v2] c: Implement new -Wenum-int-mismatch warning [PR105131] Message-ID: References: <20220517235629.473087-1-polacek@redhat.com> MIME-Version: 1.0 In-Reply-To: User-Agent: Mutt/2.2.1 (2022-02-19) X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-12.8 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, 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-Patchwork-Original-From: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Cc: GCC Patches , Joseph Myers Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" On Wed, May 18, 2022 at 11:14:25AM +0100, Pedro Alves wrote: > On 2022-05-18 00:56, Marek Polacek via Gcc-patches wrote: > > > +In C, an enumerated type is compatible with @code{char}, a signed > > +integer type, or an unsigned integer type. However, since the choice > > +of the underlying type of an enumerated type is implementation-defined, > > +such mismatches may cause portability issues. In C++, such mismatches > > +are an error. In C, this warning is enabled by @option{-Wall}. > > Should it also be enabled by -Wc++-compat? Yes, that's a good idea. Fixed here: Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- In C, an enumerated type is compatible with char, a signed integer type, or an unsigned integer type (6.7.2.2/5). Therefore this code compiles: enum E { l = -1, z = 0, g = 1 }; int foo(void); enum E foo(void) { return z; } if the underlying type of 'enum E' is 'int' (if not, we emit an error). This is different for typedefs, where C11 permits typedefs to be redeclared to the same type, but not to compatible types. In C++, the code above is invalid. It seems desirable to emit a warning in the C case, because it is probably a mistake and definitely a portability error, given that the choice of the underlying type is implementation-defined. To that end, this patch implements a new -Wenum-int-mismatch warning. Conveniently, we already have comptypes_check_enum_int to detect such mismatches. This warning is enabled by either -Wall or -Wc++-compat. PR c/105131 gcc/c-family/ChangeLog: * c.opt (Wenum-int-mismatch): New. gcc/c/ChangeLog: * c-decl.cc (diagnose_mismatched_decls): Warn about enum/integer type mismatches. * c-tree.h (comptypes_check_enum_int): Declare. * c-typeck.cc (comptypes): No longer static. gcc/ChangeLog: * doc/invoke.texi: Document -Wenum-int-mismatch. gcc/testsuite/ChangeLog: * gcc.dg/Wenum-int-mismatch-1.c: New test. * gcc.dg/Wenum-int-mismatch-2.c: New test. * gcc.dg/Wenum-int-mismatch-3.c: New test. --- gcc/c-family/c.opt | 4 +++ gcc/c/c-decl.cc | 13 ++++++-- gcc/c/c-tree.h | 1 + gcc/c/c-typeck.cc | 2 +- gcc/doc/invoke.texi | 21 +++++++++++++ gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c | 35 +++++++++++++++++++++ gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c | 35 +++++++++++++++++++++ gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c | 35 +++++++++++++++++++++ 8 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c base-commit: 60fdce11dc9e5ddf671b07a3fc6ed70476860b22 diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 035b1de0d84..41a20bc625e 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -638,6 +638,10 @@ Wenum-conversion C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C ObjC,Wextra) Warn about implicit conversion of enum types. +Wenum-int-mismatch +C ObjC Var(warn_enum_int_mismatch) Warning LangEnabledBy(C ObjC,Wall || Wc++-compat) +Warn about enum/integer type mismatches. + Werror C ObjC C++ ObjC++ ; Documented in common.opt diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 83655548fc4..5266a61b859 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -1993,9 +1993,12 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, bool pedwarned = false; bool warned = false; + bool enum_and_int_p = false; auto_diagnostic_group d; - if (!comptypes (oldtype, newtype)) + int comptypes_result = comptypes_check_enum_int (oldtype, newtype, + &enum_and_int_p); + if (!comptypes_result) { if (TREE_CODE (olddecl) == FUNCTION_DECL && fndecl_built_in_p (olddecl, BUILT_IN_NORMAL) @@ -2137,6 +2140,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, return false; } } + /* Warn about enum/integer type mismatches. They are compatible types + (C2X 6.7.2.2/5), but may pose portability problems. */ + else if (enum_and_int_p && TREE_CODE (newdecl) != TYPE_DECL) + warned = warning_at (DECL_SOURCE_LOCATION (newdecl), + OPT_Wenum_int_mismatch, + "conflicting types for %q+D due to enum/integer " + "mismatch; have %qT", newdecl, newtype); /* Redeclaration of a type is a constraint violation (6.7.2.3p1), but silently ignore the redeclaration if either is in a system @@ -2146,7 +2156,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (TREE_CODE (newdecl) == TYPE_DECL) { bool types_different = false; - int comptypes_result; comptypes_result = comptypes_check_different_types (oldtype, newtype, &types_different); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index c70f0ba5ab6..2bcb9662620 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -685,6 +685,7 @@ extern tree require_complete_type (location_t, tree); extern bool same_translation_unit_p (const_tree, const_tree); extern int comptypes (tree, tree); extern int comptypes_check_different_types (tree, tree, bool *); +extern int comptypes_check_enum_int (tree, tree, bool *); extern bool c_vla_type_p (const_tree); extern bool c_mark_addressable (tree, bool = false); extern void c_incomplete_type_error (location_t, const_tree, const_tree); diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index bcfe08b82bc..4f3611f1b89 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -1055,7 +1055,7 @@ comptypes (tree type1, tree type2) /* Like comptypes, but if it returns non-zero because enum and int are compatible, it sets *ENUM_AND_INT_P to true. */ -static int +int comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p) { const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index e8e6d4e039b..98a543ae06f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -349,6 +349,7 @@ Objective-C and Objective-C++ Dialects}. -Wno-div-by-zero -Wdouble-promotion @gol -Wduplicated-branches -Wduplicated-cond @gol -Wempty-body -Wno-endif-labels -Wenum-compare -Wenum-conversion @gol +-Wenum-int-mismatch @gol -Werror -Werror=* -Wexpansion-to-defined -Wfatal-errors @gol -Wfloat-conversion -Wfloat-equal -Wformat -Wformat=2 @gol -Wno-format-contains-nul -Wno-format-extra-args @gol @@ -5759,6 +5760,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}. -Wdangling-pointer=2 @gol -Wduplicate-decl-specifier @r{(C and Objective-C only)} @gol -Wenum-compare @r{(in C/ObjC; this is on by default in C++)} @gol +-Wenum-int-mismatch @r{(C and Objective-C only)} @gol -Wformat @gol -Wformat-overflow @gol -Wformat-truncation @gol @@ -8735,6 +8737,25 @@ Warn when a value of enumerated type is implicitly converted to a different enumerated type. This warning is enabled by @option{-Wextra} in C@. +@item -Wenum-int-mismatch @r{(C and Objective-C only)} +@opindex Wenum-int-mismatch +@opindex Wno-enum-int-mismatch +Warn about mismatches between an enumerated type and an integer type in +declarations. For example: + +@smallexample +enum E @{ l = -1, z = 0, g = 1 @}; +int foo(void); +enum E foo(void); +@end smallexample + +In C, an enumerated type is compatible with @code{char}, a signed +integer type, or an unsigned integer type. However, since the choice +of the underlying type of an enumerated type is implementation-defined, +such mismatches may cause portability issues. In C++, such mismatches +are an error. In C, this warning is enabled by @option{-Wall} and +@option{-Wc++-compat}. + @item -Wjump-misses-init @r{(C, Objective-C only)} @opindex Wjump-misses-init @opindex Wno-jump-misses-init diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c new file mode 100644 index 00000000000..f71a308bc19 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c @@ -0,0 +1,35 @@ +/* PR c/105131 */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +enum E { l = -1, z = 0, g = 1 }; + +int foo(void); /* { dg-message "previous declaration" } */ +enum E foo(void) { return z; } /* { dg-warning "conflicting types" } */ + +void bar(int); /* { dg-message "previous declaration" } */ +void bar(enum E); /* { dg-warning "conflicting types" } */ + +extern int arr[10]; /* { dg-message "previous declaration" } */ +extern enum E arr[10]; /* { dg-warning "conflicting types" } */ + +extern int i; /* { dg-message "previous declaration" } */ +extern enum E i; /* { dg-warning "conflicting types" } */ + +extern int *p; /* { dg-message "previous declaration" } */ +extern enum E *p; /* { dg-warning "conflicting types" } */ + +enum E foo2(void) { return z; } /* { dg-message "previous definition" } */ +int foo2(void); /* { dg-warning "conflicting types" } */ + +void bar2(enum E); /* { dg-message "previous declaration" } */ +void bar2(int); /* { dg-warning "conflicting types" } */ + +extern enum E arr2[10]; /* { dg-message "previous declaration" } */ +extern int arr2[10]; /* { dg-warning "conflicting types" } */ + +extern enum E i2; /* { dg-message "previous declaration" } */ +extern int i2; /* { dg-warning "conflicting types" } */ + +extern enum E *p2; /* { dg-message "previous declaration" } */ +extern int *p2; /* { dg-warning "conflicting types" } */ diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c new file mode 100644 index 00000000000..7296b703672 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c @@ -0,0 +1,35 @@ +/* PR c/105131 */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +enum E { l = 0, z, g }; + +unsigned int foo(void); /* { dg-message "previous declaration" } */ +enum E foo(void) { return z; } /* { dg-warning "conflicting types" } */ + +void bar(unsigned int); /* { dg-message "previous declaration" } */ +void bar(enum E); /* { dg-warning "conflicting types" } */ + +extern enum E arr[10]; /* { dg-message "previous declaration" } */ +extern unsigned int arr[10]; /* { dg-warning "conflicting types" } */ + +extern unsigned int i; /* { dg-message "previous declaration" } */ +extern enum E i; /* { dg-warning "conflicting types" } */ + +extern unsigned int *p; /* { dg-message "previous declaration" } */ +extern enum E *p; /* { dg-warning "conflicting types" } */ + +enum E foo2(void) { return z; } /* { dg-message "previous definition" } */ +unsigned int foo2(void); /* { dg-warning "conflicting types" } */ + +void bar2(enum E); /* { dg-message "previous declaration" } */ +void bar2(unsigned int); /* { dg-warning "conflicting types" } */ + +extern unsigned int arr2[10]; /* { dg-message "previous declaration" } */ +extern enum E arr2[10]; /* { dg-warning "conflicting types" } */ + +extern enum E i2; /* { dg-message "previous declaration" } */ +extern unsigned int i2; /* { dg-warning "conflicting types" } */ + +extern enum E *p2; /* { dg-message "previous declaration" } */ +extern unsigned int *p2; /* { dg-warning "conflicting types" } */ diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c new file mode 100644 index 00000000000..8773f01869c --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c @@ -0,0 +1,35 @@ +/* PR c/105131 */ +/* { dg-do compile } */ +/* { dg-options "-Wc++-compat" } */ + +enum E { l = -1, z = 0, g = 1 }; + +int foo(void); /* { dg-message "previous declaration" } */ +enum E foo(void) { return z; } /* { dg-warning "conflicting types" } */ + +void bar(int); /* { dg-message "previous declaration" } */ +void bar(enum E); /* { dg-warning "conflicting types" } */ + +extern int arr[10]; /* { dg-message "previous declaration" } */ +extern enum E arr[10]; /* { dg-warning "conflicting types" } */ + +extern int i; /* { dg-message "previous declaration" } */ +extern enum E i; /* { dg-warning "conflicting types" } */ + +extern int *p; /* { dg-message "previous declaration" } */ +extern enum E *p; /* { dg-warning "conflicting types" } */ + +enum E foo2(void) { return z; } /* { dg-message "previous definition" } */ +int foo2(void); /* { dg-warning "conflicting types" } */ + +void bar2(enum E); /* { dg-message "previous declaration" } */ +void bar2(int); /* { dg-warning "conflicting types" } */ + +extern enum E arr2[10]; /* { dg-message "previous declaration" } */ +extern int arr2[10]; /* { dg-warning "conflicting types" } */ + +extern enum E i2; /* { dg-message "previous declaration" } */ +extern int i2; /* { dg-warning "conflicting types" } */ + +extern enum E *p2; /* { dg-message "previous declaration" } */ +extern int *p2; /* { dg-warning "conflicting types" } */