From patchwork Tue Oct 29 10:07:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 99753 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 69E6F3858404 for ; Tue, 29 Oct 2024 10:07:52 +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.129.124]) by sourceware.org (Postfix) with ESMTP id E83273858D34 for ; Tue, 29 Oct 2024 10:07:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E83273858D34 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 E83273858D34 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730196438; cv=none; b=N8vSxWYMdh/7mIVR99tAR96YSuaivQMnU8jnx/iVlT2KVCHK2VrcTGEpa/tekoQDxxHcIgbq4JS8SW80o/eROPvo+jtq0nHjo80tHn5AZfyMY8rjKUr1Q2m8Swc9pKRJgfjK3wR6faE0V+u2zwVb+C9QT5ADyO2qjUMmKe6uO6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730196438; c=relaxed/simple; bh=0ZGokKBtPcXWVDAkkCCTAE+ppFk10LWMvzh8UhOmU4U=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=X06XTKLYu+lIYcrdM0bGkgtXKnrtv4LV22/ZceXtbhPnB92CbdCWL30rCFszmorRTR+GgKVJqO+FzBXYF5qbCsY+W37+AAxgb2m9dbnSZHa0OBhs5ZzoVCnwpSDSh/p95gZ/HsP3IbYM9EqPzpGP8FhuAZWrsqD3xpD7qUID8do= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730196434; 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; bh=qWqYrRzLmzNlfDP93iW3xrnKrumgNl5QF3yW5vP39Ak=; b=I1sx9zAM8+/ZgZLz1gJN1dnpZr4yMyPO2ydV+43TqodWbV6JO6tKdFDWcIsNta5kIDFNo6 e0gMJ3TARH56uOa5kTj/GV/mvEF5Y+4IAAr5YDmtv2vq6xLbjtfTJ3FVUOyXO6CVyIfJoR 3mo7lThAV+xSKBt1TpHo9NFQzNbr0uU= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-615-rypjoLfaNlGpyGXqCJAw0g-1; Tue, 29 Oct 2024 06:07:13 -0400 X-MC-Unique: rypjoLfaNlGpyGXqCJAw0g-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5FB001956057 for ; Tue, 29 Oct 2024 10:07:12 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.16]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C038A300018D; Tue, 29 Oct 2024 10:07:10 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 49TA77Hh3085305 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Tue, 29 Oct 2024 11:07:07 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 49TA77Ll3085304; Tue, 29 Oct 2024 11:07:07 +0100 Date: Tue, 29 Oct 2024 11:07:07 +0100 From: Jakub Jelinek To: "Joseph S. Myers" Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c: Add C2Y N3370 - Case range expressions support [PR117021] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP 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: , Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org Hi! The following patch adds the C2Y N3370 paper support. We had the case ranges as a GNU extension for decades, so this patch simply: 1) adds different diagnostics when it is used in C (depending on flag_isoc2y and pedantic and warn_c23_c2y_compat) 2) emits a pedwarn in C if in a range conversion changes the value of the low or high bounds and in that case doesn't emit -Woverflow and similar warnings anymore if the pedwarn has been diagnosed 3) changes the handling of empty ranges both in C and C++; previously we just warned but let the values be still looked up in the splay tree/entered into it (and let only gimplification throw away those empty cases), so e.g. case -6 ... -8: break; case -6: break; complained about duplicate case label. But that actually isn't duplicate case label, case -6 ... -8: stands for nothing at all and that is how it is treated later on (thrown away) Older version has been bootstrapped/regtested on x86_64-linux and i686-linux successfully (without the last hunk in c_add_case_label and some of testcase additions), ok for trunk if even this updated patch passes bootstrap/regtest? 2024-10-29 Jakub Jelinek PR c/117021 gcc/c-family/ * c-common.cc (c_add_case_label): Emit different diagnostics for C on case ranges. Diagnose for C using pedwarn conversions of range expressions changing value and don't emit further conversion diagnostics if the pedwarn has been diagnosed. For empty ranges bail out after emitting warning, don't add anything into splay trees nor add a CASE_LABEL_EXPR. gcc/testsuite/ * gcc.dg/switch-6.c: Expect different diagnostics. Add -std=gnu23 to dg-options. * gcc.dg/switch-7.c: Expect different diagnostics. Add -std=c23 to dg-options. * gcc.dg/gnu23-switch-1.c: New test. * gcc.dg/gnu23-switch-2.c: New test. * gcc.dg/c23-switch-1.c: New test. * gcc.dg/c2y-switch-1.c: New test. * gcc.dg/c2y-switch-2.c: New test. * gcc.dg/c2y-switch-3.c: New test. Jakub --- gcc/c-family/c-common.cc.jj 2024-10-29 09:06:12.529014618 +0100 +++ gcc/c-family/c-common.cc 2024-10-29 10:48:36.477959663 +0100 @@ -5186,13 +5186,41 @@ c_add_case_label (location_t loc, splay_ /* Case ranges are a GNU extension. */ if (high_value) - pedwarn (loc, OPT_Wpedantic, - "range expressions in switch statements are non-standard"); + { + if (c_dialect_cxx ()) + pedwarn (loc, OPT_Wpedantic, + "range expressions in switch statements are non-standard"); + else if (warn_c23_c2y_compat > 0) + { + if (pedantic && !flag_isoc2y) + pedwarn (loc, OPT_Wc23_c2y_compat, + "ISO C does not support range expressions in switch " + "statements before C2Y"); + else + warning_at (loc, OPT_Wc23_c2y_compat, + "ISO C does not support range expressions in switch " + "statements before C2Y"); + } + else if (warn_c23_c2y_compat && pedantic && !flag_isoc2y) + pedwarn (loc, OPT_Wpedantic, + "ISO C does not support range expressions in switch " + "statements before C2Y"); + } type = TREE_TYPE (cond); if (low_value) { low_value = check_case_value (loc, low_value); + tree tem = NULL_TREE; + if (high_value + && !c_dialect_cxx () + && low_value != error_mark_node + && !int_fits_type_p (low_value, type) + && pedwarn (loc, OPT_Wpedantic, + "conversion of %qE to %qT in range expression changes " + "value to %qE", low_value, type, + (tem = fold_convert (type, low_value)))) + low_value = tem; low_value = convert_and_check (loc, type, low_value); low_value = fold (low_value); if (low_value == error_mark_node) @@ -5201,6 +5229,15 @@ c_add_case_label (location_t loc, splay_ if (high_value) { high_value = check_case_value (loc, high_value); + tree tem = NULL_TREE; + if (!c_dialect_cxx () + && high_value != error_mark_node + && !int_fits_type_p (high_value, type) + && pedwarn (loc, OPT_Wpedantic, + "conversion of %qE to %qT in range expression changes " + "value to %qE", high_value, type, + (tem = fold_convert (type, high_value)))) + high_value = tem; high_value = convert_and_check (loc, type, high_value); high_value = fold (high_value); if (high_value == error_mark_node) @@ -5215,7 +5252,10 @@ c_add_case_label (location_t loc, splay_ if (tree_int_cst_equal (low_value, high_value)) high_value = NULL_TREE; else if (!tree_int_cst_lt (low_value, high_value)) - warning_at (loc, 0, "empty range specified"); + { + warning_at (loc, 0, "empty range specified"); + goto error_out; + } } /* Look up the LOW_VALUE in the table of case labels we already --- gcc/testsuite/gcc.dg/switch-6.c.jj 2024-10-29 09:01:53.563641337 +0100 +++ gcc/testsuite/gcc.dg/switch-6.c 2024-10-29 10:08:48.219414989 +0100 @@ -2,13 +2,13 @@ for case ranges with -pedantic. */ /* Origin: Joseph Myers */ /* { dg-do compile } */ -/* { dg-options "-pedantic" } */ +/* { dg-options "-pedantic -std=gnu23" } */ void f (int a) { switch (a) { - case 0 ... 0: ; /* { dg-warning "range expressions in switch statements are non-standard" } */ + case 0 ... 0: ; /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ } } --- gcc/testsuite/gcc.dg/switch-7.c.jj 2024-10-29 09:01:53.589640972 +0100 +++ gcc/testsuite/gcc.dg/switch-7.c 2024-10-29 10:08:48.219414989 +0100 @@ -2,13 +2,13 @@ for case ranges with -pedantic-errors. */ /* Origin: Joseph Myers */ /* { dg-do compile } */ -/* { dg-options "-pedantic-errors" } */ +/* { dg-options "-pedantic-errors -std=c23" } */ void f (int a) { switch (a) { - case 0 ... 0: ; /* { dg-error "range expressions in switch statements are non-standard" } */ + case 0 ... 0: ; /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ } } --- gcc/testsuite/gcc.dg/gnu23-switch-1.c.jj 2024-10-29 10:08:48.219414989 +0100 +++ gcc/testsuite/gcc.dg/gnu23-switch-1.c 2024-10-29 10:53:34.859778641 +0100 @@ -0,0 +1,100 @@ +/* C2Y N3370 - Case range expressions. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu23 -pedantic -W -Wall" } */ + +enum E { F = 10, G = 20 }; + +void +foo (unsigned x) +{ + switch (x) + { + case -1: + break; + case ~0U + 1ULL: /* { dg-warning "conversion from 'long long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */ + break; + default: + break; + } +} + +void +bar (unsigned x) +{ + switch (x) + { + case -2 ... -1: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "conversion of '-2' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-1 } */ + /* { dg-warning "conversion of '-1' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-2 } */ + break; + case ~0U + 1ULL ... ~0U + 2ULL: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '0'" "" { target *-*-* } .-1 } */ + /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { target *-*-* } .-2 } */ + break; + case 70 ... 70: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + break; + case 80 ... 78: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -4 ... -4: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "conversion of '-4' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-1 } */ + break; + case ~0U + 6ULL ... ~0U + 6ULL: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '5'" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} + +void +baz (unsigned char x) +{ + switch (x) + { + case -32 ... -30: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "case label value is less than minimum value for type" "" { target *-*-* } .-1 } */ + break; + case -31: /* { dg-error "duplicate case value" } */ + break; + case -42: /* { dg-warning "case label value is less than minimum value for type" } */ + break; + case -43 ... -41: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-error "duplicate \\\(or overlapping\\\) case value" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} + +void +qux (int x) +{ + switch (x) + { + case -6 ... -8: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -6: + break; + case -7: + break; + case -8: + break; + case F...G: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + break; + case -10: + break; + case -10 ... -11: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -14 ... -15: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -14 ... -15: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} --- gcc/testsuite/gcc.dg/gnu23-switch-2.c.jj 2024-10-29 10:08:48.220414975 +0100 +++ gcc/testsuite/gcc.dg/gnu23-switch-2.c 2024-10-29 10:53:41.986678747 +0100 @@ -0,0 +1,89 @@ +/* C2Y N3370 - Case range expressions. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu23 -pedantic -W -Wall -Wno-c23-c2y-compat" } */ + +enum E { F = 10, G = 20 }; + +void +foo (unsigned x) +{ + switch (x) + { + case -1: + break; + case ~0U + 1ULL: /* { dg-warning "conversion from 'long long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */ + break; + default: + break; + } +} + +void +bar (unsigned x) +{ + switch (x) + { + case -2 ... -1: /* { dg-warning "conversion of '-2' to 'unsigned int' in range expression changes value to '\[0-9]*'" } */ + /* { dg-warning "conversion of '-1' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-1 } */ + break; + case ~0U + 1ULL ... ~0U + 2ULL: /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '0'" } */ + /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { target *-*-* } .-1 } */ + break; + case 70 ... 70: + break; + case 80 ... 78: /* { dg-warning "empty range specified" } */ + break; + case -4 ... -4: /* { dg-warning "conversion of '-4' to 'unsigned int' in range expression changes value to '\[0-9]*'" } */ + break; + case ~0U + 6ULL ... ~0U + 6ULL: /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '5'" } */ + break; + default: + break; + } +} + +void +baz (unsigned char x) +{ + switch (x) + { + case -32 ... -30: /* { dg-warning "case label value is less than minimum value for type" } */ + break; + case -31: /* { dg-error "duplicate case value" } */ + break; + case -42: /* { dg-warning "case label value is less than minimum value for type" } */ + break; + case -43 ... -41: /* { dg-error "duplicate \\\(or overlapping\\\) case value" } */ + break; + default: + break; + } +} + +void +qux (int x) +{ + switch (x) + { + case -6 ... -8: /* { dg-warning "empty range specified" } */ + break; + case -6: + break; + case -7: + break; + case -8: + break; + case F...G: + break; + case -10: + break; + case -10 ... -11: /* { dg-warning "empty range specified" } */ + break; + case -14 ... -15: /* { dg-warning "empty range specified" } */ + break; + case -14 ... -15: /* { dg-warning "empty range specified" } */ + break; + default: + break; + } +} --- gcc/testsuite/gcc.dg/c23-switch-1.c.jj 2024-10-29 10:08:48.220414975 +0100 +++ gcc/testsuite/gcc.dg/c23-switch-1.c 2024-10-29 10:53:22.527951496 +0100 @@ -0,0 +1,100 @@ +/* C2Y N3370 - Case range expressions. */ +/* { dg-do compile } */ +/* { dg-options "-std=c23 -pedantic-errors -W -Wall" } */ + +enum E { F = 10, G = 20 }; + +void +foo (unsigned x) +{ + switch (x) + { + case -1: + break; + case ~0U + 1ULL: /* { dg-warning "conversion from 'long long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */ + break; + default: + break; + } +} + +void +bar (unsigned x) +{ + switch (x) + { + case -2 ... -1: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-error "conversion of '-2' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-1 } */ + /* { dg-error "conversion of '-1' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-2 } */ + break; + case ~0U + 1ULL ... ~0U + 2ULL: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-error "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '0'" "" { target *-*-* } .-1 } */ + /* { dg-error "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { target *-*-* } .-2 } */ + break; + case 70 ... 70: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + break; + case 80 ... 78: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -4 ... -4: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-error "conversion of '-4' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-1 } */ + break; + case ~0U + 6ULL ... ~0U + 6ULL: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-error "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '5'" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} + +void +baz (unsigned char x) +{ + switch (x) + { + case -32 ... -30: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "case label value is less than minimum value for type" "" { target *-*-* } .-1 } */ + break; + case -31: /* { dg-error "duplicate case value" } */ + break; + case -42: /* { dg-warning "case label value is less than minimum value for type" } */ + break; + case -43 ... -41: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-error "duplicate \\\(or overlapping\\\) case value" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} + +void +qux (int x) +{ + switch (x) + { + case -6 ... -8: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -6: + break; + case -7: + break; + case -8: + break; + case F...G: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + break; + case -10: + break; + case -10 ... -11: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -14 ... -15: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -14 ... -15: /* { dg-error "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} --- gcc/testsuite/gcc.dg/c2y-switch-1.c.jj 2024-10-29 10:08:48.220414975 +0100 +++ gcc/testsuite/gcc.dg/c2y-switch-1.c 2024-10-29 10:52:13.440919866 +0100 @@ -0,0 +1,89 @@ +/* C2Y N3370 - Case range expressions. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2y -pedantic -W -Wall" } */ + +enum E { F = 10, G = 20 }; + +void +foo (unsigned x) +{ + switch (x) + { + case -1: + break; + case ~0U + 1ULL: /* { dg-warning "conversion from 'long long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */ + break; + default: + break; + } +} + +void +bar (unsigned x) +{ + switch (x) + { + case -2 ... -1: /* { dg-warning "conversion of '-2' to 'unsigned int' in range expression changes value to '\[0-9]*'" } */ + /* { dg-warning "conversion of '-1' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-1 } */ + break; + case ~0U + 1ULL ... ~0U + 2ULL: /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '0'" } */ + /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { target *-*-* } .-1 } */ + break; + case 70 ... 70: + break; + case 80 ... 78: /* { dg-warning "empty range specified" } */ + break; + case -4 ... -4: /* { dg-warning "conversion of '-4' to 'unsigned int' in range expression changes value to '\[0-9]*'" } */ + break; + case ~0U + 6ULL ... ~0U + 6ULL: /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '5'" } */ + break; + default: + break; + } +} + +void +baz (unsigned char x) +{ + switch (x) + { + case -32 ... -30: /* { dg-warning "case label value is less than minimum value for type" } */ + break; + case -31: /* { dg-error "duplicate case value" } */ + break; + case -42: /* { dg-warning "case label value is less than minimum value for type" } */ + break; + case -43 ... -41: /* { dg-error "duplicate \\\(or overlapping\\\) case value" } */ + break; + default: + break; + } +} + +void +qux (int x) +{ + switch (x) + { + case -6 ... -8: /* { dg-warning "empty range specified" } */ + break; + case -6: + break; + case -7: + break; + case -8: + break; + case F...G: + break; + case -10: + break; + case -10 ... -11: /* { dg-warning "empty range specified" } */ + break; + case -14 ... -15: /* { dg-warning "empty range specified" } */ + break; + case -14 ... -15: /* { dg-warning "empty range specified" } */ + break; + default: + break; + } +} --- gcc/testsuite/gcc.dg/c2y-switch-2.c.jj 2024-10-29 10:08:48.220414975 +0100 +++ gcc/testsuite/gcc.dg/c2y-switch-2.c 2024-10-29 10:52:54.576343283 +0100 @@ -0,0 +1,100 @@ +/* C2Y N3370 - Case range expressions. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2y -pedantic -W -Wall -Wc23-c2y-compat" } */ + +enum E { F = 10, G = 20 }; + +void +foo (unsigned x) +{ + switch (x) + { + case -1: + break; + case ~0U + 1ULL: /* { dg-warning "conversion from 'long long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */ + break; + default: + break; + } +} + +void +bar (unsigned x) +{ + switch (x) + { + case -2 ... -1: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "conversion of '-2' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-1 } */ + /* { dg-warning "conversion of '-1' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-2 } */ + break; + case ~0U + 1ULL ... ~0U + 2ULL: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '0'" "" { target *-*-* } .-1 } */ + /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { target *-*-* } .-2 } */ + break; + case 70 ... 70: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + break; + case 80 ... 78: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -4 ... -4: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "conversion of '-4' to 'unsigned int' in range expression changes value to '\[0-9]*'" "" { target *-*-* } .-1 } */ + break; + case ~0U + 6ULL ... ~0U + 6ULL: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "conversion of '\[0-9]*' to 'unsigned int' in range expression changes value to '5'" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} + +void +baz (unsigned char x) +{ + switch (x) + { + case -32 ... -30: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "case label value is less than minimum value for type" "" { target *-*-* } .-1 } */ + break; + case -31: /* { dg-error "duplicate case value" } */ + break; + case -42: /* { dg-warning "case label value is less than minimum value for type" } */ + break; + case -43 ... -41: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-error "duplicate \\\(or overlapping\\\) case value" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} + +void +qux (int x) +{ + switch (x) + { + case -6 ... -8: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -6: + break; + case -7: + break; + case -8: + break; + case F...G: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + break; + case -10: + break; + case -10 ... -11: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -14 ... -15: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + case -14 ... -15: /* { dg-warning "ISO C does not support range expressions in switch statements before C2Y" } */ + /* { dg-warning "empty range specified" "" { target *-*-* } .-1 } */ + break; + default: + break; + } +} --- gcc/testsuite/gcc.dg/c2y-switch-3.c.jj 2024-10-29 10:21:51.261442070 +0100 +++ gcc/testsuite/gcc.dg/c2y-switch-3.c 2024-10-29 10:55:27.757196207 +0100 @@ -0,0 +1,40 @@ +/* C2Y N3370 - Case range expressions. */ +/* { dg-do run } */ +/* { dg-options "-std=c2y -pedantic-errors" } */ + +extern void abort (); + +void +foo (int x) +{ + switch (x) + { + case -42 ... 42: + if (x < -42 || x > 42) + abort (); + break; + case 43 ... 43: + if (x != 43) + abort (); + break; + case 44: + if (x != 44) + abort (); + break; + case 45 ... 46: + if (x < 45 || x > 46) + abort (); + break; + default: + if (x >= -42 && x <= 46) + abort (); + break; + } +} + +int +main () +{ + for (int i = -44; i <= 48; ++i) + foo (i); +}