From patchwork Tue Oct 8 22:14:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1173528 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-510498-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="YFWVm4A1"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46ns8K0p9fz9sDQ for ; Wed, 9 Oct 2019 09:14:22 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=gYhF2UQyp+/KRa8xThRghBnq6KGPmouSla4z1TUMpfqSJ7MKBHlSl OHyBt0VaDFWzAN7fSyCLzacvzV8Vy4jIQKgADAJPT/QplKqufv0rNCUTapGkSFpF khrFQknOgIUObJ7srECF7gg6LDLb5NCIxI3AbEqAOAbMZdwJ+yG8a8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=yMII2hEIDHijOtaBcaO9kW9lBr8=; b=YFWVm4A1FnP/t0zQGr/4 +gSiAXYUUetD5hgir56kNruY5cLDEolb7HKeEII+US0AR38w08SGRs6A21D3wbd0 ggbVZxcXluGADMVg3uAjVfsjOI7aTM2pYPiJYkxIkB3f3R4SPTpABsFZaZY6xSNr 8KCW1VTzy4Gh7oJbBxTChzU= Received: (qmail 53658 invoked by alias); 8 Oct 2019 22:14:15 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 53644 invoked by uid 89); 8 Oct 2019 22:14:14 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 08 Oct 2019 22:14:13 +0000 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 32357806A53 for ; Tue, 8 Oct 2019 22:14:12 +0000 (UTC) Received: from redhat.com (ovpn-121-76.rdu2.redhat.com [10.10.121.76]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BE25219C69; Tue, 8 Oct 2019 22:14:11 +0000 (UTC) Date: Tue, 8 Oct 2019 18:14:09 -0400 From: Marek Polacek To: GCC Patches , Jason Merrill Subject: C++ PATCH for c++/92032 - DR 1601: Promotion of enum with fixed underlying type Message-ID: <20191008221409.GA2949@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.12.1 (2019-06-15) I've been messing with compare_ics recently and noticed that we don't implement CWG 1601, which should be fairly easy. The motivating example is enum E : char { e }; void f(char); void f(int); void g() { f(e); } where the call to f was ambiguous but we should choose f(char). Currently we give f(int) cr_promotion in standard_conversion, while f(char) remains cr_std, which is worse than cr_promotion. So I thought I'd give it cr_promotion also and then add a tiebreaker to compare_ics. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2019-10-08 Marek Polacek PR c++/92032 - DR 1601: Promotion of enum with fixed underlying type. * call.c (standard_conversion): When converting an enumeration with a fixed underlying type to the underlying type, give it the cr_promotion rank. (compare_ics): Implement a tiebreaker as per CWG 1601. * g++.dg/cpp0x/scoped_enum10.C: New test. * g++.dg/cpp0x/scoped_enum11.C: New test. diff --git gcc/cp/call.c gcc/cp/call.c index 6c9acac4614..10172855d4d 100644 --- gcc/cp/call.c +++ gcc/cp/call.c @@ -1484,8 +1484,18 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, conv = build_conv (ck_std, to, conv); - /* Give this a better rank if it's a promotion. */ - if (same_type_p (to, type_promotes_to (from)) + tree underlying_type = NULL_TREE; + if (TREE_CODE (from) == ENUMERAL_TYPE + && ENUM_FIXED_UNDERLYING_TYPE_P (from)) + underlying_type = ENUM_UNDERLYING_TYPE (from); + + /* Give this a better rank if it's a promotion. + + To handle CWG 1601, also bump the rank if we are converting + an enumeration with a fixed underlying type to the underlying + type. */ + if ((same_type_p (to, type_promotes_to (from)) + || (underlying_type && same_type_p (to, underlying_type))) && next_conversion (conv)->rank <= cr_promotion) conv->rank = cr_promotion; } @@ -10506,6 +10516,31 @@ compare_ics (conversion *ics1, conversion *ics2) } } + /* [over.ics.rank] + + Per CWG 1601: + -- A conversion that promotes an enumeration whose underlying type + is fixed to its underlying type is better than one that promotes to + the promoted underlying type, if the two are different. */ + if (ics1->rank == cr_promotion + && ics2->rank == cr_promotion + && UNSCOPED_ENUM_P (from_type1) + && ENUM_FIXED_UNDERLYING_TYPE_P (from_type1) + && same_type_p (from_type1, from_type2)) + { + tree utype = ENUM_UNDERLYING_TYPE (from_type1); + tree prom = type_promotes_to (from_type1); + if (!same_type_p (utype, prom)) + { + if (same_type_p (to_type1, utype) + && same_type_p (to_type2, prom)) + return 1; + else if (same_type_p (to_type2, utype) + && same_type_p (to_type1, prom)) + return -1; + } + } + /* Neither conversion sequence is better than the other. */ return 0; } diff --git gcc/testsuite/g++.dg/cpp0x/scoped_enum10.C gcc/testsuite/g++.dg/cpp0x/scoped_enum10.C new file mode 100644 index 00000000000..b588581cd3e --- /dev/null +++ gcc/testsuite/g++.dg/cpp0x/scoped_enum10.C @@ -0,0 +1,37 @@ +// PR c++/92032 - DR 1601: Promotion of enumeration with fixed underlying type. +// { dg-do compile { target c++11 } } + +enum E : char { e }; +enum F : int { f }; +enum G : long { g }; +enum H : unsigned { h }; + +int f1(char); +void f1(int); + +void f2(int); +int f2(char); + +int f3(int); +void f3(short); + +int f4(long); +void f4(int); + +void f5(unsigned); +int f5(int); + +int f6(unsigned); +void f6(int); + +void +test () +{ + int r = 0; + r += f1 (e); + r += f2 (e); + r += f3 (f); + r += f4 (g); + r += f5 (f); + r += f6 (h); +} diff --git gcc/testsuite/g++.dg/cpp0x/scoped_enum11.C gcc/testsuite/g++.dg/cpp0x/scoped_enum11.C new file mode 100644 index 00000000000..e6dcfbac9d8 --- /dev/null +++ gcc/testsuite/g++.dg/cpp0x/scoped_enum11.C @@ -0,0 +1,35 @@ +// PR c++/92032 - DR 1601: Promotion of enumeration with fixed underlying type. +// { dg-do compile { target c++11 } } + +enum E1 : long { e1 }; +enum E2 : short { e2 }; + +int f1(short); +void f1(int); + +void f2(int); +int f2(short); + +void f3(int); +int f3(long); + +int f4(short); +void f4(long); + +int f5(int); +void f5(long); + +int f6(unsigned int); // { dg-message "candidate" } +void f6(long); // { dg-message "candidate" } + +void +fn () +{ + int r = 0; + r += f1 (e2); + r += f2 (e2); + r += f3 (e1); + r += f4 (e2); + r += f5 (e2); + r += f6 (e2); // { dg-error "ambiguous" } +}