From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29791 invoked by alias); 25 Nov 2019 23:32:23 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 29782 invoked by uid 89); 25 Nov 2019 23:32:22 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.7 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS autolearn=ham version=3.3.1 spammy=finishing, 2019-11-16, vector_mode_p, 20191116 X-HELO: us-smtp-1.mimecast.com Received: from us-smtp-delivery-1.mimecast.com (HELO us-smtp-1.mimecast.com) (205.139.110.120) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 25 Nov 2019 23:32:21 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1574724739; 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: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=o7S7DAwRP8y/yAyxgdNg31wTsOgatPW2umtP1mzGJmk=; b=fKmCyNMP0EtAZYNP3JhS9lUP4bXoo5Q6c3hg+VTvPQkHj4kanAU2ztMZGlGpV6DabjDvOd ioPiEzZt5tf0bAJEZtFZsYmELfXctGfjOGDKFXy38ge80uIuDRG5ez8rQgsQ3k3lkS21oE WLTtdjbI/q+Zlzwwqg6cGf/0MAEDzBk= 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-118-Y4o6qqQANQuQGpapVfupyQ-1; Mon, 25 Nov 2019 18:32:16 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5CB33107ACE3; Mon, 25 Nov 2019 23:32:15 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-117-59.ams2.redhat.com [10.36.117.59]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DF4AA60C85; Mon, 25 Nov 2019 23:32:11 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id xAPNW9rh020455; Tue, 26 Nov 2019 00:32:09 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id xAPNW7rq020454; Tue, 26 Nov 2019 00:32:07 +0100 Date: Mon, 25 Nov 2019 23:42:00 -0000 From: Jakub Jelinek To: Jason Merrill Cc: Sam van Kampen , Martin Sebor , gcc-patches List Subject: [C++ PATCH] Fix up is too small to hold all values of enum warning (PR c++/61414) Message-ID: <20191125233207.GE10088@tucnak> Reply-To: Jakub Jelinek References: <20171016111842.zmajbbopy2wkrzjz@segfault.party> <20171016123727.anxuxjzna3be3zyy@segfault.party> <35949158-4c52-207d-d962-adc988fd5310@gmail.com> <20171018135549.lkgo3xt6t7jacnqh@segfault.party> <20171018191516.h5ewt3z6wsvgauvs@segfault.party> <20191125143932.GA10088@tucnak> <20191125144623.GA2416@tucnak> MIME-Version: 1.0 In-Reply-To: <20191125144623.GA2416@tucnak> User-Agent: Mutt/1.11.3 (2019-02-01) X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Content-Disposition: inline X-IsSubscribed: yes X-SW-Source: 2019-11/txt/msg02366.txt.bz2 Hi! On Mon, Nov 25, 2019 at 03:46:23PM +0100, Jakub Jelinek wrote: > On Mon, Nov 25, 2019 at 03:39:32PM +0100, Jakub Jelinek wrote: > > I guess the question is, shall we store the minimum precision needed > > somewhere by finish_enum_value_list (perhaps only bother if the precisi= on > > of the underlying type is not the same) or compute it each time again > > (which would mean for each bitfield of enum type walk the list of all t= he > > enum values)? And, if we should store it somewhere, any preferences wh= ere? > > These days C++ FE has TYPE_LANG_SPECIFIC just for classes, so options a= re > > just use the class TYPE_LANG_SPECIFIC and just stick the min/max values= in > > some trees in there, restore having different lang specific variants and > > store just minimum precision in there, add hash map from tree (hashed u= sing > > TYPE_UID) to precision, something else? >=20 > Or yet another possibility, only compute it on demand and use a hash map = as > cache. Here is that option implemented, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2019-11-26 Jakub Jelinek PR c++/61414 * c-attribs.c (handle_mode_attribute): Add mode attribute to ENUMERAL_TYPEs. * class.c (enum_to_min_precision): New hash_map. (enum_min_precision): New function. (check_bitfield_decl): Use it. * g++.dg/cpp0x/enum23.C: Remove xfail. * g++.dg/cpp0x/enum28.C: New test. --- gcc/c-family/c-attribs.c.jj 2019-11-23 11:05:50.813492164 +0100 +++ gcc/c-family/c-attribs.c 2019-11-25 16:47:35.317750531 +0100 @@ -1866,6 +1866,7 @@ handle_mode_attribute (tree *node, tree typefm =3D make_signed_type (TYPE_PRECISION (typefm)); TREE_TYPE (typefm) =3D type; } + *no_add_attrs =3D false; } else if (VECTOR_MODE_P (mode) ? TREE_CODE (type) !=3D TREE_CODE (TREE_TYPE (typefm)) --- gcc/cp/class.c.jj 2019-11-16 18:13:42.844606979 +0100 +++ gcc/cp/class.c 2019-11-25 16:42:15.050633229 +0100 @@ -3265,6 +3265,60 @@ add_implicitly_declared_members (tree t, } } =20 +/* Cache of enum_min_precision values. */ +static GTY((deletable)) hash_map *enum_to_min_precision; + +/* Return the minimum precision of a bit-field needed to store all + enumerators of ENUMERAL_TYPE TYPE. */ + +static int +enum_min_precision (tree type) +{ + type =3D TYPE_MAIN_VARIANT (type); + /* For unscoped enums without fixed underlying type and without mode + attribute we can just use precision of the underlying type. */ + if (UNSCOPED_ENUM_P (type) + && !ENUM_FIXED_UNDERLYING_TYPE_P (type) + && !lookup_attribute ("mode", TYPE_ATTRIBUTES (type))) + return TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type)); + + if (enum_to_min_precision =3D=3D NULL) + enum_to_min_precision =3D hash_map::create_ggc (37); + + bool existed; + int prec =3D enum_to_min_precision->get_or_insert (type, &existed); + if (existed) + return prec; + + tree minnode, maxnode; + if (TYPE_VALUES (type)) + { + minnode =3D maxnode =3D NULL_TREE; + for (tree values =3D TYPE_VALUES (type); + values; values =3D TREE_CHAIN (values)) + { + tree decl =3D TREE_VALUE (values); + tree value =3D DECL_INITIAL (decl); + if (value =3D=3D error_mark_node) + value =3D integer_zero_node; + if (!minnode) + minnode =3D maxnode =3D value; + else if (tree_int_cst_lt (maxnode, value)) + maxnode =3D value; + else if (tree_int_cst_lt (value, minnode)) + minnode =3D value; + } + } + else + minnode =3D maxnode =3D integer_zero_node; + + signop sgn =3D tree_int_cst_sgn (minnode) >=3D 0 ? UNSIGNED : SIGNED; + int lowprec =3D tree_int_cst_min_precision (minnode, sgn); + int highprec =3D tree_int_cst_min_precision (maxnode, sgn); + prec =3D MAX (lowprec, highprec); + return prec; +} + /* FIELD is a bit-field. We are finishing the processing for its enclosing type. Issue any appropriate messages and set appropriate flags. Returns false if an error has been diagnosed. */ @@ -3326,7 +3380,7 @@ check_bitfield_decl (tree field) "width of %qD exceeds its type", field); else if (TREE_CODE (type) =3D=3D ENUMERAL_TYPE) { - int prec =3D TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type)); + int prec =3D enum_min_precision (type); if (compare_tree_int (w, prec) < 0) warning_at (DECL_SOURCE_LOCATION (field), 0, "%qD is too small to hold all values of %q#T", --- gcc/testsuite/g++.dg/cpp0x/enum23.C.jj 2013-02-16 09:31:06.400506406 +0= 100 +++ gcc/testsuite/g++.dg/cpp0x/enum23.C 2019-11-25 16:51:19.532332223 +0100 @@ -5,5 +5,5 @@ enum class MyEnum { A =3D 1 }; =20 struct MyClass { - MyEnum Field1 : 3; // { dg-bogus "warning: 'MyClass::Field1' is too smal= l" "" { xfail *-*-* } } + MyEnum Field1 : 3; // { dg-bogus "warning: 'MyClass::Field1' is too smal= l" } }; --- gcc/testsuite/g++.dg/cpp0x/enum38.C.jj 2019-11-25 16:50:56.323686060 +0= 100 +++ gcc/testsuite/g++.dg/cpp0x/enum38.C 2019-11-25 16:52:28.466281278 +0100 @@ -0,0 +1,25 @@ +// PR c++/61414 +// { dg-do compile { target c++11 } } + +enum C { C0 =3D -4, C1 =3D 3 }; +enum D { D0 =3D 0, D1 =3D 15 }; +enum class E { E0 =3D -4, E1 =3D 3 }; +enum F : unsigned { F0 =3D 0, F1 =3D 15 }; +enum __attribute__((__mode__ (__QI__))) G { G0 =3D -4, G1 =3D 3 }; +enum __attribute__((__mode__ (__HI__))) H { H0 =3D 0, H1 =3D 15 }; + +struct S +{ + C a : 2; // { dg-warning "'S::a' is too small to hold all values of 'enu= m C'" } + C b : 3; // { dg-bogus "'S::b' is too small to hold all values of 'enum = C'" } + D c : 3; // { dg-warning "'S::c' is too small to hold all values of 'enu= m D'" } + D d : 4; // { dg-bogus "'S::d' is too small to hold all values of 'enum = D'" } + E e : 2; // { dg-warning "'S::e' is too small to hold all values of 'enu= m class E'" } + E f : 3; // { dg-bogus "'S::f' is too small to hold all values of 'enum = class E'" } + F g : 3; // { dg-warning "'S::g' is too small to hold all values of 'enu= m F'" } + F h : 4; // { dg-bogus "'S::h' is too small to hold all values of 'enum = F'" } + G i : 2; // { dg-warning "'S::i' is too small to hold all values of 'enu= m G'" } + G j : 3; // { dg-bogus "'S::j' is too small to hold all values of 'enum = G'" } + H k : 3; // { dg-warning "'S::k' is too small to hold all values of 'enu= m H'" } + H l : 4; // { dg-bogus "'S::l' is too small to hold all values of 'enum = H'" } +}; Jakub