Hi!

The -Wunused-but-set-* warnings work by using 2 bits on VAR_DECLs &
PARM_DECLs, TREE_USED and DECL_READ_P.  If neither is set, we typically
emit -Wunused-variable or -Wunused-parameter warning, that is for variables
which are just declared (including initializer) and completely unused.
If TREE_USED is set and DECL_READ_P is unset, -Wunused-but-set-* warnings
are emitted, i.e. for variables which can appear on the lhs of an assignment
expression but aren't actually used elsewhere.  The DECL_READ_P marking is
done through mark_exp_read called from lots of places (e.g. lvalue to rvalue
conversions etc.).

LLVM has an extension on top of that in that it doesn't count pre/post
inc/decrements as use (i.e. DECL_READ_P for GCC).

The following patch does that too, though because we had the current
behavior for 11+ years already and lot of people is -Wunused-but-set-*
warning free in the current GCC behavior and not in the clang one (including
GCC sources), it allows users to choose.
Furthermore, it implements another level, where also var @= expr uses of var
(except when it is also used in expr) aren't counted as DECL_READ_P.

I think it would be nice to also handle var = var @ expr or var = expr @ var
but unfortunately mark_exp_read is then done in both FEs during parsing of
var @ expr or expr @ var and the code doesn't know it is rhs of an
assignment with var as lhs.

The patch works mostly by checking if DECL_READ_P is clear at some point and
then clearing it again after some operation which might have set it.

-Wunused or -Wall or -Wunused -Wextra or -Wall -Wextra turn on the 3 level
of the new warning (i.e. the one which ignores also var++, ++var etc. as
well as var @= expr), so does -Wunused-but-set-{variable,parameter}, but
users can use explicit -Wunused-but-set-{variable,parameter}={1,2} to select
a different level.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Though, I'm afraid the gofrontend part will need to go in separately through
upstream.

2025-04-24  Jakub Jelinek  <ja...@redhat.com>

        PR c/44677
gcc/
        * common.opt (Wunused-but-set-parameter=, Wunused-but-set-variable=):
        New options.
        (Wunused-but-set-parameter, Wunused-but-set-variable): Turn into
        aliases.
        * common.opt.urls: Regenerate.
        * diagnostic-spec.cc (nowarn_spec_t::nowarn_spec_t): Use
        OPT_Wunused_but_set_variable_ instead of OPT_Wunused_but_set_variable
        and OPT_Wunused_but_set_parameter_ instead of
        OPT_Wunused_but_set_parameter.
        * gimple-ssa-store-merging.cc (find_bswap_or_nop_1): Remove unused
        but set variable tmp.
        * ipa-strub.cc (pass_ipa_strub::execute): Cast named_args to
        (void) if ATTR_FNSPEC_DECONST_WATERMARK is not defined.
        * doc/invoke.texi (Wunused-but-set-parameter=,
        Wunused-but-set-variable=): Document new options.
        (Wunused-but-set-parameter, Wunused-but-set-variable): Adjust
        documentation now that they are just aliases.
gcc/c-family/
        * c-opts.cc (c_common_post_options): Change
        warn_unused_but_set_parameter and warn_unused_but_set_variable
        from 1 to 3 if they were set only implicitly.
        * c-attribs.cc (build_attr_access_from_parms): Remove unused
        but set variable nelts.
gcc/c/
        * c-parser.cc (c_parser_unary_expression): Clear DECL_READ_P
        after default_function_array_read_conversion for
        -Wunused-but-set-{parameter,variable}={2,3} on
        PRE{IN,DE}CREMENT_EXPR argument.
        (c_parser_postfix_expression_after_primary): Similarly for
        POST{IN,DE}CREMENT_EXPR.
        * c-decl.cc (pop_scope): Use OPT_Wunused_but_set_variable_
        instead of OPT_Wunused_but_set_variable.
        (finish_function): Use OPT_Wunused_but_set_parameter_
        instead of OPT_Wunused_but_set_parameter.
        * c-typeck.cc (mark_exp_read): Handle {PRE,POST}{IN,DE}CREMENT_EXPR
        and don't handle it when cast to void.
        (build_modify_expr): Clear DECL_READ_P after build_binary_op
        for -Wunused-but-set-{parameter,variable}=3.
gcc/cp/
        * cp-gimplify.cc (cp_fold): Clear DECL_READ_P after cp_fold_rvalue
        for x = x OP y.
        * decl.cc (poplevel): Use OPT_Wunused_but_set_variable_
        instead of OPT_Wunused_but_set_variable.
        (finish_function): Use OPT_Wunused_but_set_parameter_
        instead of OPT_Wunused_but_set_parameter.
        * expr.cc (mark_use): Clear read_p for {PRE,POST}{IN,DE}CREMENT_EXPR
        cast to void on {VAR,PARM}_DECL for
        -Wunused-but-set-{parameter,variable}={2,3}.
        (mark_exp_read): Handle {PRE,POST}{IN,DE}CREMENT_EXPR and don't handle
        it when cast to void.
        * module.cc (trees_in::fn_parms_fini): Remove unused but set variable
        ix.
        * semantics.cc (finish_unary_op_expr): Clear DECL_READ_P
        after cp_fully_fold for -Wunused-but-set-{parameter,variable}={2,3} on
        PRE{IN,DE}CREMENT_EXPR argument.
        * typeck.cc (cp_build_unary_op): Clear DECL_READ_P
        after mark_lvalue_use for -Wunused-but-set-{parameter,variable}={2,3}
        on PRE{IN,DE}CREMENT_EXPR argument.
        (cp_build_modify_expr): Clear DECL_READ_P after cp_build_binary_op
        for -Wunused-but-set-{parameter,variable}=3.
gcc/go/
        * gofrontend/gogo.cc (Function::export_func_with_type): Remove
        unused but set variable i.
gcc/testsuite/
        * c-c++-common/Wunused-parm-1.c: New test.
        * c-c++-common/Wunused-parm-2.c: New test.
        * c-c++-common/Wunused-parm-3.c: New test.
        * c-c++-common/Wunused-parm-4.c: New test.
        * c-c++-common/Wunused-parm-5.c: New test.
        * c-c++-common/Wunused-parm-6.c: New test.
        * c-c++-common/Wunused-var-7.c (bar, baz): Expect warning on a.
        * c-c++-common/Wunused-var-19.c: New test.
        * c-c++-common/Wunused-var-20.c: New test.
        * c-c++-common/Wunused-var-21.c: New test.
        * c-c++-common/Wunused-var-22.c: New test.
        * c-c++-common/Wunused-var-23.c: New test.
        * c-c++-common/Wunused-var-24.c: New test.
        * g++.dg/cpp26/name-independent-decl1.C (foo): Expect one
        set but not used warning.
        * g++.dg/warn/Wunused-parm-12.C: New test.
        * g++.dg/warn/Wunused-parm-13.C: New test.
        * g++.dg/warn/Wunused-var-2.C (f2): Expect set but not used warning
        on parameter x and variable a.
        * g++.dg/warn/Wunused-var-40.C: New test.
        * g++.dg/warn/Wunused-var-41.C: New test.
        * gcc.dg/memchr-3.c (test_find): Change return type from void to int,
        and add return n; statement.
        * gcc.dg/unused-9.c (g): Move dg-bogus to the correct line and expect
        a warning on i.

--- gcc/common.opt.jj   2025-04-15 21:43:05.029214497 +0200
+++ gcc/common.opt      2025-04-23 21:33:19.025931935 +0200
@@ -853,11 +853,17 @@ Common Var(warn_unused) Init(0) Warning
 Enable all -Wunused- warnings.
 
 Wunused-but-set-parameter
-Common Var(warn_unused_but_set_parameter) Warning EnabledBy(Wunused && Wextra)
+Common Alias(Wunused-but-set-parameter=,3,0) Warning
+
+Wunused-but-set-parameter=
+Common Var(warn_unused_but_set_parameter) RejectNegative Joined UInteger 
Warning IntegerRange(0, 3) EnabledBy(Wunused && Wextra)
 Warn when a function parameter is only set, otherwise unused.
 
 Wunused-but-set-variable
