]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c, c++: Extend -Wunused-but-set-* warnings [PR44677]
authorJakub Jelinek <jakub@redhat.com>
Tue, 15 Jul 2025 13:00:33 +0000 (15:00 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 15 Jul 2025 13:00:33 +0000 (15:00 +0200)
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.

2025-07-15  Jakub Jelinek  <jakub@redhat.com>
    Jason Merrill  <jason@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 on lhs of MODIFY_EXPR
after cp_fold_rvalue if it wasn't set before.
* 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): Return early for
PRE{IN,DE}CREMENT_EXPR.
* 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/cobol/
* gcobolspec.cc (lang_specific_driver): Remove unused but set variable
n_cobol_files.
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.

40 files changed:
gcc/c-family/c-attribs.cc
gcc/c-family/c-opts.cc
gcc/c/c-decl.cc
gcc/c/c-parser.cc
gcc/c/c-typeck.cc
gcc/cobol/gcobolspec.cc
gcc/common.opt
gcc/common.opt.urls
gcc/cp/cp-gimplify.cc
gcc/cp/decl.cc
gcc/cp/expr.cc
gcc/cp/module.cc
gcc/cp/semantics.cc
gcc/cp/typeck.cc
gcc/diagnostic-spec.cc
gcc/doc/invoke.texi
gcc/gimple-ssa-store-merging.cc
gcc/go/gofrontend/gogo.cc
gcc/ipa-strub.cc
gcc/testsuite/c-c++-common/Wunused-parm-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-parm-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-parm-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-parm-4.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-parm-5.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-parm-6.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-var-19.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-var-20.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-var-21.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-var-22.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-var-23.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-var-24.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wunused-var-7.c
gcc/testsuite/g++.dg/cpp26/name-independent-decl1.C
gcc/testsuite/g++.dg/warn/Wunused-parm-12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wunused-parm-13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wunused-var-2.C
gcc/testsuite/g++.dg/warn/Wunused-var-40.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wunused-var-41.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/memchr-3.c
gcc/testsuite/gcc.dg/unused-9.c

index 5d7a31fd99b644f05f32754dc113f87f96c0a9f2..ac215344f30019d14822a81e828f5e3c4a048a0d 100644 (file)
@@ -5858,8 +5858,7 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr)
             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))
index 872bdf4ea2467d773af86189360964b362e6cd15..795f5a355af6fe8ae4909ab48598188f22aa3bb7 100644 (file)
@@ -1226,6 +1226,17 @@ c_common_post_options (const char **pfilename)
   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)
index 8bbd6ebc66ad81b1fa1b19da2cf55fbb4bf34be2..acbe2b88e674882c4123208b2098d1cf6ea61137 100644 (file)
@@ -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);
            }
 
@@ -11465,9 +11465,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);
     }
 
index 0c3e3e2889c60c08d91569d41b324ffe0e1b4c7c..5119841a589522ed0904aa21961f9475994fe5a2 100644 (file)
@@ -10547,15 +10547,31 @@ c_parser_unary_expression (c_parser *parser)
       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);
@@ -13933,7 +13949,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          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);
@@ -13945,7 +13971,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          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);
index 9a5eb0da3a1ddd2b1abdd55fddb92680822a808b..5d11e576dc99ee85218c31fdae0609661f28300e 100644 (file)
@@ -2310,14 +2310,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:
@@ -7308,8 +7324,21 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
                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.  */
index 9532d4256b22c466d0251a63610171608f3467e1..038aaec13469c768a94a860ad3fc29d95111674f 100644 (file)
@@ -142,9 +142,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
   int n_infiles = 0;
   int n_outfiles = 0;
 
-  // The number of input files when the language is "none" or "cobol"
-  int n_cobol_files = 0;
-
   // saw_OPT_no_main means "don't expect -main"
   bool saw_OPT_no_main = false;
 
@@ -234,11 +231,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
       case OPT_SPECIAL_input_file:
         no_files_error = false;
         n_infiles += 1;
