From patchwork Tue Nov 14 17:38:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 165027 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:6358:a59:b0:164:83eb:24d7 with SMTP id 25csp2087812rwb; Tue, 14 Nov 2023 09:39:14 -0800 (PST) X-Google-Smtp-Source: AGHT+IFxZi0daglFMq58qAraQCgSuNZ4ysRJEuLX7H/UsCi5xKQgMqhiZ/hZ7p0ebJ1qg7rdlWUA X-Received: by 2002:a05:620a:2589:b0:779:e19b:64f5 with SMTP id x9-20020a05620a258900b00779e19b64f5mr4381966qko.21.1699983554709; Tue, 14 Nov 2023 09:39:14 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1699983554; cv=pass; d=google.com; s=arc-20160816; b=BENHCQw0MHFictDuz6Po+lZ78b+s+C/DNgVJFjSnY94pBOLzgU7MSl75P3eO8OK+kP vw6CWYT9dQLf8ptLNVhM+L7L2A/fIEh9mugkvRpe9EotyYYGcNwJlvzJfGrUf6G9EpjY 9UIRRvt29alU0CD5+4h3X96RzeYQWhb84u7Sto6xF96ichbWINxA9QvqEvXZfKCvL8iD +E6oW9u59vjAsDJELqyVjLnl0XHS2A3AMti/MXLTWQ9G3+j2DWF7fY/qaiM6xoU2rEqn EWu9yexkeiqPApaINhENslNeuFOOLQOPGquwEN7m22aY1r+7oqnFPjm2Lb/n1V0rXJQN YbIQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:reply-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-disposition:in-reply-to :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=EFMlggiaKqGw6pAEeZqqdqvBQJ3j0DwQHsA1rO1Rwio=; fh=drb8jPahgz959MrupsiUi8XeCFozkYVF0F6zLW2CcMA=; b=fNEv9pmKrtcXsBhIPTpKzLejWhATtfDapYEaJdV/l9VC9ut1ro6DlzqQrq5vC2KTRz QnK5QCbR5ZUCVBv9cEyRfFpZ5q61+ASDOjY3FA97RYclse6GiyGLMqJkefXSBuvJdCDQ hhIUHqaZFaWlUEMZqg7Ms2pWF08AMN069fAV/JUCP5radRoi+82olGB1a+rj7Mr4SdBl pn6aSouc8tg9Dri7QxGSk+OdU3Pmm5e78UQmd8ovPUT/HQAenJxIpMHgZwF7847LG9va Ntw6Uh4fi88QsL2J0WYhF7Mhx5m+BMXU5cg3sGYId0iZxxm8qqYOyobFzHBaUEB0W06Z 6NKA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="bW/o0KOA"; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id p15-20020a05620a112f00b00775cadf4e5csi7070979qkk.214.2023.11.14.09.39.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Nov 2023 09:39:14 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="bW/o0KOA"; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 72CFC385843E for ; Tue, 14 Nov 2023 17:39:14 +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.133.124]) by sourceware.org (Postfix) with ESMTPS id 281363858D32 for ; Tue, 14 Nov 2023 17:38:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 281363858D32 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 281363858D32 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699983529; cv=none; b=UpHYH7PuZUykBXgjgxwtD0jGNdHt4eE2rdDgL9//26rZ06J/q+VpZDfwo/sAJjQQJSQk4bNgZRA2LIP18Pc5qKinideSKJPHTJ2cwKRnjavgem7yNRM7wIarepkqUqyC/dbmOKNEVsojKAm08UGT4ymyPECyXkXQaK/o1DkhgKc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699983529; c=relaxed/simple; bh=+8kpM6Xlb1YkeePgGUsHvVHj6Wuf9Vrq6r1IMCuTzOs=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=mxXQh4ZWdVpaZGjBZbcon6BBeIN/rPuxmNT+hYJ/6kvg7Va3qGAf/L/RPJRZzz7r/MlQBrI10HADjQIlJwvIJKOdDlJedmKOlSOTxxfdN7B+EjzktclpZQxw7+Eypu4PNr87xYqzrfAXJwZEjGsafSzndO1gOadpoh9/TX5Gfx0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1699983525; 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:in-reply-to:in-reply-to: references:references; bh=EFMlggiaKqGw6pAEeZqqdqvBQJ3j0DwQHsA1rO1Rwio=; b=bW/o0KOAZwii+9tpgczWxQwBT8UJGzS5NqNafwshQbvR//0uhLf483hB/PIMfZd3ydYe8x z14XWLgQJ5JN0sQU2jqBX2fyK5nIWGb2tTkJEe1NKzqZhpPPQK0Y9B4BgxVlQkBLTgAQ1W JEGUPLTcUJ9yiKB5VITn7Gk8nEMm6lc= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-42-VHM7li1tPlCBmkEab9IDtw-1; Tue, 14 Nov 2023 12:38:43 -0500 X-MC-Unique: VHM7li1tPlCBmkEab9IDtw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id EDE7385A58B for ; Tue, 14 Nov 2023 17:38:42 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.194.53]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6B332143; Tue, 14 Nov 2023 17:38:42 +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 3AEHcdul1910283 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Tue, 14 Nov 2023 18:38:40 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 3AEHcdg11910282; Tue, 14 Nov 2023 18:38:39 +0100 Date: Tue, 14 Nov 2023 18:38:39 +0100 From: Jakub Jelinek To: Jason Merrill Cc: gcc-patches@gcc.gnu.org, Marek Polacek Subject: [PATCH] c++, v2: Implement C++26 P2864R2 - Remove Deprecated Arithmetic Conversion on Enumerations From C++26 Message-ID: References: <1c62f30c-8e9f-43a1-a667-6f3a0cd95230@redhat.com> MIME-Version: 1.0 In-Reply-To: <1c62f30c-8e9f-43a1-a667-6f3a0cd95230@redhat.com> X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=no 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+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1782561955792485978 X-GMAIL-MSGID: 1782561955792485978 On Mon, Nov 13, 2023 at 10:59:52PM -0500, Jason Merrill wrote: > On 11/13/23 06:50, Jakub Jelinek wrote: > > The following patch implements C++26 P2864R2 by emitting pedwarn enabled by > > the same options as the C++20 and later warnings (i.e. -Wenum-compare, > > -Wdeprecated-enum-enum-conversion and -Wdeprecated-enum-float-conversion > > which are all enabled by default). I think we still want to allow users > > some option workaround, so am not using directly error, but if that is > > what you want instead, I can change it. > > I agree, but we also need to return error_mark_node for these cases when > SFINAE, i.e. !(complain & tf_warning_or_error) So like this then? Bootstrapped/regtested on x86_64-linux and i686-linux. 2023-11-14 Jakub Jelinek gcc/cp/ * typeck.cc: Implement C++26 P2864R2 - Remove Deprecated Arithmetic Conversion on Enumerations From C++26. (do_warn_enum_conversions): Return bool rather than void, add COMPLAIN argument. Use pedwarn rather than warning_at for C++26 and remove " is deprecated" part of the diagnostics in that case. For SFINAE in C++26 return true on newly erroneous cases. (cp_build_binary_op): For C++26 call do_warn_enum_conversions unconditionally, pass complain argument to it and if it returns true, return error_mark_node. * call.cc (build_conditional_expr): Use pedwarn rather than warning_at for C++26 and remove " is deprecated" part of the diagnostics in that case and check for complain & tf_warning_or_error. Use emit_diagnostic with cxx_dialect >= cxx26 ? DK_PEDWARN : DK_WARNING. For SFINAE in C++26 return error_mark_node on newly erroneous cases. (build_new_op): Use emit_diagnostic with cxx_dialect >= cxx26 ? DK_PEDWARN : DK_WARNING and complain & tf_warning_or_error check for C++26. For SFINAE in C++26 return error_mark_node on newly erroneous cases. gcc/testsuite/ * g++.dg/cpp26/enum-conv1.C: New test. * g++.dg/cpp2a/enum-conv1.C: Adjust expected diagnostics in C++26. * g++.dg/diagnostic/enum3.C: Likewise. * g++.dg/parse/attr3.C: Likewise. * g++.dg/cpp0x/linkage2.C: Likewise. Jakub --- gcc/cp/typeck.cc.jj 2023-11-13 13:02:21.573785549 +0100 +++ gcc/cp/typeck.cc 2023-11-14 09:49:31.026997048 +0100 @@ -4940,16 +4940,25 @@ warn_for_null_address (location_t locati type, this behavior is deprecated ([depr.arith.conv.enum]). CODE is the code of the binary operation, TYPE0 and TYPE1 are the types of the operands, and LOC is the location for the whole binary expression. + For C++26 this is ill-formed rather than deprecated. + Return true for SFINAE errors. TODO: Consider combining this with -Wenum-compare in build_new_op_1. */ -static void +static bool do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, - tree type1) + tree type1, tsubst_flags_t complain) { if (TREE_CODE (type0) == ENUMERAL_TYPE && TREE_CODE (type1) == ENUMERAL_TYPE && TYPE_MAIN_VARIANT (type0) != TYPE_MAIN_VARIANT (type1)) { + if (cxx_dialect >= cxx26) + { + if ((complain & tf_warning_or_error) == 0) + return true; + } + else if ((complain & tf_warning) == 0) + return false; /* In C++20, -Wdeprecated-enum-enum-conversion is on by default. Otherwise, warn if -Wenum-conversion is on. */ enum opt_code opt; @@ -4958,7 +4967,7 @@ do_warn_enum_conversions (location_t loc else if (warn_enum_conversion) opt = OPT_Wenum_conversion; else - return; + return false; switch (code) { @@ -4969,21 +4978,29 @@ do_warn_enum_conversions (location_t loc case EQ_EXPR: case NE_EXPR: /* Comparisons are handled by -Wenum-compare. */ - return; + return false; case SPACESHIP_EXPR: /* This is invalid, don't warn. */ - return; + return false; case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: - warning_at (loc, opt, "bitwise operation between different " - "enumeration types %qT and %qT is deprecated", - type0, type1); - return; + if (cxx_dialect >= cxx26) + pedwarn (loc, opt, "bitwise operation between different " + "enumeration types %qT and %qT", type0, type1); + else + warning_at (loc, opt, "bitwise operation between different " + "enumeration types %qT and %qT is deprecated", + type0, type1); + return false; default: - warning_at (loc, opt, "arithmetic between different enumeration " - "types %qT and %qT is deprecated", type0, type1); - return; + if (cxx_dialect >= cxx26) + pedwarn (loc, opt, "arithmetic between different enumeration " + "types %qT and %qT", type0, type1); + else + warning_at (loc, opt, "arithmetic between different enumeration " + "types %qT and %qT is deprecated", type0, type1); + return false; } } else if ((TREE_CODE (type0) == ENUMERAL_TYPE @@ -4991,6 +5008,13 @@ do_warn_enum_conversions (location_t loc || (SCALAR_FLOAT_TYPE_P (type0) && TREE_CODE (type1) == ENUMERAL_TYPE)) { + if (cxx_dialect >= cxx26) + { + if ((complain & tf_warning_or_error) == 0) + return true; + } + else if ((complain & tf_warning) == 0) + return false; const bool enum_first_p = TREE_CODE (type0) == ENUMERAL_TYPE; /* In C++20, -Wdeprecated-enum-float-conversion is on by default. Otherwise, warn if -Wenum-conversion is on. */ @@ -5000,7 +5024,7 @@ do_warn_enum_conversions (location_t loc else if (warn_enum_conversion) opt = OPT_Wenum_conversion; else - return; + return false; switch (code) { @@ -5010,7 +5034,13 @@ do_warn_enum_conversions (location_t loc case LE_EXPR: case EQ_EXPR: case NE_EXPR: - if (enum_first_p) + if (enum_first_p && cxx_dialect >= cxx26) + pedwarn (loc, opt, "comparison of enumeration type %qT with " + "floating-point type %qT", type0, type1); + else if (cxx_dialect >= cxx26) + pedwarn (loc, opt, "comparison of floating-point type %qT " + "with enumeration type %qT", type0, type1); + else if (enum_first_p) warning_at (loc, opt, "comparison of enumeration type %qT with " "floating-point type %qT is deprecated", type0, type1); @@ -5018,12 +5048,18 @@ do_warn_enum_conversions (location_t loc warning_at (loc, opt, "comparison of floating-point type %qT " "with enumeration type %qT is deprecated", type0, type1); - return; + return false; case SPACESHIP_EXPR: /* This is invalid, don't warn. */ - return; + return false; default: - if (enum_first_p) + if (enum_first_p && cxx_dialect >= cxx26) + pedwarn (loc, opt, "arithmetic between enumeration type %qT " + "and floating-point type %qT", type0, type1); + else if (cxx_dialect >= cxx26) + pedwarn (loc, opt, "arithmetic between floating-point type %qT " + "and enumeration type %qT", type0, type1); + else if (enum_first_p) warning_at (loc, opt, "arithmetic between enumeration type %qT " "and floating-point type %qT is deprecated", type0, type1); @@ -5031,9 +5067,10 @@ do_warn_enum_conversions (location_t loc warning_at (loc, opt, "arithmetic between floating-point type %qT " "and enumeration type %qT is deprecated", type0, type1); - return; + return true; } } + return false; } /* Build a binary-operation expression without default conversions. @@ -6163,15 +6200,13 @@ cp_build_binary_op (const op_location_t return error_mark_node; } if (complain & tf_warning) - { - do_warn_double_promotion (result_type, type0, type1, - "implicit conversion from %qH to %qI " - "to match other operand of binary " - "expression", - location); - do_warn_enum_conversions (location, code, TREE_TYPE (orig_op0), - TREE_TYPE (orig_op1)); - } + do_warn_double_promotion (result_type, type0, type1, + "implicit conversion from %qH to %qI " + "to match other operand of binary " + "expression", location); + if (do_warn_enum_conversions (location, code, TREE_TYPE (orig_op0), + TREE_TYPE (orig_op1), complain)) + return error_mark_node; } if (may_need_excess_precision && (orig_type0 != type0 || orig_type1 != type1) --- gcc/cp/call.cc.jj 2023-11-13 13:02:21.545785943 +0100 +++ gcc/cp/call.cc 2023-11-14 09:59:27.336644386 +0100 @@ -6163,19 +6163,36 @@ build_conditional_expr (const op_locatio == DECL_CONTEXT (stripped_orig_arg3))) /* Two enumerators from the same enumeration can have different types when the enumeration is still being defined. */; - else if (complain & tf_warning) - warning_at (loc, OPT_Wenum_compare, "enumerated mismatch " - "in conditional expression: %qT vs %qT", - arg2_type, arg3_type); + else if (complain & (cxx_dialect >= cxx26 + ? tf_warning_or_error : tf_warning)) + emit_diagnostic (cxx_dialect >= cxx26 ? DK_PEDWARN : DK_WARNING, + loc, OPT_Wenum_compare, "enumerated mismatch " + "in conditional expression: %qT vs %qT", + arg2_type, arg3_type); + else if (cxx_dialect >= cxx26) + return error_mark_node; } - else if ((complain & tf_warning) - && warn_deprecated_enum_float_conv + else if ((((complain & (cxx_dialect >= cxx26 + ? tf_warning_or_error : tf_warning)) + && warn_deprecated_enum_float_conv) + || (cxx_dialect >= cxx26 + && (complain & tf_warning_or_error) == 0)) && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE && SCALAR_FLOAT_TYPE_P (arg3_type)) || (SCALAR_FLOAT_TYPE_P (arg2_type) && TREE_CODE (arg3_type) == ENUMERAL_TYPE))) { - if (TREE_CODE (arg2_type) == ENUMERAL_TYPE) + if (cxx_dialect >= cxx26 && (complain & tf_warning_or_error) == 0) + return error_mark_node; + if (cxx_dialect >= cxx26 && TREE_CODE (arg2_type) == ENUMERAL_TYPE) + pedwarn (loc, OPT_Wdeprecated_enum_float_conversion, + "conditional expression between enumeration type " + "%qT and floating-point type %qT", arg2_type, arg3_type); + else if (cxx_dialect >= cxx26) + pedwarn (loc, OPT_Wdeprecated_enum_float_conversion, + "conditional expression between floating-point type " + "%qT and enumeration type %qT", arg2_type, arg3_type); + else if (TREE_CODE (arg2_type) == ENUMERAL_TYPE) warning_at (loc, OPT_Wdeprecated_enum_float_conversion, "conditional expression between enumeration type " "%qT and floating-point type %qT is deprecated", @@ -7258,11 +7275,18 @@ build_new_op (const op_location_t &loc, if (TREE_CODE (arg1_type) == ENUMERAL_TYPE && TREE_CODE (arg2_type) == ENUMERAL_TYPE && (TYPE_MAIN_VARIANT (arg1_type) - != TYPE_MAIN_VARIANT (arg2_type)) - && (complain & tf_warning)) - warning_at (loc, OPT_Wenum_compare, - "comparison between %q#T and %q#T", - arg1_type, arg2_type); + != TYPE_MAIN_VARIANT (arg2_type))) + { + if (cxx_dialect >= cxx26 + && (complain & tf_warning_or_error) == 0) + result = error_mark_node; + else if (cxx_dialect >= cxx26 || (complain & tf_warning)) + emit_diagnostic (cxx_dialect >= cxx26 + ? DK_PEDWARN : DK_WARNING, + loc, OPT_Wenum_compare, + "comparison between %q#T and %q#T", + arg1_type, arg2_type); + } break; default: break; --- gcc/testsuite/g++.dg/diagnostic/enum3.C.jj 2023-11-13 13:02:21.617784930 +0100 +++ gcc/testsuite/g++.dg/diagnostic/enum3.C 2023-11-14 09:39:10.021090313 +0100 @@ -5,5 +5,6 @@ enum e1 { e1val }; enum e2 { e3val }; int main( int, char * [] ) { - if ( e1val == e3val ) return 1; // { dg-warning -Wenum-compare } + if ( e1val == e3val ) return 1; // { dg-warning "comparison between 'enum e1' and 'enum e2'" "" { target c++23_down } } + // { dg-error "comparison between 'enum e1' and 'enum e2'" "" { target c++26 } .-1 } } --- gcc/testsuite/g++.dg/cpp26/enum-conv1.C.jj 2023-11-14 10:08:14.505260200 +0100 +++ gcc/testsuite/g++.dg/cpp26/enum-conv1.C 2023-11-14 10:17:07.964758706 +0100 @@ -0,0 +1,39 @@ +// P2864R2 - Remove Deprecated Arithmetic Conversion on Enumerations From C++26 +// { dg-do compile { target c++20 } } + +enum A { a }; +enum B { b }; + +template decltype (true ? X : Y) f1 () { throw 1; } +// { dg-error "enumerated mismatch in conditional expression: 'A' vs 'B'" "" { target c++26 } .-1 } +// { dg-error "conditional expression between enumeration type 'A' and floating-point type 'double'" "" { target c++26 } .-2 } +// { dg-error "conditional expression between floating-point type 'double' and enumeration type 'A'" "" { target c++26 } .-3 } +template decltype (X + Y) f2 () { throw 1; } +// { dg-error "arithmetic between different enumeration types 'A' and 'B'" "" { target c++26 } .-1 } +// { dg-error "arithmetic between enumeration type 'A' and floating-point type 'double'" "" { target c++26 } .-2 } +// { dg-error "arithmetic between floating-point type 'double' and enumeration type 'A'" "" { target c++26 } .-3 } +template decltype (X | Y) f3 () { throw 1; } +// { dg-error "bitwise operation between different enumeration types 'A' and 'B'" "" { target c++26 } .-1 } +template decltype (X < Y) f4 () { throw 1; } +// { dg-error "comparison between 'enum A' and 'enum B'" "" { target c++26 } .-1 } +// { dg-error "comparison of enumeration type 'A' with floating-point type 'double'" "" { target c++26 } .-2 } +// { dg-error "comparison of floating-point type 'double' with enumeration type 'A'" "" { target c++26 } .-3 } + +int +main () +{ + f1 (); + f2 (); + f3 (); + f4 (); + f1 (); // { dg-error "no matching function for call to" "" { target c++26 } } + f2 (); // { dg-error "no matching function for call to" "" { target c++26 } } + f3 (); // { dg-error "no matching function for call to" "" { target c++26 } } + f4 (); // { dg-error "no matching function for call to" "" { target c++26 } } + f1 (); // { dg-error "no matching function for call to" "" { target c++26 } } + f2 (); // { dg-error "no matching function for call to" "" { target c++26 } } + f4 (); // { dg-error "no matching function for call to" "" { target c++26 } } + f1<0.0, a> (); // { dg-error "no matching function for call to" "" { target c++26 } } + f2<0.0, a> (); // { dg-error "no matching function for call to" "" { target c++26 } } + f4<0.0, a> (); // { dg-error "no matching function for call to" "" { target c++26 } } +} --- gcc/testsuite/g++.dg/parse/attr3.C.jj 2023-11-13 13:02:21.627784789 +0100 +++ gcc/testsuite/g++.dg/parse/attr3.C 2023-11-14 09:39:10.030090178 +0100 @@ -10,5 +10,6 @@ int main () { S::F y; // { dg-warning "'F' is deprecated" } y = S::f; - return x + y; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } } + return x + y; // { dg-warning "arithmetic between different enumeration types" "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types" "" { target c++26 } .-1 } } --- gcc/testsuite/g++.dg/cpp2a/enum-conv1.C.jj 2023-11-13 13:02:21.614784972 +0100 +++ gcc/testsuite/g++.dg/cpp2a/enum-conv1.C 2023-11-14 09:39:10.001090611 +0100 @@ -14,11 +14,16 @@ void conv () { bool b1 = e == e1; - bool b2 = e == f; // { dg-warning "comparison between .enum E1. and .enum E2." } - bool b3 = e == 0.0; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } } - bool b4 = 0.0 == f; // { dg-warning "comparison of floating-point type .double. with enumeration type .E2." "" { target c++20 } } - int n1 = true ? e : f; // { dg-warning "enumerated mismatch" } - int n2 = true ? e : 0.0; // { dg-warning "conditional expression between" "" { target c++20 } } + bool b2 = e == f; // { dg-warning "comparison between .enum E1. and .enum E2." "" { target c++23_down } } + // { dg-error "comparison between .enum E1. and .enum E2." "" { target c++26 } .-1 } + bool b3 = e == 0.0; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target { c++20 && c++23_down } } } + // { dg-error "comparison of enumeration type .E1. with floating-point type .double." "" { target c++26 } .-1 } + bool b4 = 0.0 == f; // { dg-warning "comparison of floating-point type .double. with enumeration type .E2." "" { target { c++20 && c++23_down } } } + // { dg-error "comparison of floating-point type .double. with enumeration type .E2." "" { target c++26 } .-1 } + int n1 = true ? e : f; // { dg-warning "enumerated mismatch" "" { target c++23_down } } + // { dg-error "enumerated mismatch" "" { target c++26 } .-1 } + int n2 = true ? e : 0.0; // { dg-warning "conditional expression between" "" { target { c++20 && c++23_down } } } + // { dg-error "conditional expression between" "" { target c++26 } .-1 } } int @@ -29,42 +34,60 @@ enum_enum (bool b) r += e - e; r += e - e1; - r += e - f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } } - r += f - e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } } - + r += e - f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types .E1. and .E2." "" { target c++26 } .-1 } + r += f - e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types .E2. and .E1." "" { target c++26 } .-1 } r += f + f; - r += f + e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } } - r += e + f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } } + r += f + e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types .E2. and .E1." "" { target c++26 } .-1 } + r += e + f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types .E1. and .E2." "" { target c++26 } .-1 } - r += e1 - e2; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } } + r += e1 - e2; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types .E1. and .E2." "" { target c++26 } .-1 } r += e1 - e1c; r += e1c - e1; - r += e * f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } } - r += f * e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } } + r += e * f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types .E1. and .E2." "" { target c++26 } .-1 } + r += f * e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types .E2. and .E1." "" { target c++26 } .-1 } r += e * e; r += e1 < e1c; r += e < e1; - r += e1 < e2; // { dg-warning "comparison between .enum E1. and .enum E2." } - r += e < f; // { dg-warning "comparison between .enum E1. and .enum E2." } - r += f < e; // { dg-warning "comparison between .enum E2. and .enum E1." } + r += e1 < e2; // { dg-warning "comparison between .enum E1. and .enum E2." "" { target c++23_down } } + // { dg-error "comparison between .enum E1. and .enum E2." "" { target c++26 } .-1 } + r += e < f; // { dg-warning "comparison between .enum E1. and .enum E2." "" { target c++23_down } } + // { dg-error "comparison between .enum E1. and .enum E2." "" { target c++26 } .-1 } + r += f < e; // { dg-warning "comparison between .enum E2. and .enum E1." "" { target c++23_down } } + // { dg-error "comparison between .enum E2. and .enum E1." "" { target c++26 } .-1 } r += e1 == e1c; r += e == e1; - r += e == f; // { dg-warning "comparison between .enum E1. and .enum E2." } - r += f == e; // { dg-warning "comparison between .enum E2. and .enum E1." } - r += e1 == e2; // { dg-warning "comparison between .enum E1. and .enum E2." } - r += e2 == e1; // { dg-warning "comparison between .enum E2. and .enum E1." } + r += e == f; // { dg-warning "comparison between .enum E1. and .enum E2." "" { target c++23_down } } + // { dg-error "comparison between .enum E1. and .enum E2." "" { target c++26 } .-1 } + r += f == e; // { dg-warning "comparison between .enum E2. and .enum E1." "" { target c++23_down } } + // { dg-error "comparison between .enum E2. and .enum E1." "" { target c++26 } .-1 } + r += e1 == e2; // { dg-warning "comparison between .enum E1. and .enum E2." "" { target c++23_down } } + // { dg-error "comparison between .enum E1. and .enum E2." "" { target c++26 } .-1 } + r += e2 == e1; // { dg-warning "comparison between .enum E2. and .enum E1." "" { target c++23_down } } + // { dg-error "comparison between .enum E2. and .enum E1." "" { target c++26 } .-1 } r += b ? e1 : e1c; r += b ? e1 : e; - r += b ? f : e; // { dg-warning "enumerated mismatch in conditional expression: .E2. vs .E1." } - r += b ? e1 : e2; // { dg-warning "enumerated mismatch in conditional expression: .E1. vs .E2." } - - r += e | f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } } - r += e ^ f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } } - r += e & f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } } + r += b ? f : e; // { dg-warning "enumerated mismatch in conditional expression: .E2. vs .E1." "" { target c++23_down } } + // { dg-error "enumerated mismatch in conditional expression: .E2. vs .E1." "" { target c++26 } .-1 } + r += b ? e1 : e2; // { dg-warning "enumerated mismatch in conditional expression: .E1. vs .E2." "" { target c++23_down } } + // { dg-error "enumerated mismatch in conditional expression: .E1. vs .E2." "" { target c++26 } .-1 } + + r += e | f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target { c++20 && c++23_down } } } + // { dg-error "bitwise operation between different enumeration types .E1. and .E2." "" { target c++26 } .-1 } + r += e ^ f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target { c++20 && c++23_down } } } + // { dg-error "bitwise operation between different enumeration types .E1. and .E2." "" { target c++26 } .-1 } + r += e & f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target { c++20 && c++23_down } } } + // { dg-error "bitwise operation between different enumeration types .E1. and .E2." "" { target c++26 } .-1 } r += !e; r += e1 | e; @@ -76,10 +99,14 @@ enum_enum (bool b) // Anonymous enum. r += u1 - u1; - r += u1 + u2; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } } - r += u1 * u2; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } } - r += u1 == u2; // { dg-warning "comparison between" } - r += u1 & u2; // { dg-warning "bitwise operation between different enumeration types" "" { target c++20 } } + r += u1 + u2; // { dg-warning "arithmetic between different enumeration types" "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types" "" { target c++26 } .-1 } + r += u1 * u2; // { dg-warning "arithmetic between different enumeration types" "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types" "" { target c++26 } .-1 } + r += u1 == u2; // { dg-warning "comparison between" "" { target c++23_down } } + // { dg-error "comparison between" "" { target c++26 } .-1 } + r += u1 & u2; // { dg-warning "bitwise operation between different enumeration types" "" { target { c++20 && c++23_down } } } + // { dg-error "bitwise operation between different enumeration types" "" { target c++26 } .-1 } return r; } @@ -89,28 +116,47 @@ enum_float (bool b) { double r = 0.0; - r += e1 - d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } } - r += d - e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } } - r += e1 + d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } } - r += d + e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } } - r += e1 * d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } } - r += d * e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } } - r += u1 * d; // { dg-warning "arithmetic between enumeration type" "" { target c++20 } } - r += d * u1; // { dg-warning "arithmetic between floating-point type" "" { target c++20 } } - - r += e1 < d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } } - r += d < e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." "" { target c++20 } } - r += d == e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." "" { target c++20 } } - r += e1 == d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } } - r += u1 == d; // { dg-warning "comparison of enumeration type" "" { target c++20 } } - r += d == u1; // { dg-warning "comparison of floating-point type" "" { target c++20 } } - - r += b ? e1 : d; // { dg-warning "conditional expression between enumeration type .E1. and floating-point type .double." "" { target c++20 } } - r += b ? d : e1; // { dg-warning "conditional expression between floating-point type .double. and enumeration type .E1." "" { target c++20 } } - r += b ? d : u1; // { dg-warning "conditional expression between" "" { target c++20 } } - r += b ? u1 : d; // { dg-warning "conditional expression between" "" { target c++20 } } + r += e1 - d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++26 } .-1 } + r += d - e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++26 } .-1 } + r += e1 + d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++26 } .-1 } + r += d + e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++26 } .-1 } + r += e1 * d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++26 } .-1 } + r += d * e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++26 } .-1 } + r += u1 * d; // { dg-warning "arithmetic between enumeration type" "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between enumeration type" "" { target c++26 } .-1 } + r += d * u1; // { dg-warning "arithmetic between floating-point type" "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between floating-point type" "" { target c++26 } .-1 } + + r += e1 < d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target { c++20 && c++23_down } } } + // { dg-error "comparison of enumeration type .E1. with floating-point type .double." "" { target c++26 } .-1 } + r += d < e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "comparison of floating-point type .double. with enumeration type .E1." "" { target c++26 } .-1 } + r += d == e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "comparison of floating-point type .double. with enumeration type .E1." "" { target c++26 } .-1 } + r += e1 == d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target { c++20 && c++23_down } } } + // { dg-error "comparison of enumeration type .E1. with floating-point type .double." "" { target c++26 } .-1 } + r += u1 == d; // { dg-warning "comparison of enumeration type" "" { target { c++20 && c++23_down } } } + // { dg-error "comparison of enumeration type" "" { target c++26 } .-1 } + r += d == u1; // { dg-warning "comparison of floating-point type" "" { target { c++20 && c++23_down } } } + // { dg-error "comparison of floating-point type" "" { target c++26 } .-1 } + + r += b ? e1 : d; // { dg-warning "conditional expression between enumeration type .E1. and floating-point type .double." "" { target { c++20 && c++23_down } } } + // { dg-error "conditional expression between enumeration type .E1. and floating-point type .double." "" { target c++26 } .-1 } + r += b ? d : e1; // { dg-warning "conditional expression between floating-point type .double. and enumeration type .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "conditional expression between floating-point type .double. and enumeration type .E1." "" { target c++26 } .-1 } + r += b ? d : u1; // { dg-warning "conditional expression between" "" { target { c++20 && c++23_down } } } + // { dg-error "conditional expression between" "" { target c++26 } .-1 } + r += b ? u1 : d; // { dg-warning "conditional expression between" "" { target { c++20 && c++23_down } } } + // { dg-error "conditional expression between" "" { target c++26 } .-1 } - d += e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } } + d += e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++26 } .-1 } d = e1; return r; --- gcc/testsuite/g++.dg/cpp0x/linkage2.C.jj 2023-11-13 13:02:21.587785352 +0100 +++ gcc/testsuite/g++.dg/cpp0x/linkage2.C 2023-11-14 09:39:10.038090059 +0100 @@ -29,5 +29,6 @@ void f() { ba.g(a); // OK ba.h(a); // error, B::h never defined i(ba, a); // OK - e1+e2+e3; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } } + e1+e2+e3; // { dg-warning "arithmetic between different enumeration types" "" { target { c++20 && c++23_down } } } + // { dg-error "arithmetic between different enumeration types" "" { target c++26 } .-1 } }