On 2/4/21 6:09 PM, Marek Polacek wrote:
On Thu, Feb 04, 2021 at 03:47:54PM -0500, Jason Merrill via Gcc-patches wrote:
On 2/4/21 1:11 PM, Marek Polacek wrote:
On Thu, Feb 04, 2021 at 10:59:21AM -0500, Jason Merrill wrote:
On 2/3/21 7:03 PM, Marek Polacek wrote:
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
Hmm, that seems wrong; the ?: expression itself does not use lvalue operands
any more than ',' does. I notice that removing those mark_lvalue_use calls
doesn't regress Wunused-var-10.c, which was added with them in r160289.
The mark_lvalue_use calls didn't strike me as wrong because [expr.cond]/7
says that lvalue-to-rvalue conversion is performed on the second and third
operands.
Only after we've decided (in /6) that the result is a prvalue.
Oh, I see. :~
With those mark_lvalue_use calls removed, we'd not issue the
warning for
(b ? (x = 2) : y) = 1;
(b ? x : (y = 5)) = 1;
Why wouldn't we? The assignment should call mark_lvalue_use for the LHS,
which recursively applies it to the arms of the ?:.
Aha: we call mark_lvalue_use_*nonread* and the warning was guarded by
read_p. I don't know why I did it, I see no regressions if I just
remove the check. And then I get the expected results.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10?
OK.
-- >8 --
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 | 2 --
gcc/cp/expr.c | 14 +++++++-------
gcc/testsuite/g++.dg/cpp2a/volatile5.C | 15 +++++++++++++++
3 files changed, 22 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/volatile5.C
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 %<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
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: 4e7c24d97dd65083a770252ce942f43d408fe11d