On 4/24/25 3:50 AM, Jakub Jelinek wrote:
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?
--- 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;
Why does this need to happen in cp_fold? Weren't the flags set properly
at build time?
@@ -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:
Why is this specific to these codes? I would think we would want
consistent handling of (void) here and in mark_exp_read.
@@ -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);
Again I wonder why cp_fold is setting DECL_READ_P.
Jason