-Common Var(warn_unused_but_set_variable) Warning EnabledBy(Wunused)
+Common Alias(Wunused-but-set-variable=,3,0) Warning
+
+Wunused-but-set-variable=
+Common Var(warn_unused_but_set_variable) RejectNegative Joined UInteger 
Warning IntegerRange(0, 3) EnabledBy(Wunused)
 Warn when a variable is only set, otherwise unused.
 
 Wunused-function
--- gcc/common.opt.urls.jj      2025-04-17 10:56:43.093328861 +0200
+++ gcc/common.opt.urls 2025-04-24 08:23:26.958220151 +0200
@@ -269,9 +269,15 @@ UrlSuffix(gcc/Warning-Options.html#index
 Wunused-but-set-parameter
 UrlSuffix(gcc/Warning-Options.html#index-Wno-unused-but-set-parameter)
 
+Wunused-but-set-parameter=
+UrlSuffix(gcc/Warning-Options.html#index-Wno-unused-but-set-parameter)
+
 Wunused-but-set-variable
 UrlSuffix(gcc/Warning-Options.html#index-Wno-unused-but-set-variable)
 
+Wunused-but-set-variable=
+UrlSuffix(gcc/Warning-Options.html#index-Wno-unused-but-set-variable)
+
 Wunused-function
 UrlSuffix(gcc/Warning-Options.html#index-Wno-unused-function)
 
--- gcc/diagnostic-spec.cc.jj   2025-01-02 20:54:32.122130018 +0100
+++ gcc/diagnostic-spec.cc      2025-04-23 21:33:19.026931922 +0200
@@ -72,9 +72,9 @@ nowarn_spec_t::nowarn_spec_t (opt_code o
     case OPT_Wstrict_aliasing:
     case OPT_Wunused:
     case OPT_Wunused_function:
-    case OPT_Wunused_but_set_variable:
+    case OPT_Wunused_but_set_variable_:
     case OPT_Wunused_variable:
-    case OPT_Wunused_but_set_parameter:
+    case OPT_Wunused_but_set_parameter_:
       m_bits = NW_LEXICAL;
       break;
 
--- gcc/gimple-ssa-store-merging.cc.jj  2025-01-02 20:54:32.239128399 +0100
+++ gcc/gimple-ssa-store-merging.cc     2025-04-23 23:16:06.760754906 +0200
@@ -644,9 +644,7 @@ find_bswap_or_nop_1 (gimple *stmt, struc
 
          /* Mask.  */
          uint64_t mask = 0;
-         uint64_t tmp = (1 << BITS_PER_UNIT) - 1;
-         for (unsigned i = 0; i < bitsize / BITS_PER_UNIT;
-              i++, tmp <<= BITS_PER_UNIT)
+         for (unsigned i = 0; i < bitsize / BITS_PER_UNIT; i++)
            mask |= (uint64_t) MARKER_MASK << (i * BITS_PER_MARKER);
          n->n &= mask;
 
--- gcc/ipa-strub.cc.jj 2025-01-02 20:54:32.266128025 +0100
+++ gcc/ipa-strub.cc    2025-04-24 00:02:57.347838302 +0200
@@ -3060,6 +3060,8 @@ pass_ipa_strub::execute (function *)
                         TYPE_ATTRIBUTES (TREE_TYPE (nnode->decl)));
        }
     }
+#else
+    (void) named_args;
 #endif
 
     {
--- gcc/doc/invoke.texi.jj      2025-04-23 21:32:50.747306995 +0200
+++ gcc/doc/invoke.texi 2025-04-23 21:33:19.031931856 +0200
@@ -433,7 +433,8 @@ Objective-C and Objective-C++ Dialects}.
 -Wunsuffixed-float-constants
 -Wunterminated-string-initialization
 -Wunused
--Wunused-but-set-parameter  -Wunused-but-set-variable
+-Wunused-but-set-parameter  -Wunused-but-set-parameter=@var{n}
+-Wunused-but-set-variable  -Wunused-but-set-variable=@var{n}
 -Wunused-const-variable  -Wunused-const-variable=@var{n}
 -Wunused-function  -Wunused-label  -Wunused-local-typedefs
 -Wunused-macros
@@ -7781,27 +7782,89 @@ statement.
 @opindex Wunused-but-set-parameter
 @opindex Wno-unused-but-set-parameter
 @item -Wunused-but-set-parameter
+@option{-Wunused-but-set-parameter} is the same as
+@option{-Wunused-but-set-parameter=3} and
+@option{-Wno-unused-but-set-parameter} is the same as
+@option{-Wunused-but-set-parameter=0}.
+
+@opindex Wunused-but-set-parameter=
+@item -Wunused-but-set-parameter=@var{n}
 Warn whenever a function parameter is assigned to, but otherwise unused
 (aside from its declaration).
 
 To suppress this warning use the @code{unused} attribute
 (@pxref{Variable Attributes}).
 
-This warning is also enabled by @option{-Wunused} together with
-@option{-Wextra}.
+@option{-Wunused-but-set-parameter=0} disables the warning.
+With @option{-Wunused-but-set-parameter=1} all uses except initialization
+and left hand side of assignment which is not further used disable the
+warning.
+With @option{-Wunused-but-set-parameter=2} additionally uses of parameter
+in @code{++} and @code{--} operators don't count as uses.
+And finally with @option{-Wunused-but-set-parameter=3} additionally
+uses in @var{parm} @code{@var{@@}=} @var{rhs} outside of @var{rhs} don't
+count as uses.  See @option{-Wunused-but-set-variable=@var{n}} option for
+examples.
+
+This @option{-Wunused-but-set-parameter=3} warning is also enabled by
+@option{-Wunused} together with @option{-Wextra}.
 
 @opindex Wunused-but-set-variable
 @opindex Wno-unused-but-set-variable
 @item -Wunused-but-set-variable
+@option{-Wunused-but-set-variable} is the same as
+@option{-Wunused-but-set-variable=3} and
+@option{-Wno-unused-but-set-variable} is the same as
+@option{-Wunused-but-set-variable=0}.
+
+@opindex Wunused-but-set-variable=
+@item -Wunused-but-set-variable=@var{n}
 Warn whenever a local variable is assigned to, but otherwise unused
 (aside from its declaration).
-This warning is enabled by @option{-Wall}.
+This @option{-Wunused-but-set-variable=3} warning is enabled by @option{-Wall}.
 
 To suppress this warning use the @code{unused} attribute
 (@pxref{Variable Attributes}).
 
-This warning is also enabled by @option{-Wunused}, which is enabled
-by @option{-Wall}.
+@option{-Wunused-but-set-variable=0} disables the warning.
+With @option{-Wunused-but-set-variable=1} all uses except initialization
+and left hand side of assignment which is not further used disable the
+warning.
+With @option{-Wunused-but-set-variable=2} additionally uses of variable
+in @code{++} and @code{--} operators don't count as uses.
+And finally with @option{-Wunused-but-set-variable=3} additionally
+uses in @var{parm} @code{@var{@@}=} @var{rhs} outside of @var{rhs} don't
+count as uses.
+
+This @option{-Wunused-but-set-variable=3} warning is also enabled by
+@option{-Wunused}, which is enabled by @option{-Wall}.
+
+@smallexample
+void foo (void)
+@{
+  int a = 1; // @option{-Wunused-variable} warning
+  int b = 0; // Warning for @var{n} >= 1
+  b = 1; b = 2;
+  int c = 0; // Warning for @var{n} >= 2
+  ++c; c--; --c; c++;
+  int d = 0; // Warning for @var{n} >= 3
+  d += 4;
+  int e = 0; // No warning, cast to void
+  (void) e;
+  int f = 0; // No warning, f used
+  int g = f = 5;
+  (void) g;
+  int h = 0; // No warning, preincrement used
+  int i = ++h;
+  (void) i;
+  int j = 0; // No warning, postdecrement used
+  int k = j--;
+  (void) k;
+  int l = 0; // No warning, l used
+  int m = l |= 2;
+  (void) m;
+@}
+@end smallexample
 
 @opindex Wunused-function
 @opindex Wno-unused-function
--- gcc/c-family/c-opts.cc.jj   2025-02-12 22:23:07.139772186 +0100
+++ gcc/c-family/c-opts.cc      2025-04-23 21:33:19.032931842 +0200
@@ -1217,6 +1217,17 @@ c_common_post_options (const char **pfil
   SET_OPTION_IF_UNSET (&global_options, &global_options_set,
                       flag_range_for_ext_temps, cxx_dialect >= cxx23);
 
+  /* EnabledBy unfortunately can't specify value to use if set and
+     LangEnabledBy can't specify multiple options with &&.  For -Wunused
+     or -Wunused -Wextra we want these to default to 3 unless user specified
+     some other level explicitly.  */
+  if (warn_unused_but_set_parameter == 1)
+    SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                        warn_unused_but_set_parameter, 3);
+  if (warn_unused_but_set_variable == 1)
+    SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                        warn_unused_but_set_variable, 3);
+
   /* -fimmediate-escalation has no effect when immediate functions are not
      supported.  */
   if (flag_immediate_escalation && cxx_dialect < cxx20)
--- gcc/c-family/c-attribs.cc.jj        2025-03-18 21:22:20.651027530 +0100
+++ gcc/c-family/c-attribs.cc   2025-04-23 21:57:19.077838901 +0200
@@ -5849,8 +5849,7 @@ build_attr_access_from_parms (tree parms
             order.  */
          vblist = tree_cons (NULL_TREE, argvbs, vblist);
 
-         unsigned nelts = 0;
-         for (tree vb = argvbs; vb; vb = TREE_CHAIN (vb), ++nelts)
+         for (tree vb = argvbs; vb; vb = TREE_CHAIN (vb))
            {
              tree bound = TREE_VALUE (vb);
              if (const unsigned *psizpos = arg2pos.get (bound))
--- gcc/c/c-parser.cc.jj        2025-04-02 23:02:22.019473781 +0200
+++ gcc/c/c-parser.cc   2025-04-23 21:33:19.040931736 +0200
@@ -10493,15 +10493,31 @@ c_parser_unary_expression (c_parser *par
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-
-      op = default_function_array_read_conversion (exp_loc, op);
+      if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
+         && !DECL_READ_P (op.value)
+         && (VAR_P (op.value) ? warn_unused_but_set_variable
+                              : warn_unused_but_set_parameter) > 1)
+       {
+         op = default_function_array_read_conversion (exp_loc, op);
+         DECL_READ_P (op.value) = 0;
+       }
+      else
+       op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-
-      op = default_function_array_read_conversion (exp_loc, op);
+      if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
+         && !DECL_READ_P (op.value)
+         && (VAR_P (op.value) ? warn_unused_but_set_variable
+                              : warn_unused_but_set_parameter) > 1)
+       {
+         op = default_function_array_read_conversion (exp_loc, op);
+         DECL_READ_P (op.value) = 0;
+       }
+      else
+       op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
     case CPP_AND:
       c_parser_consume_token (parser);
@@ -13833,7 +13849,17 @@ c_parser_postfix_expression_after_primar
          start = expr.get_start ();
          finish = c_parser_peek_token (parser)->get_finish ();
          c_parser_consume_token (parser);
-         expr = default_function_array_read_conversion (expr_loc, expr);
+         if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
+             && !DECL_READ_P (expr.value)
+             && (VAR_P (expr.value) ? warn_unused_but_set_variable
+                                    : warn_unused_but_set_parameter) > 1
+             && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
+           {
+             expr = default_function_array_read_conversion (expr_loc, expr);
+             DECL_READ_P (expr.value) = 0;
+           }
+         else
+           expr = default_function_array_read_conversion (expr_loc, expr);
          expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
                                       expr.value, false);
          set_c_expr_source_range (&expr, start, finish);
@@ -13845,7 +13871,17 @@ c_parser_postfix_expression_after_primar
          start = expr.get_start ();
          finish = c_parser_peek_token (parser)->get_finish ();
          c_parser_consume_token (parser);
-         expr = default_function_array_read_conversion (expr_loc, expr);
+         if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
+             && !DECL_READ_P (expr.value)
+             && (VAR_P (expr.value) ? warn_unused_but_set_variable
+                                    : warn_unused_but_set_parameter) > 1
+             && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
+           {
+             expr = default_function_array_read_conversion (expr_loc, expr);
+             DECL_READ_P (expr.value) = 0;
+           }
+         else
+           expr = default_function_array_read_conversion (expr_loc, expr);
          expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
                                       expr.value, false);
          set_c_expr_source_range (&expr, start, finish);
--- gcc/c/c-decl.cc.jj  2025-04-09 18:28:23.515697147 +0200
+++ gcc/c/c-decl.cc     2025-04-23 21:33:19.043931697 +0200
@@ -1363,7 +1363,7 @@ pop_scope (void)
        case VAR_DECL:
          /* Warnings for unused variables.  */
          if ((!TREE_USED (p) || !DECL_READ_P (p))
-             && !warning_suppressed_p (p, OPT_Wunused_but_set_variable)
+             && !warning_suppressed_p (p, OPT_Wunused_but_set_variable_)
              && !DECL_IN_SYSTEM_HEADER (p)
              && DECL_NAME (p)
              && !DECL_ARTIFICIAL (p)
@@ -1377,7 +1377,7 @@ pop_scope (void)
                }
              else if (DECL_CONTEXT (p) == current_function_decl)
                warning_at (DECL_SOURCE_LOCATION (p),
-                           OPT_Wunused_but_set_variable,
+                           OPT_Wunused_but_set_variable_,
                            "variable %qD set but not used", p);
            }
 
@@ -11486,9 +11486,9 @@ finish_function (location_t end_loc)
            && !DECL_READ_P (decl)
            && DECL_NAME (decl)
            && !DECL_ARTIFICIAL (decl)
-           && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter))
+           && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter_))
          warning_at (DECL_SOURCE_LOCATION (decl),
-                     OPT_Wunused_but_set_parameter,
+                     OPT_Wunused_but_set_parameter_,
                      "parameter %qD set but not used", decl);
     }
 
