]> git.ipfire.org Git - thirdparty/gcc.git/commit
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)
commit0eac9cfee8cb0b21de866a04d5d59685ab35208f
tree32bfa247beeb267aeab23a41ac0a32c5449ec0bf
parent365ffdc172c3683a84455de8c437bbe29f5aba46
c, c++: Extend -Wunused-but-set-* warnings [PR44677]

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