From patchwork Wed May 25 20:03:18 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 97412 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 63505B6F8F for ; Thu, 26 May 2011 06:03:40 +1000 (EST) Received: (qmail 661 invoked by alias); 25 May 2011 20:03:34 -0000 Received: (qmail 641 invoked by uid 22791); 25 May 2011 20:03:33 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_CX, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 25 May 2011 20:03:19 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4PK3I8e029260 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 25 May 2011 16:03:19 -0400 Received: from [127.0.0.1] (ovpn-113-23.phx2.redhat.com [10.3.113.23]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p4PK3IEM007947 for ; Wed, 25 May 2011 16:03:18 -0400 Message-ID: <4DDD6086.3060802@redhat.com> Date: Wed, 25 May 2011 16:03:18 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110428 Fedora/3.1.10-1.fc14 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/44311 (scoped enum and switch) 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 The C++ standard specifies that case values are implicitly converted to the type of the switch condition, but we weren't doing that. As a result, we weren't getting the appropriate errors about converting to/from scoped enum. This patch also fixes use of constexpr conversion operators in case labels. Tested x86_64-pc-linux-gnu, applying to trunk. commit e33ad562ffd4ad6d0c705779f3f33e2a5626631c Author: Jason Merrill Date: Wed May 25 01:33:53 2011 -0400 PR c++/44311 * decl.c (case_conversion): New. (finish_case_label): Use it. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2b6a777..7fc1945 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2957,6 +2957,28 @@ pop_switch (void) free (cs); } +/* Convert a case constant VALUE in a switch to the type TYPE of the switch + condition. Note that if TYPE and VALUE are already integral we don't + really do the conversion because the language-independent + warning/optimization code will work better that way. */ + +static tree +case_conversion (tree type, tree value) +{ + if (value == NULL_TREE) + return value; + + if (cxx_dialect >= cxx0x + && (SCOPED_ENUM_P (type) + || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value)))) + { + if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type)) + type = type_promotes_to (type); + value = perform_implicit_conversion (type, value, tf_warning_or_error); + } + return cxx_constant_value (value); +} + /* Note that we've seen a definition of a case label, and complain if this is a bad place for one. */ @@ -2965,6 +2987,7 @@ finish_case_label (location_t loc, tree low_value, tree high_value) { tree cond, r; struct cp_binding_level *p; + tree type; if (processing_template_decl) { @@ -2984,13 +3007,12 @@ finish_case_label (location_t loc, tree low_value, tree high_value) if (!check_switch_goto (switch_stack->level)) return error_mark_node; - if (low_value) - low_value = cxx_constant_value (low_value); - if (high_value) - high_value = cxx_constant_value (high_value); + type = SWITCH_STMT_TYPE (switch_stack->switch_stmt); - r = c_add_case_label (loc, switch_stack->cases, cond, - SWITCH_STMT_TYPE (switch_stack->switch_stmt), + low_value = case_conversion (type, low_value); + high_value = case_conversion (type, high_value); + + r = c_add_case_label (loc, switch_stack->cases, cond, type, low_value, high_value); /* After labels, make any new cleanups in the function go into their diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C new file mode 100644 index 0000000..55cf2ad --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C @@ -0,0 +1,23 @@ +// Test for constexpr conversion in case context +// { dg-options -std=c++0x } + +enum class E { e1, e2 }; + +struct A +{ + E e; + constexpr operator E() { return e; } + constexpr A(E e): e(e) { } +}; + +E e; + +int main() +{ + switch (e) + { + case A(E::e1): + case A(E::e2): + ; + } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/enum15.C b/gcc/testsuite/g++.dg/cpp0x/enum15.C new file mode 100644 index 0000000..d653216 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/enum15.C @@ -0,0 +1,20 @@ +// PR c++/44311 +// { dg-options -std=c++0x } + +enum class A { Val0, Val1 }; + +void foo (A a, int i) +{ + switch (a) + { + case A::Val0: break; + case 1: break; // { dg-error "" } + } + + switch (i) + { + case A::Val0: break; // { dg-error "" } + case 1: break; + case 2.0: break; + } +}