-        if(    strcmp(language, "none")  == 0
-            || strcmp(language, "cobol") == 0 )
-          {
-          n_cobol_files += 1;
-          }
         if( strstr(decoded_options[i].orig_option_with_args_text, "libgcobol.a") )
           {
           // We have been given an explicit libgcobol.a.  We need to note that.
index 3d65656e658caebd1462381bd0bffe6da69466f2..d68d7d8d91489ee0d1ebfc3766d2739901c54a4e 100644 (file)
@@ -851,11 +851,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
index a507168d4092cb1d486b4dd5421e37367628999a..38dd9d3175980bd0242e02fa59ebc0e4a6d9e389 100644 (file)
@@ -272,9 +272,15 @@ UrlSuffix(gcc/Warning-Options.html#index-Wno-unused)
 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)
 
index 882a943391cbbae1dc1834df97654f1524f5b6f7..addbc29d104bd11f431e5822880d9b6de6c4b5d2 100644 (file)
@@ -3217,7 +3217,15 @@ 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))
+       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
index 843f0e4fd160e3a480cc5e37e9c38817fe03d6f1..4752874fc97aafa54bdf940933011d9b1d7bbfaf 100644 (file)
@@ -747,11 +747,11 @@ poplevel (int keep, int reverse, int functionbody)
              {
                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;
              }
@@ -19496,14 +19496,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;
     }
index 2157cfba2ebbc330aa1c591ec51f29d61e868844..8b5a098ecb379babe97d4698bf43c1abf52beffb 100644 (file)
@@ -211,8 +211,27 @@ mark_use (tree expr, bool rvalue_p, bool read_p,
            }
          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:
