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;
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;
/* 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). */
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);
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. */
--- /dev/null
+/* 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); }