{"id":2231959,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2231959/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/afTZmG0U0aOVnvuW@tucnak/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/1.1/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<afTZmG0U0aOVnvuW@tucnak>","date":"2026-05-01T16:49:28","name":"c, c++, v3: Introduce -Wconstant-logical-operand warning [PR125081]","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"c2f50dfa3ece8d2a7c29a2e3c3f73b20333ec601","submitter":{"id":671,"url":"http://patchwork.ozlabs.org/api/1.1/people/671/?format=json","name":"Jakub Jelinek","email":"jakub@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/afTZmG0U0aOVnvuW@tucnak/mbox/","series":[{"id":502485,"url":"http://patchwork.ozlabs.org/api/1.1/series/502485/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=502485","date":"2026-05-01T16:49:28","name":"c, c++, v3: Introduce -Wconstant-logical-operand warning [PR125081]","version":1,"mbox":"http://patchwork.ozlabs.org/series/502485/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2231959/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2231959/checks/","tags":{},"headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=QH+tPu5a;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=QH+tPu5a","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.129.124"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g6cTz261fz1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 02 May 2026 02:50:13 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id B99B044115D0\n\tfor <incoming@patchwork.ozlabs.org>; Fri,  1 May 2026 16:50:11 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by sourceware.org (Postfix) with ESMTP id C8F8043B5511\n for <gcc-patches@gcc.gnu.org>; Fri,  1 May 2026 16:49:34 +0000 (GMT)","from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-549-BsCMgMXoOAayJCOW4j-gSw-1; Fri,\n 01 May 2026 12:49:33 -0400","from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 29FAB1800364\n for <gcc-patches@gcc.gnu.org>; Fri,  1 May 2026 16:49:32 +0000 (UTC)","from tucnak.zalov.cz (unknown [10.44.34.21])\n by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id 486921800446; Fri,  1 May 2026 16:49:31 +0000 (UTC)","from tucnak.zalov.cz (localhost [127.0.0.1])\n by tucnak.zalov.cz (8.18.1/8.18.1) with ESMTPS id 641GnSDJ2677898\n (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT);\n Fri, 1 May 2026 18:49:28 +0200","(from jakub@localhost)\n by tucnak.zalov.cz (8.18.1/8.18.1/Submit) id 641GnSW22677897;\n Fri, 1 May 2026 18:49:28 +0200"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org B99B044115D0","OpenDKIM Filter v2.11.0 sourceware.org C8F8043B5511"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org C8F8043B5511","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org C8F8043B5511","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777654174; cv=none;\n b=AYZoJs0pxFoIfv1U/8GnQy6HVKtvuBV3hp9TSmR/mVRxyiLqnzxUQQUP+G4M5Rv2GkcfzJun/2aSHGDvdyFCvqsfQIO5z3nXXbVdvATHIvcYUFLZ4CgUokxD9hrytCYb+v4FAhBqMEGuiNcEawxsyF45Brfgj9UEnqg0r25qnuY=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777654174; c=relaxed/simple;\n bh=5YsR7kTPApb4mScJp6hrfVR1fSt0kChCH6PpD7l9gx8=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=RlqNBOBgcGgmx+YJaJfmBrqgTAZD4NfrGU2bi2OPRuKq96zMHOG8PopF7bS6qAcQfxRPI3W2DLCo7KPcivmpnyYpsuY/h/XCAYJbJP9ZsQ7YTMe7FeKB9FjkE4Sbcm1OYP3Xm8apZ87sdd92ZgvGdmSzI2FcVcU0OW+Ge+MqTls=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1777654174;\n h=from:from:reply-to:reply-to:subject:subject:date:date:\n message-id:message-id:to:to:cc:cc:mime-version:mime-version:\n content-type:content-type:in-reply-to:in-reply-to:  references:references;\n bh=6sLsDgA91SW32PhPOCzmkGRbkF0Nv6XHgW07QsUzyig=;\n b=QH+tPu5aTYn2yyu1++gpkNicsjj50znGPsqt5If2yWRdd4O0Odw4MMDL5/U4Y9l2aWVNab\n ioGbkg82I4u6B1Zf9qSV+PhqiLZT0hOTgb2DEHZPsJP7cWXiVk8B9wGPnx2hzWDGZg7k6h\n UB7+PpEG71yX/XaxW8fm1ryQW4c/fDY=","X-MC-Unique":"BsCMgMXoOAayJCOW4j-gSw-1","X-Mimecast-MFC-AGG-ID":"BsCMgMXoOAayJCOW4j-gSw_1777654172","Date":"Fri, 1 May 2026 18:49:28 +0200","From":"Jakub Jelinek <jakub@redhat.com>","To":"Jason Merrill <jason@redhat.com>, \"Joseph S. Myers\" <josmyers@redhat.com>,\n Marek Polacek <polacek@redhat.com>","Cc":"gcc-patches@gcc.gnu.org","Subject":"[PATCH] c, c++, v3: Introduce -Wconstant-logical-operand warning\n [PR125081]","Message-ID":"<afTZmG0U0aOVnvuW@tucnak>","References":"<afMPwPZBZlyCU7TG@tucnak>\n <8d188ded-0e3a-426d-b3ef-6357cc98440f@redhat.com>\n <afNwI0F3WFI9i1bL@tucnak>\n <9acfb25a-8cb0-45f1-8059-d959d8e88b2a@redhat.com>\n <afO3cl6JJrYYVMVu@tucnak>\n <44d8281e-6529-4844-95fe-70edea1a4a70@redhat.com>","MIME-Version":"1.0","In-Reply-To":"<44d8281e-6529-4844-95fe-70edea1a4a70@redhat.com>","X-Scanned-By":"MIMEDefang 3.4.1 on 10.30.177.111","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"ZgiQFYmk2l3JRbFQMWNbqbcfmioytSh7J4sEbxuO51E_1777654172","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Reply-To":"Jakub Jelinek <jakub@redhat.com>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"},"content":"On Fri, May 01, 2026 at 11:54:25AM -0400, Jason Merrill wrote:\n> This could also be factored into a lambda, rather than repeated?  The C++\n> changes are OK either way.\n\nGood idea.  Here is what I'll retest tonight (made it a lambda for both C\nand C++ FEs).\n\n2026-05-01  Jakub Jelinek  <jakub@redhat.com>\n\n\tPR c++/125081\ngcc/doc/\n\t* invoke.texi (Wconstant-logical-operand): Document.\ngcc/c-family/\n\t* c.opt (Wconstant-logical-operand): New option.\n\t* c.opt.urls: Regenerate.\ngcc/c/\n\t* c-tree.h (parser_build_binary_op): Add ORIG_ARG1 argument.\n\t* c-typeck.cc (parser_build_binary_op): Likewise.  Emit\n\t-Wconstant-logical-operand warnings.\n\t* c-parser.cc (c_parser_binary_expression): Adjust\n\tparser_build_binary_op caller, pass to it the original\n\tstack[sp - 1].expr.value before c_objc_common_truthvalue_conversion.\ngcc/cp/\n\t* typeck.cc (cp_build_binary_op): Emit -Wconstant-logical-operand\n\twarnings.\n\t* c-c++-common/Wconstant-logical-operand-1.c: New test.\n\t* c-c++-common/Wconstant-logical-operand-2.c: New test.\n\n\n\n\tJakub","diff":"--- gcc/doc/invoke.texi.jj\t2026-05-01 08:32:06.568296638 +0200\n+++ gcc/doc/invoke.texi\t2026-05-01 18:01:47.677452253 +0200\n@@ -385,7 +385,7 @@ Objective-C and Objective-C++ Dialects}.\n -Wchar-subscripts\n -Wclobbered  -Wcomment\n -Wcompare-distinct-pointer-types\n--Wno-complain-wrong-lang\n+-Wno-complain-wrong-lang  -Wconstant-logical-operand\n -Wconversion  -Wno-coverage-mismatch  -Wno-cpp\n -Wdangling-else  -Wdangling-pointer  -Wdangling-pointer=@var{n}\n -Wdate-time\n@@ -10647,6 +10647,22 @@ extern int a;\n if (a < 0 && a < 0) @{ @dots{} @}\n @end smallexample\n \n+@opindex Wconstant-logical-operand\n+@opindex Wno-constant-logical-operand\n+@item -Wconstant-logical-operand\n+Warn about another case of suspicious uses of logical operators in\n+expressions, when neither operand of a logical operator is boolean\n+and one of the operands is (or folds into) a constant other than 0 or 1,\n+or enumerator with value 1 if the enumeral type contains enumerators with\n+values other than 0 or 1.\n+In such case the warning will suggest using corresponding bitwise operator.\n+@smallexample\n+extern int a;\n+if (a && 64) @{ @dots{} @}\n+@end smallexample\n+If the warning is a false positive, one can clarify the code by using\n+e.g. @code{a && 64 != 0} instead.\n+\n @opindex Wlogical-not-parentheses\n @opindex Wno-logical-not-parentheses\n @item -Wlogical-not-parentheses\n--- gcc/c-family/c.opt.jj\t2026-05-01 08:32:06.541297102 +0200\n+++ gcc/c-family/c.opt\t2026-05-01 18:01:47.678956153 +0200\n@@ -595,6 +595,10 @@ Wconditionally-supported\n C++ ObjC++ Var(warn_conditionally_supported) Warning\n Warn for conditionally-supported constructs.\n \n+Wconstant-logical-operand\n+C ObjC C++ ObjC++ Var(warn_constant_logical_operand) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)\n+Warn for constant operands of logical operators other than 0 or 1.\n+\n Wconversion\n C ObjC C++ ObjC++ Var(warn_conversion) Warning\n Warn for implicit type conversions that may change a value.\n--- gcc/c-family/c.opt.urls.jj\t2026-05-01 08:32:06.544297050 +0200\n+++ gcc/c-family/c.opt.urls\t2026-05-01 18:01:47.679211324 +0200\n@@ -415,6 +415,9 @@ UrlSuffix(gcc/Warning-Options.html#index\n Wconditionally-supported\n UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wconditionally-supported)\n \n+Wconstant-logical-operand\n+UrlSuffix(gcc/Warning-Options.html#index-Wconstant-logical-operand)\n+\n Wconversion\n UrlSuffix(gcc/Warning-Options.html#index-Wconversion) LangUrlSuffix_Fortran(gfortran/Error-and-Warning-Options.html#index-Wconversion)\n \n--- gcc/c/c-typeck.cc.jj\t2026-05-01 08:32:06.558296810 +0200\n+++ gcc/c/c-typeck.cc\t2026-05-01 18:07:09.140112204 +0200\n@@ -5112,13 +5112,15 @@ char_type_p (tree type)\n    in the input.  CODE, a tree_code, specifies the binary operator, and\n    ARG1 and ARG2 are the operands.  In addition to constructing the\n    expression, we check for operands that were written with other binary\n-   operators in a way that is likely to confuse the user.\n+   operators in a way that is likely to confuse the user.  ORIG_ARG1 is\n+   the original first operand for TRUTH_{AND,OR}IF_EXPR before it is\n+   converted to truth value, otherwise NULL_TREE.\n \n    LOCATION is the location of the binary operator.  */\n \n struct c_expr\n parser_build_binary_op (location_t location, enum tree_code code,\n-\t\t\tstruct c_expr arg1, struct c_expr arg2)\n+\t\t\tstruct c_expr arg1, struct c_expr arg2, tree orig_arg1)\n {\n   struct c_expr result;\n   result.m_decimal = 0;\n@@ -5163,6 +5165,47 @@ parser_build_binary_op (location_t locat\n     warn_logical_operator (location, code, TREE_TYPE (result.value),\n \t\t\t   code1, arg1.value, code2, arg2.value);\n \n+  if (warn_constant_logical_operand\n+      && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)\n+      && (TREE_CODE (type1) == INTEGER_TYPE\n+\t  || TREE_CODE (type1) == ENUMERAL_TYPE\n+\t  || TREE_CODE (type1) == BITINT_TYPE)\n+      && (TREE_CODE (type2) == INTEGER_TYPE\n+\t  || TREE_CODE (type2) == ENUMERAL_TYPE\n+\t  || TREE_CODE (type2) == BITINT_TYPE))\n+    {\n+      const char *name = code == TRUTH_ANDIF_EXPR ? \"&&\" : \"||\";\n+      if (orig_arg1 == NULL_TREE)\n+\torig_arg1 = arg1.value;\n+      auto enum_other_than_0_1 = [] (tree type) {\n+\tif (TREE_CODE (type) != ENUMERAL_TYPE)\n+\t  return false;\n+\tfor (tree l = TYPE_VALUES (type); l; l = TREE_CHAIN (l))\n+\t  {\n+\t    tree v = DECL_INITIAL (TREE_VALUE (l));\n+\t    if (!integer_zerop (v) && !integer_onep (v))\n+\t      return true;\n+\t  }\n+\treturn false;\n+      };\n+      auto diagnose_constant_logical_operand = [=] (tree val, tree type) {\n+\tif (TREE_CODE (val) != INTEGER_CST || integer_zerop (val))\n+\t  return false;\n+\tif (integer_onep (val) && !enum_other_than_0_1 (type))\n+\t  return false;\n+\tgcc_rich_location richloc (location);\n+\trichloc.add_fixit_replace (name + 1);\n+\tauto_diagnostic_group d;\n+\tif (warning_at (location, OPT_Wconstant_logical_operand,\n+\t\t\t\"use of logical %qs with constant operand %qE\",\n+\t\t\tname, val))\n+\t  inform (&richloc, \"use %qs for bitwise operation\", name + 1);\n+\treturn true;\n+      };\n+      if (!diagnose_constant_logical_operand (arg2.value, type2))\n+\tdiagnose_constant_logical_operand (orig_arg1, type1);\n+    }\n+\n   if (warn_tautological_compare)\n     {\n       tree lhs = arg1.value;\n--- gcc/c/c-parser.cc.jj\t2026-05-01 08:32:06.553296896 +0200\n+++ gcc/c/c-parser.cc\t2026-05-01 18:01:47.681792212 +0200\n@@ -10304,6 +10304,9 @@ c_parser_binary_expression (c_parser *pa\n     location_t loc;\n     /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR.  */\n     tree sizeof_arg;\n+    /* The original expr.value before c_objc_common_truthvalue_conversion\n+       for TRUTH_{AND,OR}*_EXPR lhs operands.  */\n+    tree orig_expr;\n   } stack[NUM_PRECS];\n   int sp;\n   /* Location of the binary operator.  */\n@@ -10399,7 +10402,9 @@ c_parser_binary_expression (c_parser *pa\n       stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,\t      \\\n \t\t\t\t\t\t   stack[sp].op,\t      \\\n \t\t\t\t\t\t   stack[sp - 1].expr,\t      \\\n-\t\t\t\t\t\t   stack[sp].expr);\t      \\\n+\t\t\t\t\t\t   stack[sp].expr,\t      \\\n+\t\t\t\t\t\t   stack[sp - 1].orig_expr);  \\\n+    stack[sp - 1].orig_expr = NULL_TREE;\t\t\t\t      \\\n     sp--;\t\t\t\t\t\t\t\t      \\\n   } while (0)\n   gcc_assert (!after || c_dialect_objc ());\n@@ -10407,6 +10412,7 @@ c_parser_binary_expression (c_parser *pa\n   stack[0].expr = c_parser_cast_expression (parser, after);\n   stack[0].prec = PREC_NONE;\n   stack[0].sizeof_arg = c_last_sizeof_arg;\n+  stack[0].orig_expr = NULL_TREE;\n   sp = 0;\n   while (true)\n     {\n@@ -10505,6 +10511,7 @@ c_parser_binary_expression (c_parser *pa\n \t  stack[sp].expr\n \t    = convert_lvalue_to_rvalue (stack[sp].loc,\n \t\t\t\t\tstack[sp].expr, true, true);\n+\t  stack[sp].orig_expr = stack[sp].expr.value;\n \t  stack[sp].expr.value = c_objc_common_truthvalue_conversion\n \t    (stack[sp].loc, default_conversion (stack[sp].expr.value));\n \t  c_inhibit_evaluation_warnings += (stack[sp].expr.value\n@@ -10516,6 +10523,7 @@ c_parser_binary_expression (c_parser *pa\n \t  stack[sp].expr\n \t    = convert_lvalue_to_rvalue (stack[sp].loc,\n \t\t\t\t\tstack[sp].expr, true, true);\n+\t  stack[sp].orig_expr = stack[sp].expr.value;\n \t  stack[sp].expr.value = c_objc_common_truthvalue_conversion\n \t    (stack[sp].loc, default_conversion (stack[sp].expr.value));\n \t  c_inhibit_evaluation_warnings += (stack[sp].expr.value\n@@ -10531,6 +10539,7 @@ c_parser_binary_expression (c_parser *pa\n       stack[sp].prec = oprec;\n       stack[sp].op = ocode;\n       stack[sp].sizeof_arg = c_last_sizeof_arg;\n+      stack[sp].orig_expr = NULL_TREE;\n     }\n  out:\n   while (sp > 0)\n--- gcc/c/c-tree.h.jj\t2026-05-01 08:32:06.553296896 +0200\n+++ gcc/c/c-tree.h\t2026-05-01 18:01:47.683085944 +0200\n@@ -890,7 +890,7 @@ extern struct c_expr parser_build_unary_\n     \t\t\t\t\t    struct c_expr);\n extern struct c_expr parser_build_binary_op (location_t,\n     \t\t\t\t\t     enum tree_code, struct c_expr,\n-\t\t\t\t\t     struct c_expr);\n+\t\t\t\t\t     struct c_expr, tree);\n extern tree build_conditional_expr (location_t, tree, bool, tree, tree,\n \t\t\t\t    location_t, tree, tree, location_t);\n extern tree build_compound_expr (location_t, tree, tree);\n--- gcc/cp/typeck.cc.jj\t2026-05-01 08:32:06.562296741 +0200\n+++ gcc/cp/typeck.cc\t2026-05-01 18:08:40.955586883 +0200\n@@ -5953,6 +5953,44 @@ cp_build_binary_op (const op_location_t\n \t  return cp_build_binary_op (location, code, op0, op1, complain);\n \t}\n \n+      if (warn_constant_logical_operand\n+\t  && (complain & tf_warning)\n+\t  && (code0 == INTEGER_TYPE || code0 == ENUMERAL_TYPE)\n+\t  && (code1 == INTEGER_TYPE || code1 == ENUMERAL_TYPE))\n+\t{\n+\t  tree cop0 = fold_for_warn (op0), cop1 = fold_for_warn (op1);\n+\t  const char *name\n+\t    = ((code == TRUTH_ANDIF_EXPR || code == TRUTH_AND_EXPR)\n+\t       ? \"&&\" : \"||\");\n+\t  auto enum_other_than_0_1 = [] (tree type) {\n+\t    if (TREE_CODE (type) != ENUMERAL_TYPE)\n+\t      return false;\n+\t    for (tree l = TYPE_VALUES (type); l; l = TREE_CHAIN (l))\n+\t      {\n+\t\ttree v = DECL_INITIAL (TREE_VALUE (l));\n+\t\tif (!integer_zerop (v) && !integer_onep (v))\n+\t\t  return true;\n+\t      }\n+\t    return false;\n+\t  };\n+\t  auto diagnose_constant_logical_operand = [=] (tree val, tree type) {\n+\t    if (TREE_CODE (val) != INTEGER_CST || integer_zerop (val))\n+\t      return false;\n+\t    if (integer_onep (val) && !enum_other_than_0_1 (type))\n+\t      return false;\n+\t    gcc_rich_location richloc (location);\n+\t    richloc.add_fixit_replace (name + 1);\n+\t    auto_diagnostic_group d;\n+\t    if (warning_at (location, OPT_Wconstant_logical_operand,\n+\t\t\t    \"use of logical %qs with constant operand %qE\",\n+\t\t\t    name, val))\n+\t      inform (&richloc, \"use %qs for bitwise operation\", name + 1);\n+\t    return true;\n+\t  };\n+\t  if (!diagnose_constant_logical_operand (cop1, orig_type1))\n+\t    diagnose_constant_logical_operand (cop0, orig_type0);\n+\t}\n+\n       result_type = boolean_type_node;\n       break;\n \n--- gcc/testsuite/c-c++-common/Wconstant-logical-operand-1.c.jj\t2026-05-01 18:01:47.684201405 +0200\n+++ gcc/testsuite/c-c++-common/Wconstant-logical-operand-1.c\t2026-05-01 18:01:47.684201405 +0200\n@@ -0,0 +1,106 @@\n+/* PR c++/125081 */\n+/* { dg-do compile } */\n+/* { dg-options \"-std=c23\" { target c } } */\n+/* { dg-additional-options \"-Wconstant-logical-operand\" } */\n+\n+void foo (int);\n+enum A { B, C };\n+enum D { E, F, G, H, I };\n+\n+void\n+bar (int x, bool y)\n+{\n+  if (x && 64)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '64'\" } */\n+    foo (1);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (128 && x)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '128'\" } */\n+    foo (2);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x && 1)\n+    foo (3);\n+  if (1 && x)\n+    foo (4);\n+  if (x && 0)\n+    foo (5);\n+  if (0 && x)\n+    foo (6);\n+  if (x || 32)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '32'\" } */\n+    foo (7);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (256 || x)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '256'\" } */\n+    foo (8);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x || 1)\n+    foo (9);\n+  if (1 || x)\n+    foo (10);\n+  if (x || 0)\n+    foo (11);\n+  if (0 || x)\n+    foo (12);\n+  if (y && 64)\n+    foo (13);\n+  if (128 && y)\n+    foo (14);\n+  if (y || 32)\n+    foo (15);\n+  if (256 || y)\n+    foo (16);\n+  if (x && B)\n+    foo (17);\n+  if (B && x)\n+    foo (18);\n+  if (x && C)\n+    foo (19);\n+  if (C && x)\n+    foo (20);\n+  if (x && E)\n+    foo (21);\n+  if (E && x)\n+    foo (22);\n+  if (x && F)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '\\[1F]'\" } */\n+    foo (23);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (F && x)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '\\[1F]'\" } */\n+    foo (24);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x && G)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '\\[2G]'\" } */\n+    foo (25);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (G && x)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '\\[2G]'\" } */\n+    foo (26);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x || B)\n+    foo (27);\n+  if (B || x)\n+    foo (28);\n+  if (x || C)\n+    foo (29);\n+  if (C || x)\n+    foo (30);\n+  if (x || E)\n+    foo (31);\n+  if (E || x)\n+    foo (32);\n+  if (x || F)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '\\[1F]'\" } */\n+    foo (33);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (F || x)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '\\[1F]'\" } */\n+    foo (34);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x || G)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '\\[2G]'\" } */\n+    foo (35);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (G || x)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '\\[2G]'\" } */\n+    foo (36);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+}\n+\n+void\n+baz (int x, bool y)\n+{\n+  if (x && 63 + 1)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '64'\" } */\n+    foo (1);\t\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (127 + 1 && x)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '128'\" } */\n+    foo (2);\t\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x || 31 + 1)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '32'\" } */\n+    foo (7);\t\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (255 + 1 || x)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '256'\" } */\n+    foo (8);\t\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (y && 63 + 1)\n+    foo (13);\n+  if (127 + 1 && y)\n+    foo (14);\n+  if (y || 31 + 1)\n+    foo (15);\n+  if (255 + 1 || y)\n+    foo (16);\n+}\n--- gcc/testsuite/c-c++-common/Wconstant-logical-operand-2.c.jj\t2026-05-01 18:01:47.684304880 +0200\n+++ gcc/testsuite/c-c++-common/Wconstant-logical-operand-2.c\t2026-05-01 18:01:47.684304880 +0200\n@@ -0,0 +1,110 @@\n+/* PR c++/125081 */\n+/* { dg-do compile } */\n+/* { dg-options \"-std=c23\" { target c } } */\n+/* { dg-additional-options \"-Wall\" } */\n+\n+void foo (int);\n+enum A { B, C };\n+enum D { E, F, G, H, I };\n+\n+void\n+bar (int x, bool y)\n+{\n+  if (x && 64)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '64'\" } */\n+    foo (1);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (128 && x)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '128'\" } */\n+    foo (2);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x && 1)\n+    foo (3);\n+  if (1 && x)\n+    foo (4);\n+  if (x && 0)\n+    foo (5);\n+  if (0 && x)\n+    foo (6);\n+  if (x || 32)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '32'\" } */\n+    foo (7);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (256 || x)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '256'\" } */\n+    foo (8);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x || 1)\n+    foo (9);\n+  if (1 || x)\n+    foo (10);\n+  if (x || 0)\n+    foo (11);\n+  if (0 || x)\n+    foo (12);\n+  if (y && 64)\n+    foo (13);\n+  if (128 && y)\n+    foo (14);\n+  if (y || 32)\n+    foo (15);\n+  if (256 || y)\n+    foo (16);\n+  if (x && B)\n+    foo (17);\n+  if (B && x)\n+    foo (18);\n+  if (x && C)\n+    foo (19);\n+  if (C && x)\n+    foo (20);\n+  if (x && E)\n+    foo (21);\n+  if (E && x)\n+    foo (22);\n+  if (x && F)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '\\[1F]'\" } */\n+    foo (23);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (F && x)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '\\[1F]'\" } */\n+    foo (24);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x && G)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '\\[2G]'\" } */\n+    foo (25);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+\t\t/* { dg-warning \"enum constant in boolean context\" \"\" { target c++ } .-2 } */\n+  if (G && x)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '\\[2G]'\" } */\n+    foo (26);\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+\t\t/* { dg-warning \"enum constant in boolean context\" \"\" { target c++ } .-2 } */\n+  if (x || B)\n+    foo (27);\n+  if (B || x)\n+    foo (28);\n+  if (x || C)\n+    foo (29);\n+  if (C || x)\n+    foo (30);\n+  if (x || E)\n+    foo (31);\n+  if (E || x)\n+    foo (32);\n+  if (x || F)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '\\[1F]'\" } */\n+    foo (33);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (F || x)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '\\[1F]'\" } */\n+    foo (34);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x || G)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '\\[2G]'\" } */\n+    foo (35);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+\t\t/* { dg-warning \"enum constant in boolean context\" \"\" { target c++ } .-2 } */\n+  if (G || x)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '\\[2G]'\" } */\n+    foo (36);\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+\t\t/* { dg-warning \"enum constant in boolean context\" \"\" { target c++ } .-2 } */\n+}\n+\n+void\n+baz (int x, bool y)\n+{\n+  if (x && 63 + 1)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '64'\" } */\n+    foo (1);\t\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (127 + 1 && x)\t/* { dg-warning \"use of logical '\\\\\\&\\\\\\&' with constant operand '128'\" } */\n+    foo (2);\t\t/* { dg-message \"note: use '\\\\\\&' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (x || 31 + 1)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '32'\" } */\n+    foo (7);\t\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (255 + 1 || x)\t/* { dg-warning \"use of logical '\\\\\\|\\\\\\|' with constant operand '256'\" } */\n+    foo (8);\t\t/* { dg-message \"note: use '\\\\\\|' for bitwise operation\" \"\" { target *-*-* } .-1 } */\n+  if (y && 63 + 1)\n+    foo (13);\n+  if (127 + 1 && y)\n+    foo (14);\n+  if (y || 31 + 1)\n+    foo (15);\n+  if (255 + 1 || y)\n+    foo (16);\n+}\n","prefixes":[]}