--- gcc/c/c-typeck.cc.jj        2025-04-16 18:24:17.674393580 +0200
+++ gcc/c/c-typeck.cc   2025-04-23 21:33:19.048931630 +0200
@@ -2316,14 +2316,30 @@ mark_exp_read (tree exp)
     case PARM_DECL:
       DECL_READ_P (exp) = 1;
       break;
+    CASE_CONVERT:
+      if (VOID_TYPE_P (TREE_TYPE (exp)))
+       switch (TREE_CODE (TREE_OPERAND (exp, 0)))
+         {
+         case PREINCREMENT_EXPR:
+         case PREDECREMENT_EXPR:
+         case POSTINCREMENT_EXPR:
+         case POSTDECREMENT_EXPR:
+           return;
+         default:
+           break;
+         }
+      /* FALLTHRU */
     case ARRAY_REF:
     case COMPONENT_REF:
     case MODIFY_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
-    CASE_CONVERT:
     case ADDR_EXPR:
     case VIEW_CONVERT_EXPR:
+    case PREINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
       mark_exp_read (TREE_OPERAND (exp, 0));
       break;
     case COMPOUND_EXPR:
@@ -7218,8 +7234,21 @@ build_modify_expr (location_t location,
                newrhs = build1 (EXCESS_PRECISION_EXPR, TREE_TYPE (rhs),
                                 newrhs);
            }
+         bool clear_decl_read = false;
+         if ((VAR_P (lhs) || TREE_CODE (lhs) == PARM_DECL)
+             && !DECL_READ_P (lhs)
+             && (VAR_P (lhs) ? warn_unused_but_set_variable
+                             : warn_unused_but_set_parameter) > 2)
+           {
+             mark_exp_read (newrhs);
+             if (!DECL_READ_P (lhs))
+               clear_decl_read = true;
+           }
+
          newrhs = build_binary_op (location,
                                    modifycode, lhs, newrhs, true);
+         if (clear_decl_read)
+           DECL_READ_P (lhs) = 0;
 
          /* The original type of the right hand side is no longer
             meaningful.  */
