c: Fix up -Wunused-but-set-* warnings for _Atomics [PR99588]
As the following testcases show, compared to -D_Atomic= case we have many -Wunused-but-set-* warning false positives. When an _Atomic variable/parameter is read, we call mark_exp_read on it in convert_lvalue_to_rvalue, but build_atomic_assign does not. For consistency with the non-_Atomic case where we mark_exp_read the lhs for lhs op= ... but not for lhs = ..., this patch does that too. But furthermore we need to pattern match the trees emitted by _Atomic store, so that _Atomic store itself is not marked as being a variable read, but when the result of the store is used, we mark it. 2021-03-19 Jakub Jelinek <jakub@redhat.com> PR c/99588 * c-typeck.c (mark_exp_read): Recognize what build_atomic_assign with modifycode NOP_EXPR produces and mark the _Atomic var as read if found. (build_atomic_assign): For modifycode of NOP_EXPR, use COMPOUND_EXPRs rather than STATEMENT_LIST. Otherwise call mark_exp_read on lhs. Set TREE_SIDE_EFFECTS on the TARGET_EXPR. * gcc.dg/Wunused-var-5.c: New test. * gcc.dg/Wunused-var-6.c: New test.
This commit is contained in:
parent
e5d74554b5
commit
3279a9a5a9
3 changed files with 97 additions and 6 deletions
|
@ -1968,6 +1968,50 @@ mark_exp_read (tree exp)
|
|||
mark_exp_read (TREE_OPERAND (exp, 0));
|
||||
break;
|
||||
case COMPOUND_EXPR:
|
||||
/* Pattern match what build_atomic_assign produces with modifycode
|
||||
NOP_EXPR. */
|
||||
if (VAR_P (TREE_OPERAND (exp, 1))
|
||||
&& DECL_ARTIFICIAL (TREE_OPERAND (exp, 1))
|
||||
&& TREE_CODE (TREE_OPERAND (exp, 0)) == COMPOUND_EXPR)
|
||||
{
|
||||
tree t1 = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
||||
tree t2 = TREE_OPERAND (TREE_OPERAND (exp, 0), 1);
|
||||
if (TREE_CODE (t1) == TARGET_EXPR
|
||||
&& TARGET_EXPR_SLOT (t1) == TREE_OPERAND (exp, 1)
|
||||
&& TREE_CODE (t2) == CALL_EXPR)
|
||||
{
|
||||
tree fndecl = get_callee_fndecl (t2);
|
||||
tree arg = NULL_TREE;
|
||||
if (fndecl
|
||||
&& TREE_CODE (fndecl) == FUNCTION_DECL
|
||||
&& fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
|
||||
&& call_expr_nargs (t2) >= 2)
|
||||
switch (DECL_FUNCTION_CODE (fndecl))
|
||||
{
|
||||
case BUILT_IN_ATOMIC_STORE:
|
||||
arg = CALL_EXPR_ARG (t2, 1);
|
||||
break;
|
||||
case BUILT_IN_ATOMIC_STORE_1:
|
||||
case BUILT_IN_ATOMIC_STORE_2:
|
||||
case BUILT_IN_ATOMIC_STORE_4:
|
||||
case BUILT_IN_ATOMIC_STORE_8:
|
||||
case BUILT_IN_ATOMIC_STORE_16:
|
||||
arg = CALL_EXPR_ARG (t2, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (arg)
|
||||
{
|
||||
STRIP_NOPS (arg);
|
||||
if (TREE_CODE (arg) == ADDR_EXPR
|
||||
&& DECL_P (TREE_OPERAND (arg, 0))
|
||||
&& TYPE_ATOMIC (TREE_TYPE (TREE_OPERAND (arg, 0))))
|
||||
mark_exp_read (TREE_OPERAND (arg, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case C_MAYBE_CONST_EXPR:
|
||||
mark_exp_read (TREE_OPERAND (exp, 1));
|
||||
break;
|
||||
|
@ -4065,7 +4109,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
|
|||
vec<tree, va_gc> *params;
|
||||
tree val, nonatomic_lhs_type, nonatomic_rhs_type, newval, newval_addr;
|
||||
tree old, old_addr;
|
||||
tree compound_stmt;
|
||||
tree compound_stmt = NULL_TREE;
|
||||
tree stmt, goto_stmt;
|
||||
tree loop_label, loop_decl, done_label, done_decl;
|
||||
|
||||
|
@ -4086,7 +4130,15 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
|
|||
|
||||
/* Create a compound statement to hold the sequence of statements
|
||||
with a loop. */
|
||||
compound_stmt = c_begin_compound_stmt (false);
|
||||
if (modifycode != NOP_EXPR)
|
||||
{
|
||||
compound_stmt = c_begin_compound_stmt (false);
|
||||
|
||||
/* For consistency with build_modify_expr on non-_Atomic,
|
||||
mark the lhs as read. Also, it would be very hard to match
|
||||
such expressions in mark_exp_read. */
|
||||
mark_exp_read (lhs);
|
||||
}
|
||||
|
||||
/* Remove any excess precision (which is only present here in the
|
||||
case of compound assignments). */
|
||||
|
@ -4112,13 +4164,16 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
|
|||
TREE_NO_WARNING (val) = 1;
|
||||
rhs = build4 (TARGET_EXPR, nonatomic_rhs_type, val, rhs, NULL_TREE,
|
||||
NULL_TREE);
|
||||
TREE_SIDE_EFFECTS (rhs) = 1;
|
||||
SET_EXPR_LOCATION (rhs, loc);
|
||||
add_stmt (rhs);
|
||||
if (modifycode != NOP_EXPR)
|
||||
add_stmt (rhs);
|
||||
|
||||
/* NOP_EXPR indicates it's a straight store of the RHS. Simply issue
|
||||
an atomic_store. */
|
||||
if (modifycode == NOP_EXPR)
|
||||
{
|
||||
compound_stmt = rhs;
|
||||
/* Build __atomic_store (&lhs, &val, SEQ_CST) */
|
||||
rhs = build_unary_op (loc, ADDR_EXPR, val, false);
|
||||
fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_STORE);
|
||||
|
@ -4126,10 +4181,9 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
|
|||
params->quick_push (rhs);
|
||||
params->quick_push (seq_cst);
|
||||
func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
|
||||
add_stmt (func_call);
|
||||
|
||||
/* Finish the compound statement. */
|
||||
compound_stmt = c_end_compound_stmt (loc, compound_stmt, false);
|
||||
compound_stmt = build2 (COMPOUND_EXPR, void_type_node,
|
||||
compound_stmt, func_call);
|
||||
|
||||
/* VAL is the value which was stored, return a COMPOUND_STMT of
|
||||
the statement and that value. */
|
||||
|
|
23
gcc/testsuite/gcc.dg/Wunused-var-5.c
Normal file
23
gcc/testsuite/gcc.dg/Wunused-var-5.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* PR c/99588 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=c11 -Wunused-but-set-variable" } */
|
||||
|
||||
void bar (int, ...);
|
||||
void f1 (void) { static _Atomic int x = 0; bar (0, x); }
|
||||
void f2 (void) { static _Atomic int x = 0; bar (0, x += 1); }
|
||||
void f3 (void) { static _Atomic int x = 0; bar (x); }
|
||||
void f4 (void) { static _Atomic int x = 0; bar (x += 1); }
|
||||
void f5 (void) { static _Atomic int x = 0; bar (x = 1); }
|
||||
void f6 (void) { static _Atomic int x = 0; x = 1; } /* { dg-warning "variable 'x' set but not used" } */
|
||||
void f7 (void) { static _Atomic int x = 0; x += 3; }
|
||||
void f8 (void) { _Atomic int x = 0; bar (0, x); }
|
||||
void f9 (void) { _Atomic int x = 0; bar (0, x += 1); }
|
||||
void f10 (void) { _Atomic int x = 0; bar (x); }
|
||||
void f11 (void) { _Atomic int x = 0; bar (x += 1); }
|
||||
void f12 (void) { _Atomic int x = 0; bar (x = 1); }
|
||||
void f13 (void) { _Atomic int x = 0; x = 1; } /* { dg-warning "variable 'x' set but not used" } */
|
||||
void f14 (void) { _Atomic int x = 0; x += 3; }
|
||||
void f15 (void) { _Atomic int x = 0; int y = 3; x += y; }
|
||||
void f16 (void) { _Atomic int x = 0; int y = 3; bar (x += y); }
|
||||
void f17 (void) { _Atomic int x = 0; int y = 3; x = y; } /* { dg-warning "variable 'x' set but not used" } */
|
||||
void f18 (void) { _Atomic int x = 0; int y = 3; bar (x = y); }
|
14
gcc/testsuite/gcc.dg/Wunused-var-6.c
Normal file
14
gcc/testsuite/gcc.dg/Wunused-var-6.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* PR c/99588 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=c11 -Wunused-but-set-variable" } */
|
||||
|
||||
void bar (int, ...);
|
||||
struct S { int a, b, c; };
|
||||
typedef _Atomic struct S T;
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
static T x = (struct S) { 0, 0, 0 }; /* { dg-bogus "set but not used" } */
|
||||
bar (0, x = (struct S) { 1, 1, 1 });
|
||||
}
|
Loading…
Add table
Reference in a new issue