index 689319ad9213710d0137395d9ea69435e0ce999f..e3c1a686b7327599f4ed8e47002859458cf24707 100644 (file)
@@ -11124,8 +11124,7 @@ trees_in::fn_parms_fini (int tag, tree fn, tree existing, bool is_defn)
 {
   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)
        {
index 77fac458ec8cc0541851268b2f1dfee30836bd66..640e1eab7d35973b5ac2b57e1f1afbda13d0aeba 100644 (file)
@@ -3741,6 +3741,11 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
   if (!(complain & tf_warning))
     return result;
 
+  /* These will never fold into a constant, so no need to check for
+     overflow for them.  */
+  if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+    return result;
+
   tree result_ovl = result;
   tree expr_ovl = expr;
 
index 0bf5ae4e4e2654a5ccd4f759b31491e3a5f21c66..a604511db71066c2e3822e175fa2e0300c3c4d7c 100644 (file)
@@ -7680,7 +7680,18 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
       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.  */
@@ -9796,7 +9807,22 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
          {
            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)
index df7857988b6a750d291c5ed579adef7ed8015f2e..b43ae637c16179461bfb32dfdce2b9de5c4671e6 100644 (file)
@@ -72,9 +72,9 @@ nowarn_spec_t::nowarn_spec_t (opt_code opt)
     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;
 
index f60865bdc6eea7b9779fa651931accfc476bb2cf..09802303254c0191cc0818d966b9da683df4c4d6 100644 (file)
@@ -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
@@ -7921,27 +7922,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
index 90f449ce82f489628e9b4b819f100aab61e2e930..ce56d97d43836b4193b047cb413f22ecc3d5f735 100644 (file)
@@ -644,9 +644,7 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit)
 
          /* 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;
 
index 3aad4194c628920d59026e259a2037acd0ac1716..566eca82e4d68bf74caab6098148a703503e3ef9 100644 (file)
@@ -5987,12 +5987,11 @@ Function::export_func_with_type(Export* exp, const Named_object* no,
   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;
index d7c0a928600265ad8b7382b085c7d9b8ec095494..86270af3dbae84e8094cc1f8ef6defa77482284e 100644 (file)
@@ -3059,6 +3059,8 @@ pass_ipa_strub::execute (function *)
                         TYPE_ATTRIBUTES (TREE_TYPE (nnode->decl)));
        }
     }
+#else
+    (void) named_args;
 #endif
 
     {
diff --git a/gcc/testsuite/c-c++-common/Wunused-parm-1.c b/gcc/testsuite/c-c++-common/Wunused-parm-1.c
new file mode 100644 (file)
index 0000000..355fa4a
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-parm-2.c b/gcc/testsuite/c-c++-common/Wunused-parm-2.c
new file mode 100644 (file)
index 0000000..2caea94
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-parm-3.c b/gcc/testsuite/c-c++-common/Wunused-parm-3.c
new file mode 100644 (file)
index 0000000..2978cd4
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-parm-4.c b/gcc/testsuite/c-c++-common/Wunused-parm-4.c
new file mode 100644 (file)
index 0000000..063b40f
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-parm-5.c b/gcc/testsuite/c-c++-common/Wunused-parm-5.c
new file mode 100644 (file)
index 0000000..1c80a82
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-parm-6.c b/gcc/testsuite/c-c++-common/Wunused-parm-6.c
new file mode 100644 (file)
index 0000000..ee328bd
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-var-19.c b/gcc/testsuite/c-c++-common/Wunused-var-19.c
new file mode 100644 (file)
index 0000000..32c47e6
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-var-20.c b/gcc/testsuite/c-c++-common/Wunused-var-20.c
new file mode 100644 (file)
index 0000000..e25b26b
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-var-21.c b/gcc/testsuite/c-c++-common/Wunused-var-21.c
new file mode 100644 (file)
index 0000000..0732d98
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-var-22.c b/gcc/testsuite/c-c++-common/Wunused-var-22.c
new file mode 100644 (file)
index 0000000..84f57c5
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-var-23.c b/gcc/testsuite/c-c++-common/Wunused-var-23.c
new file mode 100644 (file)
index 0000000..b74c3f4
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/c-c++-common/Wunused-var-24.c b/gcc/testsuite/c-c++-common/Wunused-var-24.c
new file mode 100644 (file)
index 0000000..a59f50a
--- /dev/null
@@ -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;
+}
index 74196436db886f03ca4b7bf3eb2e61d279d42a16..ea6babda683fb9bad36c5ed2098042e87e1b8834 100644 (file)
@@ -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;
index 0830ce863f9d6fcb17d6cd16978c00b0645c393d..9b56e841583f165cf78ad7e2f586ff267c1476e6 100644 (file)
@@ -70,7 +70,7 @@ foo ()
       ++_;
     }
     {
-      static int _ = 3;
+      static int _ = 3;                // { dg-warning "variable '_' set but not used" }
       ++_;
     }
     {
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-parm-12.C b/gcc/testsuite/g++.dg/warn/Wunused-parm-12.C
new file mode 100644 (file)
index 0000000..03029f9
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-parm-13.C b/gcc/testsuite/g++.dg/warn/Wunused-parm-13.C
new file mode 100644 (file)
index 0000000..f2d357f
--- /dev/null
@@ -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);
+}
index 0b21ef11625715e1b068b49267159a7740004914..869065fda63bba04ab375baa25c2893f4eaf11c5 100644 (file)
@@ -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;
 }
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-var-40.C b/gcc/testsuite/g++.dg/warn/Wunused-var-40.C
new file mode 100644 (file)
index 0000000..9351367
--- /dev/null
@@ -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> ();
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-var-41.C b/gcc/testsuite/g++.dg/warn/Wunused-var-41.C
new file mode 100644 (file)
index 0000000..ff981ee
--- /dev/null
@@ -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> ();
+}
index 9a357351950038197c90ad689634a8406de96234..9caa2ac30f0b64daebff98e447a6b5690598268a 100644 (file)
@@ -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;
 }
index bdf36e1f50e83eadaa1352fdc5bd1d1b5f7096d4..ad1ad0ec8abc14506477eea983bb3ae0fe3e0fea 100644 (file)
@@ -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++);
 }
-
-