--- gcc/cp/cp-gimplify.cc.jj    2025-04-12 21:41:42.660924514 +0200
+++ gcc/cp/cp-gimplify.cc       2025-04-23 21:33:19.050931604 +0200
@@ -3200,7 +3200,23 @@ cp_fold (tree x, fold_flags_t flags)
 
       loc = EXPR_LOCATION (x);
       op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops, flags);
+      bool clear_decl_read;
+      clear_decl_read = false;
+      if (code == MODIFY_EXPR
+         && (VAR_P (op0) || TREE_CODE (op0) == PARM_DECL)
+         && !DECL_READ_P (op0)
+         && (VAR_P (op0) ? warn_unused_but_set_variable
+                         : warn_unused_but_set_parameter) > 2
+         && BINARY_CLASS_P (TREE_OPERAND (x, 1))
+         && TREE_OPERAND (TREE_OPERAND (x, 1), 0) == op0)
+       {
+         mark_exp_read (TREE_OPERAND (TREE_OPERAND (x, 1), 1));
+         if (!DECL_READ_P (op0))
+           clear_decl_read = true;
+       }
       op1 = cp_fold_rvalue (TREE_OPERAND (x, 1), flags);
+      if (clear_decl_read)
+       DECL_READ_P (op0) = 0;
 
       /* decltype(nullptr) has only one value, so optimize away all comparisons
         with that type right away, keeping them in the IL causes troubles for
--- gcc/cp/decl.cc.jj   2025-04-22 21:26:15.719920897 +0200
+++ gcc/cp/decl.cc      2025-04-23 21:33:19.053931564 +0200
@@ -747,11 +747,11 @@ poplevel (int keep, int reverse, int fun
              {
                if (!DECL_NAME (decl) && DECL_DECOMPOSITION_P (decl))
                  warning_at (DECL_SOURCE_LOCATION (decl),
-                             OPT_Wunused_but_set_variable, "structured "
+                             OPT_Wunused_but_set_variable_, "structured "
                              "binding declaration set but not used");
                else
                  warning_at (DECL_SOURCE_LOCATION (decl),
-                             OPT_Wunused_but_set_variable,
+                             OPT_Wunused_but_set_variable_,
                              "variable %qD set but not used", decl);
                unused_but_set_errorcount = errorcount;
              }
@@ -19423,14 +19423,14 @@ finish_function (bool inline_p)
            && !DECL_READ_P (decl)
            && DECL_NAME (decl)
            && !DECL_ARTIFICIAL (decl)
-           && !warning_suppressed_p (decl,OPT_Wunused_but_set_parameter)
+           && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter_)
            && !DECL_IN_SYSTEM_HEADER (decl)
            && TREE_TYPE (decl) != error_mark_node
            && !TYPE_REF_P (TREE_TYPE (decl))
            && (!CLASS_TYPE_P (TREE_TYPE (decl))
                || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
          warning_at (DECL_SOURCE_LOCATION (decl),
-                     OPT_Wunused_but_set_parameter,
+                     OPT_Wunused_but_set_parameter_,
                      "parameter %qD set but not used", decl);
       unused_but_set_errorcount = errorcount;
     }
--- gcc/cp/expr.cc.jj   2025-01-02 20:54:32.078130627 +0100
+++ gcc/cp/expr.cc      2025-04-23 21:33:19.054931551 +0200
@@ -211,8 +211,27 @@ mark_use (tree expr, bool rvalue_p, bool
            }
          return expr;
        }
-      gcc_fallthrough();
+      gcc_fallthrough ();
     CASE_CONVERT:
+      if (VOID_TYPE_P (TREE_TYPE (expr)))
+       switch (TREE_CODE (TREE_OPERAND (expr, 0)))
+         {
+         case PREINCREMENT_EXPR:
+         case PREDECREMENT_EXPR:
+         case POSTINCREMENT_EXPR:
+         case POSTDECREMENT_EXPR:
+           tree op0;
+           op0 = TREE_OPERAND (TREE_OPERAND (expr, 0), 0);
+           STRIP_ANY_LOCATION_WRAPPER (op0);
+           if ((VAR_P (op0) || TREE_CODE (op0) == PARM_DECL)
+               && !DECL_READ_P (op0)
+               && (VAR_P (op0) ? warn_unused_but_set_variable
+                               : warn_unused_but_set_parameter) > 1)
+             read_p = false;
+           break;
+         default:
+           break;
+         }
       recurse_op[0] = true;
       break;
 
@@ -361,16 +380,32 @@ mark_exp_read (tree exp)
     case PARM_DECL:
       DECL_READ_P (exp) = 1;
       break;
+    CASE_CONVERT:
+      if (VOID_TYPE_P (TREE_TYPE (exp)))
+       switch (TREE_CODE (TREE_OPERAND (exp, 0)))
+         {
+         case PREINCREMENT_EXPR:
+         case PREDECREMENT_EXPR:
+         case POSTINCREMENT_EXPR:
+         case POSTDECREMENT_EXPR:
+           return;
+         default:
+           break;
+         }
+      /* FALLTHRU */
     case ARRAY_REF:
     case COMPONENT_REF:
     case MODIFY_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
-    CASE_CONVERT:
     case ADDR_EXPR:
     case INDIRECT_REF:
     case FLOAT_EXPR:
     case VIEW_CONVERT_EXPR:
+    case PREINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
       mark_exp_read (TREE_OPERAND (exp, 0));
       break;
     case COMPOUND_EXPR:
