From: Marek Polacek Date: Wed, 3 Feb 2021 22:57:22 +0000 (-0500) Subject: c++: Fix bogus -Wvolatile warning in C++20 [PR98947] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7a18bc4ae62081021f4fd90d591a588cac931f77;p=gcc.git c++: Fix bogus -Wvolatile warning in C++20 [PR98947] Since most of volatile is deprecated in C++20, we are required to warn for compound assignments to volatile variables and so on. But here we have volatile int x, y, z; (b ? x : y) = 1; and we shouldn't warn, because simple assignments like x = 24; should not provoke the warning when they are a discarded-value expression. We warn here because when ?: is used as an lvalue, we transform it in cp_build_modify_expr/COND_EXPR from (a ? b : c) = rhs to (a ? (b = rhs) : (c = rhs)) and build_conditional_expr then calls mark_lvalue_use for the new artificial assignments, which then evokes the warning. The calls to mark_lvalue_use were added in r160289 to suppress warnings in Wunused-var-10.c, but looks like they're no longer needed. To warn on (b ? (x = 2) : y) = 1; (b ? x : (y = 5)) = 1; I've tweaked a check in mark_use/MODIFY_EXPR. I'd argue this is a regression because GCC 9 doesn't warn. gcc/cp/ChangeLog: PR c++/98947 * call.c (build_conditional_expr_1): Don't call mark_lvalue_use on arg2/arg3. * expr.c (mark_use) : Don't check read_p when issuing the -Wvolatile warning. Only set TREE_THIS_VOLATILE if a warning was emitted. gcc/testsuite/ChangeLog: PR c++/98947 * g++.dg/cpp2a/volatile5.C: New test. --- diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c7e13f3a22b..4744c9768ec 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5559,8 +5559,6 @@ build_conditional_expr_1 (const op_location_t &loc, && same_type_p (arg2_type, arg3_type)) { result_type = arg2_type; - arg2 = mark_lvalue_use (arg2); - arg3 = mark_lvalue_use (arg3); goto valid_operands; } diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 480e740f08c..d16d1896f2d 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -224,17 +224,17 @@ mark_use (tree expr, bool rvalue_p, bool read_p, a volatile-qualified type is deprecated unless the assignment is either a discarded-value expression or appears in an unevaluated context." */ - if (read_p - && !cp_unevaluated_operand + if (!cp_unevaluated_operand && (TREE_THIS_VOLATILE (lhs) || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs))) && !TREE_THIS_VOLATILE (expr)) { - warning_at (location_of (expr), OPT_Wvolatile, - "using value of simple assignment with %-" - "qualified left operand is deprecated"); - /* Make sure not to warn about this assignment again. */ - TREE_THIS_VOLATILE (expr) = true; + if (warning_at (location_of (expr), OPT_Wvolatile, + "using value of simple assignment with " + "%-qualified left operand is " + "deprecated")) + /* Make sure not to warn about this assignment again. */ + TREE_THIS_VOLATILE (expr) = true; } break; } diff --git a/gcc/testsuite/g++.dg/cpp2a/volatile5.C b/gcc/testsuite/g++.dg/cpp2a/volatile5.C new file mode 100644 index 00000000000..1f9d23845b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/volatile5.C @@ -0,0 +1,15 @@ +// PR c++/98947 +// { dg-do compile } + +volatile int x, y, z; + +void +f (bool b) +{ + (b ? x : y) = 1; + (b ? x : y) += 1; // { dg-warning "compound assignment" "" { target c++20 } } + z = (b ? x : y) = 1; // { dg-warning "using value of simple assignment" "" { target c++20 } } + ((z = 2) ? x : y) = 1; // { dg-warning "using value of simple assignment" "" { target c++20 } } + (b ? (x = 2) : y) = 1; // { dg-warning "using value of simple assignment" "" { target c++20 } } + (b ? x : (y = 5)) = 1; // { dg-warning "using value of simple assignment" "" { target c++20 } } +}