c++: Fix bogus -Wvolatile warning in C++20 [PR98947]
authorMarek Polacek <polacek@redhat.com>
Wed, 3 Feb 2021 22:57:22 +0000 (17:57 -0500)
committerMarek Polacek <polacek@redhat.com>
Fri, 5 Feb 2021 16:11:04 +0000 (11:11 -0500)
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) <case MODIFY_EXPR>: 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.

gcc/cp/call.c
gcc/cp/expr.c
gcc/testsuite/g++.dg/cpp2a/volatile5.C [new file with mode: 0644]

index c7e13f3a22bcf73ea58de44af18a161c97b0cb2a..4744c9768ecc9d4329c72ec077404d42dccd4f89 100644 (file)
@@ -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;
     }
 
index 480e740f08c9a9b496f5d5641c3ce5755d468bf1..d16d1896f2ddd08264b389b02b9640cca332ec13 100644 (file)
@@ -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 %<volatile%>-"
-                         "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 "
+                             "%<volatile%>-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 (file)
index 0000000..1f9d238
--- /dev/null
@@ -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 } }
+}