--- gcc/cp/module.cc.jj 2025-04-14 15:02:23.751540802 +0200
+++ gcc/cp/module.cc    2025-04-24 00:00:18.975911347 +0200
@@ -10971,8 +10971,7 @@ trees_in::fn_parms_fini (int tag, tree f
 {
   tree existing_parm = existing ? DECL_ARGUMENTS (existing) : NULL_TREE;
   tree parms = DECL_ARGUMENTS (fn);
-  unsigned ix = 0;
-  for (tree parm = parms; parm; parm = DECL_CHAIN (parm), ix++)
+  for (tree parm = parms; parm; parm = DECL_CHAIN (parm))
     {
       if (existing_parm)
        {
--- gcc/cp/semantics.cc.jj      2025-04-22 21:26:15.735920684 +0200
+++ gcc/cp/semantics.cc 2025-04-23 21:33:19.057931511 +0200
@@ -3740,7 +3740,28 @@ finish_unary_op_expr (location_t op_loc,
   tree expr_ovl = expr;
 
   if (!processing_template_decl)
-    expr_ovl = cp_fully_fold (expr_ovl);
+    switch (code)
+      {
+      case PREINCREMENT_EXPR:
+      case PREDECREMENT_EXPR:
+      case POSTINCREMENT_EXPR:
+      case POSTDECREMENT_EXPR:
+       tree stripped_expr;
+       stripped_expr = tree_strip_any_location_wrapper (expr);
+       if ((VAR_P (stripped_expr) || TREE_CODE (stripped_expr) == PARM_DECL)
+           && !DECL_READ_P (stripped_expr)
+           && (VAR_P (stripped_expr) ? warn_unused_but_set_variable
+                                     : warn_unused_but_set_parameter) > 1)
+         {
+           expr_ovl = cp_fully_fold (expr_ovl);
+           DECL_READ_P (stripped_expr) = 0;
+           break;
+         }
+       /* FALLTHRU */
+      default:
+       expr_ovl = cp_fully_fold (expr_ovl);
+       break;
+      }
 
   if (!CONSTANT_CLASS_P (expr_ovl)
       || TREE_OVERFLOW_P (expr_ovl))
--- gcc/cp/typeck.cc.jj 2025-04-01 21:52:48.490575729 +0200
+++ gcc/cp/typeck.cc    2025-04-23 21:33:19.060931471 +0200
@@ -7630,7 +7630,18 @@ cp_build_unary_op (enum tree_code code,
       if (val != 0)
        goto return_build_unary_op;
 
-      arg = mark_lvalue_use (arg);
+      tree stripped_arg;
+      stripped_arg = tree_strip_any_location_wrapper (arg);
+      if ((VAR_P (stripped_arg) || TREE_CODE (stripped_arg) == PARM_DECL)
+         && !DECL_READ_P (stripped_arg)
+         && (VAR_P (stripped_arg) ? warn_unused_but_set_variable
+                                  : warn_unused_but_set_parameter) > 1)
+       {
+         arg = mark_lvalue_use (arg);
+         DECL_READ_P (stripped_arg) = 0;
+       }
+      else
+       arg = mark_lvalue_use (arg);
 
       /* Increment or decrement the real part of the value,
         and don't change the imaginary part.  */
@@ -9746,7 +9757,22 @@ cp_build_modify_expr (location_t loc, tr
          {
            auto_diagnostic_group d;
            rhs = stabilize_expr (rhs, &init);
+           bool clear_decl_read = false;
+           tree stripped_lhs = tree_strip_any_location_wrapper (lhs);
+           if ((VAR_P (stripped_lhs) || TREE_CODE (stripped_lhs) == PARM_DECL)
+               && !DECL_READ_P (stripped_lhs)
+               && (VAR_P (stripped_lhs) ? warn_unused_but_set_variable
+                                        : warn_unused_but_set_parameter) > 2
+               && !CLASS_TYPE_P (TREE_TYPE (lhs))
+               && !CLASS_TYPE_P (TREE_TYPE (rhs)))
+             {
+               mark_exp_read (rhs);
+               if (!DECL_READ_P (stripped_lhs))
+                 clear_decl_read = true;
+             }
            newrhs = cp_build_binary_op (loc, modifycode, lhs, rhs, complain);
+           if (clear_decl_read)
+             DECL_READ_P (stripped_lhs) = 0;
            if (newrhs == error_mark_node)
              {
                if (complain & tf_error)
--- gcc/go/gofrontend/gogo.cc.jj        2024-12-05 22:00:16.430164341 +0100
+++ gcc/go/gofrontend/gogo.cc   2025-04-24 00:02:29.930197191 +0200
@@ -5987,12 +5987,11 @@ Function::export_func_with_type(Export*
   const Typed_identifier_list* parameters = fntype->parameters();
   if (parameters != NULL)
     {
-      size_t i = 0;
       bool is_varargs = fntype->is_varargs();
       bool first = true;
       for (Typed_identifier_list::const_iterator p = parameters->begin();
           p != parameters->end();
-          ++p, ++i)
+          ++p)
        {
          if (first)
            first = false;
--- gcc/testsuite/c-c++-common/Wunused-parm-1.c.jj      2025-04-23 
21:33:19.060931471 +0200
+++ gcc/testsuite/c-c++-common/Wunused-parm-1.c 2025-04-23 21:33:19.060931471 
+0200
@@ -0,0 +1,50 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-parameter" } */
+
+void baz (int);
+
+void
+foo (int a,            /* { dg-warning "parameter 'a' set but not used" } */
+     int b,            /* { dg-warning "parameter 'b' set but not used" } */
+     int c,            /* { dg-warning "parameter 'c' set but not used" } */
+     int d,            /* { dg-warning "parameter 'd' set but not used" } */
+     int e,            /* { dg-warning "parameter 'e' set but not used" } */
+     int f,            /* { dg-warning "parameter 'f' set but not used" } */
+     int g,            /* { dg-warning "parameter 'g' set but not used" } */
+     int h,            /* { dg-warning "parameter 'h' set but not used" } */
+     int i,            /* { dg-warning "parameter 'i' set but not used" } */
+     int j,            /* { dg-warning "parameter 'j' set but not used" } */
+     int k,            /* { dg-warning "parameter 'k' set but not used" } */
+     int l,            /* { dg-warning "parameter 'l' set but not used" } */
+     int m)            /* { dg-warning "parameter 'm' set but not used" } */
+{
+  a = 1;
+  ++b;
+  c++;
+  --d;
+  e--;
+  f += 2;
+  g |= 2;
+  h -= 2;
+  i &= 2;
+  j ^= 2;
+  k *= 2;
+  l %= 2;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
+     int k, int l, int m, int n)
+{
+  b = ++a;
+  d = --c;
+  f = e--;
+  h = g++;
+  j = i += 42;
+  l = k *= 4;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-parm-2.c.jj      2025-04-23 
21:33:19.060931471 +0200
+++ gcc/testsuite/c-c++-common/Wunused-parm-2.c 2025-04-23 21:33:19.060931471 
+0200
@@ -0,0 +1,50 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused -Wextra" } */
+
+void baz (int);
+
+void
+foo (int a,            /* { dg-warning "parameter 'a' set but not used" } */
+     int b,            /* { dg-warning "parameter 'b' set but not used" } */
+     int c,            /* { dg-warning "parameter 'c' set but not used" } */
+     int d,            /* { dg-warning "parameter 'd' set but not used" } */
+     int e,            /* { dg-warning "parameter 'e' set but not used" } */
+     int f,            /* { dg-warning "parameter 'f' set but not used" } */
+     int g,            /* { dg-warning "parameter 'g' set but not used" } */
+     int h,            /* { dg-warning "parameter 'h' set but not used" } */
+     int i,            /* { dg-warning "parameter 'i' set but not used" } */
+     int j,            /* { dg-warning "parameter 'j' set but not used" } */
+     int k,            /* { dg-warning "parameter 'k' set but not used" } */
+     int l,            /* { dg-warning "parameter 'l' set but not used" } */
+     int m)            /* { dg-warning "parameter 'm' set but not used" } */
+{
+  a = 1;
+  ++b;
+  c++;
+  --d;
+  e--;
+  f += 2;
+  g |= 2;
+  h -= 2;
+  i &= 2;
+  j ^= 2;
+  k *= 2;
+  l %= 2;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
+     int k, int l, int m, int n)
+{
+  b = ++a;
+  d = --c;
+  f = e--;
+  h = g++;
+  j = i += 42;
+  l = k *= 4;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-parm-3.c.jj      2025-04-23 
21:33:19.061931458 +0200
+++ gcc/testsuite/c-c++-common/Wunused-parm-3.c 2025-04-23 21:33:19.061931458 
+0200
@@ -0,0 +1,50 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-parameter=3" } */
+
+void baz (int);
+
+void
+foo (int a,            /* { dg-warning "parameter 'a' set but not used" } */
+     int b,            /* { dg-warning "parameter 'b' set but not used" } */
+     int c,            /* { dg-warning "parameter 'c' set but not used" } */
+     int d,            /* { dg-warning "parameter 'd' set but not used" } */
+     int e,            /* { dg-warning "parameter 'e' set but not used" } */
+     int f,            /* { dg-warning "parameter 'f' set but not used" } */
+     int g,            /* { dg-warning "parameter 'g' set but not used" } */
+     int h,            /* { dg-warning "parameter 'h' set but not used" } */
+     int i,            /* { dg-warning "parameter 'i' set but not used" } */
+     int j,            /* { dg-warning "parameter 'j' set but not used" } */
+     int k,            /* { dg-warning "parameter 'k' set but not used" } */
+     int l,            /* { dg-warning "parameter 'l' set but not used" } */
+     int m)            /* { dg-warning "parameter 'm' set but not used" } */
+{
+  a = 1;
+  ++b;
+  c++;
+  --d;
+  e--;
+  f += 2;
+  g |= 2;
+  h -= 2;
+  i &= 2;
+  j ^= 2;
+  k *= 2;
+  l %= 2;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
+     int k, int l, int m, int n)
+{
+  b = ++a;
+  d = --c;
+  f = e--;
+  h = g++;
+  j = i += 42;
+  l = k *= 4;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-parm-4.c.jj      2025-04-23 
21:33:19.061931458 +0200
+++ gcc/testsuite/c-c++-common/Wunused-parm-4.c 2025-04-23 21:33:19.061931458 
+0200
@@ -0,0 +1,50 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-parameter=2" } */
+
+void baz (int);
+
+void
+foo (int a,            /* { dg-warning "parameter 'a' set but not used" } */
+     int b,            /* { dg-warning "parameter 'b' set but not used" } */
+     int c,            /* { dg-warning "parameter 'c' set but not used" } */
+     int d,            /* { dg-warning "parameter 'd' set but not used" } */
+     int e,            /* { dg-warning "parameter 'e' set but not used" } */
+     int f,
+     int g,
+     int h,
+     int i,
+     int j,
+     int k,
+     int l,
+     int m)            /* { dg-warning "parameter 'm' set but not used" } */
+{
+  a = 1;
+  ++b;
+  c++;
+  --d;
+  e--;
+  f += 2;
+  g |= 2;
+  h -= 2;
+  i &= 2;
+  j ^= 2;
+  k *= 2;
+  l %= 2;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
+     int k, int l, int m, int n)
+{
+  b = ++a;
+  d = --c;
+  f = e--;
+  h = g++;
+  j = i += 42;
+  l = k *= 4;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-parm-5.c.jj      2025-04-23 
21:33:19.061931458 +0200
+++ gcc/testsuite/c-c++-common/Wunused-parm-5.c 2025-04-23 21:33:19.061931458 
+0200
@@ -0,0 +1,50 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-parameter=1" } */
+
+void baz (int);
+
+void
+foo (int a,            /* { dg-warning "parameter 'a' set but not used" } */
+     int b,
+     int c,
+     int d,
+     int e,
+     int f,
+     int g,
+     int h,
+     int i,
+     int j,
+     int k,
+     int l,
+     int m)
+{
+  a = 1;
+  ++b;
+  c++;
+  --d;
+  e--;
+  f += 2;
+  g |= 2;
+  h -= 2;
+  i &= 2;
+  j ^= 2;
+  k *= 2;
+  l %= 2;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
+     int k, int l, int m, int n)
+{
+  b = ++a;
+  d = --c;
+  f = e--;
+  h = g++;
+  j = i += 42;
+  l = k *= 4;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-parm-6.c.jj      2025-04-23 
21:33:19.061931458 +0200
+++ gcc/testsuite/c-c++-common/Wunused-parm-6.c 2025-04-23 21:33:19.061931458 
+0200
@@ -0,0 +1,50 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-parameter=0" } */
+
+void baz (int);
+
+void
+foo (int a,
+     int b,
+     int c,
+     int d,
+     int e,
+     int f,
+     int g,
+     int h,
+     int i,
+     int j,
+     int k,
+     int l,
+     int m)
+{
+  a = 1;
+  ++b;
+  c++;
+  --d;
+  e--;
+  f += 2;
+  g |= 2;
+  h -= 2;
+  i &= 2;
+  j ^= 2;
+  k *= 2;
+  l %= 2;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
+     int k, int l, int m, int n)
+{
+  b = ++a;
+  d = --c;
+  f = e--;
+  h = g++;
+  j = i += 42;
+  l = k *= 4;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-var-7.c.jj       2020-01-14 
20:02:46.643611931 +0100
+++ gcc/testsuite/c-c++-common/Wunused-var-7.c  2025-04-23 21:33:19.062931445 
+0200
@@ -24,7 +24,7 @@ foo (void)
 void
 bar (void)
 {
-  int a;
+  int a;               /* { dg-warning "set but not used" } */
   int b;
   int c;               /* { dg-warning "set but not used" } */
   a = 1;
@@ -36,7 +36,7 @@ bar (void)
 void
 baz (void)
 {
-  int a;
+  int a;               /* { dg-warning "set but not used" } */
   int b;
   int c;
   int d;
--- gcc/testsuite/c-c++-common/Wunused-var-19.c.jj      2025-04-23 
21:33:19.061931458 +0200
+++ gcc/testsuite/c-c++-common/Wunused-var-19.c 2025-04-23 21:33:19.061931458 
+0200
@@ -0,0 +1,60 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-variable" } */
+
+void baz (int);
+
+void
+foo (void)
+{
+  int a = 0;           /* { dg-warning "variable 'a' set but not used" } */
+  a = 1;
+  int b = 0;           /* { dg-warning "variable 'b' set but not used" } */
+  ++b;
+  int c = 0;           /* { dg-warning "variable 'c' set but not used" } */
+  c++;
+  int d = 0;           /* { dg-warning "variable 'd' set but not used" } */
+  --d;
+  int e = 0;           /* { dg-warning "variable 'e' set but not used" } */
+  e--;
+  int f = 0;           /* { dg-warning "variable 'f' set but not used" } */
+  f += 2;
+  int g = 0;           /* { dg-warning "variable 'g' set but not used" } */
+  g |= 2;
+  int h = 0;           /* { dg-warning "variable 'h' set but not used" } */
+  h -= 2;
+  int i = 0;           /* { dg-warning "variable 'i' set but not used" } */
+  i &= 2;
+  int j = 0;           /* { dg-warning "variable 'j' set but not used" } */
+  j ^= 2;
+  int k = 0;           /* { dg-warning "variable 'k' set but not used" } */
+  k *= 2;
+  int l = 0;           /* { dg-warning "variable 'l' set but not used" } */
+  l %= 2;
+  int m = 0;           /* { dg-warning "variable 'm' set but not used" } */
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (void)
+{
+  int a = 0;
+  int b = ++a;
+  int c = 0;
+  int d = --c;
+  int e = 0;
+  int f = e--;
+  int g = 0;
+  int h = g++;
+  int i = 0;
+  int j;
+  j = i += 42;
+  int k = 0;
+  int l;
+  l = k *= 4;
+  int m = 0;
+  int n;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-var-20.c.jj      2025-04-23 
21:33:19.061931458 +0200
+++ gcc/testsuite/c-c++-common/Wunused-var-20.c 2025-04-23 21:33:19.061931458 
+0200
@@ -0,0 +1,60 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused" } */
+
+void baz (int);
+
+void
+foo (void)
+{
+  int a = 0;           /* { dg-warning "variable 'a' set but not used" } */
+  a = 1;
+  int b = 0;           /* { dg-warning "variable 'b' set but not used" } */
+  ++b;
+  int c = 0;           /* { dg-warning "variable 'c' set but not used" } */
+  c++;
+  int d = 0;           /* { dg-warning "variable 'd' set but not used" } */
+  --d;
+  int e = 0;           /* { dg-warning "variable 'e' set but not used" } */
+  e--;
+  int f = 0;           /* { dg-warning "variable 'f' set but not used" } */
+  f += 2;
+  int g = 0;           /* { dg-warning "variable 'g' set but not used" } */
+  g |= 2;
+  int h = 0;           /* { dg-warning "variable 'h' set but not used" } */
+  h -= 2;
+  int i = 0;           /* { dg-warning "variable 'i' set but not used" } */
+  i &= 2;
+  int j = 0;           /* { dg-warning "variable 'j' set but not used" } */
+  j ^= 2;
+  int k = 0;           /* { dg-warning "variable 'k' set but not used" } */
+  k *= 2;
+  int l = 0;           /* { dg-warning "variable 'l' set but not used" } */
+  l %= 2;
+  int m = 0;           /* { dg-warning "variable 'm' set but not used" } */
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (void)
+{
+  int a = 0;
+  int b = ++a;
+  int c = 0;
+  int d = --c;
+  int e = 0;
+  int f = e--;
+  int g = 0;
+  int h = g++;
+  int i = 0;
+  int j;
+  j = i += 42;
+  int k = 0;
+  int l;
+  l = k *= 4;
+  int m = 0;
+  int n;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-var-21.c.jj      2025-04-23 
21:33:19.061931458 +0200
+++ gcc/testsuite/c-c++-common/Wunused-var-21.c 2025-04-23 21:33:19.061931458 
+0200
@@ -0,0 +1,60 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-variable=3" } */
+
+void baz (int);
+
+void
+foo (void)
+{
+  int a = 0;           /* { dg-warning "variable 'a' set but not used" } */
+  a = 1;
+  int b = 0;           /* { dg-warning "variable 'b' set but not used" } */
+  ++b;
+  int c = 0;           /* { dg-warning "variable 'c' set but not used" } */
+  c++;
+  int d = 0;           /* { dg-warning "variable 'd' set but not used" } */
+  --d;
+  int e = 0;           /* { dg-warning "variable 'e' set but not used" } */
+  e--;
+  int f = 0;           /* { dg-warning "variable 'f' set but not used" } */
+  f += 2;
+  int g = 0;           /* { dg-warning "variable 'g' set but not used" } */
+  g |= 2;
+  int h = 0;           /* { dg-warning "variable 'h' set but not used" } */
+  h -= 2;
+  int i = 0;           /* { dg-warning "variable 'i' set but not used" } */
+  i &= 2;
+  int j = 0;           /* { dg-warning "variable 'j' set but not used" } */
+  j ^= 2;
+  int k = 0;           /* { dg-warning "variable 'k' set but not used" } */
+  k *= 2;
+  int l = 0;           /* { dg-warning "variable 'l' set but not used" } */
+  l %= 2;
+  int m = 0;           /* { dg-warning "variable 'm' set but not used" } */
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (void)
+{
+  int a = 0;
+  int b = ++a;
+  int c = 0;
+  int d = --c;
+  int e = 0;
+  int f = e--;
+  int g = 0;
+  int h = g++;
+  int i = 0;
+  int j;
+  j = i += 42;
+  int k = 0;
+  int l;
+  l = k *= 4;
+  int m = 0;
+  int n;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-var-22.c.jj      2025-04-23 
21:33:19.062931445 +0200
+++ gcc/testsuite/c-c++-common/Wunused-var-22.c 2025-04-23 21:33:19.062931445 
+0200
@@ -0,0 +1,60 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-variable=2" } */
+
+void baz (int);
+
+void
+foo (void)
+{
+  int a = 0;           /* { dg-warning "variable 'a' set but not used" } */
+  a = 1;
+  int b = 0;           /* { dg-warning "variable 'b' set but not used" } */
+  ++b;
+  int c = 0;           /* { dg-warning "variable 'c' set but not used" } */
+  c++;
+  int d = 0;           /* { dg-warning "variable 'd' set but not used" } */
+  --d;
+  int e = 0;           /* { dg-warning "variable 'e' set but not used" } */
+  e--;
+  int f = 0;
+  f += 2;
+  int g = 0;
+  g |= 2;
+  int h = 0;
+  h -= 2;
+  int i = 0;
+  i &= 2;
+  int j = 0;
+  j ^= 2;
+  int k = 0;
+  k *= 2;
+  int l = 0;
+  l %= 2;
+  int m = 0;           /* { dg-warning "variable 'm' set but not used" } */
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (void)
+{
+  int a = 0;
+  int b = ++a;
+  int c = 0;
+  int d = --c;
+  int e = 0;
+  int f = e--;
+  int g = 0;
+  int h = g++;
+  int i = 0;
+  int j;
+  j = i += 42;
+  int k = 0;
+  int l;
+  l = k *= 4;
+  int m = 0;
+  int n;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-var-23.c.jj      2025-04-23 
21:33:19.062931445 +0200
+++ gcc/testsuite/c-c++-common/Wunused-var-23.c 2025-04-23 21:33:19.062931445 
+0200
@@ -0,0 +1,60 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-variable=1" } */
+
+void baz (int);
+
+void
+foo (void)
+{
+  int a = 0;           /* { dg-warning "variable 'a' set but not used" } */
+  a = 1;
+  int b = 0;
+  ++b;
+  int c = 0;
+  c++;
+  int d = 0;
+  --d;
+  int e = 0;
+  e--;
+  int f = 0;
+  f += 2;
+  int g = 0;
+  g |= 2;
+  int h = 0;
+  h -= 2;
+  int i = 0;
+  i &= 2;
+  int j = 0;
+  j ^= 2;
+  int k = 0;
+  k *= 2;
+  int l = 0;
+  l %= 2;
+  int m = 0;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (void)
+{
+  int a = 0;
+  int b = ++a;
+  int c = 0;
+  int d = --c;
+  int e = 0;
+  int f = e--;
+  int g = 0;
+  int h = g++;
+  int i = 0;
+  int j;
+  j = i += 42;
+  int k = 0;
+  int l;
+  l = k *= 4;
+  int m = 0;
+  int n;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/c-c++-common/Wunused-var-24.c.jj      2025-04-23 
21:33:19.062931445 +0200
+++ gcc/testsuite/c-c++-common/Wunused-var-24.c 2025-04-23 21:33:19.062931445 
+0200
@@ -0,0 +1,60 @@
+/* PR c/44677 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-but-set-variable=0" } */
+
+void baz (int);
+
+void
+foo (void)
+{
+  int a = 0;
+  a = 1;
+  int b = 0;
+  ++b;
+  int c = 0;
+  c++;
+  int d = 0;
+  --d;
+  int e = 0;
+  e--;
+  int f = 0;
+  f += 2;
+  int g = 0;
+  g |= 2;
+  int h = 0;
+  h -= 2;
+  int i = 0;
+  i &= 2;
+  int j = 0;
+  j ^= 2;
+  int k = 0;
+  k *= 2;
+  int l = 0;
+  l %= 2;
+  int m = 0;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+int
+bar (void)
+{
+  int a = 0;
+  int b = ++a;
+  int c = 0;
+  int d = --c;
+  int e = 0;
+  int f = e--;
+  int g = 0;
+  int h = g++;
+  int i = 0;
+  int j;
+  j = i += 42;
+  int k = 0;
+  int l;
+  l = k *= 4;
+  int m = 0;
+  int n;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
--- gcc/testsuite/g++.dg/cpp26/name-independent-decl1.C.jj      2023-11-30 
22:24:40.962331534 +0100
+++ gcc/testsuite/g++.dg/cpp26/name-independent-decl1.C 2025-04-23 
21:33:19.063931431 +0200
@@ -70,7 +70,7 @@ foo ()
       ++_;
     }
     {
-      static int _ = 3;
+      static int _ = 3;                // { dg-warning "variable '_' set but 
not used" }
       ++_;
     }
     {
--- gcc/testsuite/g++.dg/warn/Wunused-parm-12.C.jj      2025-04-23 
21:33:19.063931431 +0200
+++ gcc/testsuite/g++.dg/warn/Wunused-parm-12.C 2025-04-23 21:33:19.063931431 
+0200
@@ -0,0 +1,59 @@
+// PR c/44677
+// { dg-do compile }
+// { dg-options "-O2 -Wunused-but-set-parameter" }
+
+void baz (int);
+
+template <int N>
+void
+foo (int a,            // { dg-warning "parameter 'a' set but not used" }
+     int b,            // { dg-warning "parameter 'b' set but not used" }
+     int c,            // { dg-warning "parameter 'c' set but not used" }
+     int d,            // { dg-warning "parameter 'd' set but not used" }
+     int e,            // { dg-warning "parameter 'e' set but not used" }
+     int f,            // { dg-warning "parameter 'f' set but not used" }
+     int g,            // { dg-warning "parameter 'g' set but not used" }
+     int h,            // { dg-warning "parameter 'h' set but not used" }
+     int i,            // { dg-warning "parameter 'i' set but not used" }
+     int j,            // { dg-warning "parameter 'j' set but not used" }
+     int k,            // { dg-warning "parameter 'k' set but not used" }
+     int l,            // { dg-warning "parameter 'l' set but not used" }
+     int m)            // { dg-warning "parameter 'm' set but not used" }
+{
+  a = 1;
+  ++b;
+  c++;
+  --d;
+  e--;
+  f += 2;
+  g |= 2;
+  h -= 2;
+  i &= 2;
+  j ^= 2;
+  k *= 2;
+  l %= 2;
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+template <int N>
+int
+bar (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
+     int k, int l, int m, int n)
+{
+  b = ++a;
+  d = --c;
+  f = e--;
+  h = g++;
+  j = i += 42;
+  l = k *= 4;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
+
+void
+test ()
+{
+  foo <0> (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+  bar <0> (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+}
--- gcc/testsuite/g++.dg/warn/Wunused-parm-13.C.jj      2025-04-23 
21:33:19.063931431 +0200
+++ gcc/testsuite/g++.dg/warn/Wunused-parm-13.C 2025-04-23 21:33:19.063931431 
+0200
@@ -0,0 +1,59 @@
+// PR c/44677
+// { dg-do compile }
+// { dg-options "-O2 -Wunused-but-set-parameter" }
+
+void baz (int);
+
+template <typename T>
+void
+foo (T a,              // { dg-warning "parameter 'a' set but not used" }
+     T b,              // { dg-warning "parameter 'b' set but not used" }
+     T c,              // { dg-warning "parameter 'c' set but not used" }
+     T d,              // { dg-warning "parameter 'd' set but not used" }
+     T e,              // { dg-warning "parameter 'e' set but not used" }
+     T f,              // { dg-warning "parameter 'f' set but not used" }
+     T g,              // { dg-warning "parameter 'g' set but not used" }
+     T h,              // { dg-warning "parameter 'h' set but not used" }
+     T i,              // { dg-warning "parameter 'i' set but not used" }
+     T j,              // { dg-warning "parameter 'j' set but not used" }
+     T k,              // { dg-warning "parameter 'k' set but not used" }
+     T l,              // { dg-warning "parameter 'l' set but not used" }
+     T m)              // { dg-warning "parameter 'm' set but not used" }
+{
+  a = 1;
+  ++b;
+  c++;
+  --d;
+  e--;
+  f += 2;
+  g |= 2;
+  h -= 2;
+  i &= 2;
+  j ^= 2;
+  k *= 2;
+  l %= 2;
+  for (T n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+template <typename T>
+T
+bar (T a, T b, T c, T d, T e, T f, T g, T h, T i, T j,
+     T k, T l, T m, T n)
+{
+  b = ++a;
+  d = --c;
+  f = e--;
+  h = g++;
+  j = i += 42;
+  l = k *= 4;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
+
+void
+test ()
+{
+  foo <int> (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+  bar <int> (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+}
--- gcc/testsuite/g++.dg/warn/Wunused-var-2.C.jj        2020-01-14 
20:02:47.003606539 +0100
+++ gcc/testsuite/g++.dg/warn/Wunused-var-2.C   2025-04-23 21:33:19.063931431 
+0200
@@ -18,9 +18,9 @@ f1 ()
 }
 
 void
-f2 (int x)
+f2 (int x)     // { dg-warning "parameter 'x' set but not used" }
 {
-  int a = 0;
+  int a = 0;   // { dg-warning "variable 'a' set but not used" }
   x++;
   ++a;
 }
--- gcc/testsuite/g++.dg/warn/Wunused-var-40.C.jj       2025-04-23 
21:33:19.063931431 +0200
+++ gcc/testsuite/g++.dg/warn/Wunused-var-40.C  2025-04-23 21:33:19.063931431 
+0200
@@ -0,0 +1,69 @@
+// PR c/44677
+// { dg-do compile }
+// { dg-options "-O2 -Wunused-but-set-variable" }
+
+void baz (int);
+
+template <int N>
+void
+foo (void)
+{
+  int a = 0;           // { dg-warning "variable 'a' set but not used" }
+  a = 1;
+  int b = 0;           // { dg-warning "variable 'b' set but not used" }
+  ++b;
+  int c = 0;           // { dg-warning "variable 'c' set but not used" }
+  c++;
+  int d = 0;           // { dg-warning "variable 'd' set but not used" }
+  --d;
+  int e = 0;           // { dg-warning "variable 'e' set but not used" }
+  e--;
+  int f = 0;           // { dg-warning "variable 'f' set but not used" }
+  f += 2;
+  int g = 0;           // { dg-warning "variable 'g' set but not used" }
+  g |= 2;
+  int h = 0;           // { dg-warning "variable 'h' set but not used" }
+  h -= 2;
+  int i = 0;           // { dg-warning "variable 'i' set but not used" }
+  i &= 2;
+  int j = 0;           // { dg-warning "variable 'j' set but not used" }
+  j ^= 2;
+  int k = 0;           // { dg-warning "variable 'k' set but not used" }
+  k *= 2;
+  int l = 0;           // { dg-warning "variable 'l' set but not used" }
+  l %= 2;
+  int m = 0;           // { dg-warning "variable 'm' set but not used" }
+  for (int n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+template <int N>
+int
+bar (void)
+{
+  int a = 0;
+  int b = ++a;
+  int c = 0;
+  int d = --c;
+  int e = 0;
+  int f = e--;
+  int g = 0;
+  int h = g++;
+  int i = 0;
+  int j;
+  j = i += 42;
+  int k = 0;
+  int l;
+  l = k *= 4;
+  int m = 0;
+  int n;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
+
+void
+test ()
+{
+  foo <0> ();
+  bar <0> ();
+}
--- gcc/testsuite/g++.dg/warn/Wunused-var-41.C.jj       2025-04-23 
21:33:19.063931431 +0200
+++ gcc/testsuite/g++.dg/warn/Wunused-var-41.C  2025-04-23 21:33:19.063931431 
+0200
@@ -0,0 +1,69 @@
+// PR c/44677
+// { dg-do compile }
+// { dg-options "-O2 -Wunused-but-set-variable" }
+
+void baz (int);
+
+template <typename T>
+void
+foo (void)
+{
+  T a = 0;             // { dg-warning "variable 'a' set but not used" }
+  a = 1;
+  T b = 0;             // { dg-warning "variable 'b' set but not used" }
+  ++b;
+  T c = 0;             // { dg-warning "variable 'c' set but not used" }
+  c++;
+  T d = 0;             // { dg-warning "variable 'd' set but not used" }
+  --d;
+  T e = 0;             // { dg-warning "variable 'e' set but not used" }
+  e--;
+  T f = 0;             // { dg-warning "variable 'f' set but not used" }
+  f += 2;
+  T g = 0;             // { dg-warning "variable 'g' set but not used" }
+  g |= 2;
+  T h = 0;             // { dg-warning "variable 'h' set but not used" }
+  h -= 2;
+  T i = 0;             // { dg-warning "variable 'i' set but not used" }
+  i &= 2;
+  T j = 0;             // { dg-warning "variable 'j' set but not used" }
+  j ^= 2;
+  T k = 0;             // { dg-warning "variable 'k' set but not used" }
+  k *= 2;
+  T l = 0;             // { dg-warning "variable 'l' set but not used" }
+  l %= 2;
+  T m = 0;             // { dg-warning "variable 'm' set but not used" }
+  for (T n = 4; n < 10; n++, m++)
+    baz (n);
+}
+
+template <typename T>
+T
+bar (void)
+{
+  T a = 0;
+  T b = ++a;
+  T c = 0;
+  T d = --c;
+  T e = 0;
+  T f = e--;
+  T g = 0;
+  T h = g++;
+  T i = 0;
+  T j;
+  j = i += 42;
+  T k = 0;
+  T l;
+  l = k *= 4;
+  T m = 0;
+  T n;
+  n = m |= 2;
+  return b + d + f + h + j + l + n;
+}
+
+void
+test ()
+{
+  foo <int> ();
+  bar <int> ();
+}
--- gcc/testsuite/gcc.dg/memchr-3.c.jj  2024-01-08 23:26:44.000000000 +0100
+++ gcc/testsuite/gcc.dg/memchr-3.c     2025-04-24 07:57:16.045090120 +0200
@@ -17,9 +17,10 @@ struct SX
 const struct SX sx = { 0x1221 };
 const char sx_rep[] = { };
 
-void test_find (void)
+int test_find (void)
 {
   int n = 0, nb = (const char*)&sx.a - (const char*)&sx;
   const char *p = (const char*)&sx, *q = sx_rep;
   n += p + 1 == memchr (p, q[1], nb);
+  return n;
 }
--- gcc/testsuite/gcc.dg/unused-9.c.jj  2020-12-17 13:33:09.000000000 +0100
+++ gcc/testsuite/gcc.dg/unused-9.c     2025-04-24 08:07:57.850543927 +0200
@@ -2,12 +2,9 @@
 /* { dg-do compile } */
 /* { dg-options "-Wunused" } */
 
-
 void g(void)
 {
-  int i = 0;
-  volatile int x;
-  (x, i++);    /* { dg-bogus "set but not used" } */
+  int i = 0;           /* { dg-warning "variable 'i' set but not used" } */
+  volatile int x;      /* { dg-bogus "variable 'x' set but not used" } */
+  (x, i++);
 }
-
-

        Jakub

Reply via email to