[PATCH] c++: Fix bogus -Wvolatile warning in C++20 [PR98947]

Marek Polacek polacek@redhat.com
Thu Feb 4 00:03:19 GMT 2021


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.  So use
a warning sentinel.  But since we should still warn for

  (b ? x : y) += 1; // compound assignment
  (b ? (x = 2) : y) = 1; // lvalue-to-rvalue conv on x = 2

I've tweaked mark_use to only set TREE_THIS_VOLATILE when the warning
is enabled.

I'd argue this is a regression because GCC 9 doesn't warn.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10?

gcc/cp/ChangeLog:

	PR c++/98947
	* expr.c (mark_use) <case MODIFY_EXPR>: Only set TREE_THIS_VOLATILE
	if warn_volatile.
	* typeck.c (cp_build_modify_expr) <case COND_EXPR>: Add a warning
	sentinel for -Wvolatile around build_conditional_expr.

gcc/testsuite/ChangeLog:

	PR c++/98947
	* g++.dg/cpp2a/volatile5.C: New test.
---
 gcc/cp/expr.c                          |  3 ++-
 gcc/cp/typeck.c                        |  4 ++++
 gcc/testsuite/g++.dg/cpp2a/volatile5.C | 15 +++++++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/volatile5.C

diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 480e740f08c..d697978ce19 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -228,7 +228,8 @@ mark_use (tree expr, bool rvalue_p, bool read_p,
 	      && !cp_unevaluated_operand
 	      && (TREE_THIS_VOLATILE (lhs)
 		  || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
-	      && !TREE_THIS_VOLATILE (expr))
+	      && !TREE_THIS_VOLATILE (expr)
+	      && warn_volatile)
 	    {
 	      warning_at (location_of (expr), OPT_Wvolatile,
 			  "using value of simple assignment with %<volatile%>-"
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a87d5e5f2ac..52c2344530d 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8617,6 +8617,10 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	tree op2 = TREE_OPERAND (lhs, 2);
 	if (TREE_CODE (op2) != THROW_EXPR)
 	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
+	/* build_conditional_expr calls mark_lvalue_use for op1/op2,
+	   which are now assignments due to the above transformation,
+	   generating bogus C++20 warnings.  */
+	warning_sentinel w (warn_volatile);
 	tree cond = build_conditional_expr (input_location,
 					    TREE_OPERAND (lhs, 0), op1, op2,
 					    complain);
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 } }
+}

base-commit: 34215a7a3a359d700a520f1d5bdaec835f0b5180
-- 
2.29.2



More information about the Gcc-patches mailing list