On 5/11/24 20:46, Patrick Palka wrote:
On Fri, 10 May 2024, Jason Merrill wrote:
On 5/9/24 16:23, Patrick Palka wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk/14? For trunk as a follow-up I can implement the
mentionted representation change to use CALL_EXPR instead of
MODOP_EXPR for a non-dependent simple assignment expression that
resolved to an operator= overload.
-- >8 --
r14-4111 made us check non-dependent assignment expressions ahead of
time, as well as give them a type. Unlike for compound assignment
expressions however, if a simple assignment resolves to an operator
overload we still represent it as a (typed) MODOP_EXPR instead of a
CALL_EXPR to the selected overload. This, I reckoned, was just a
pessimization (since we'll have to repeat overload resolution at
instantiatiation time) but should be harmless. (And it should be
easily fixable by giving cp_build_modify_expr an 'overload' parameter).
But it breaks the below testcase ultimately because MODOP_EXPR (of
non-reference type) is always treated as an lvalue according to
lvalue_kind, which is incorrect for the MODOP_EXPR representing x=42.
We can fix this by representing such assignment expressions as CALL_EXPRs
matching what that of compound assignments, but that turns out to
require some tweaking of our -Wparentheses warning logic which seems
unsuitable for backporting.
So this patch instead more conservatively fixes this by refining
lvalue_kind to consider the type of a (simple) MODOP_EXPR as we
already do for COND_EXPR.
PR c++/114994
gcc/cp/ChangeLog:
* tree.cc (lvalue_kind) <case MODOP_EXPR>: Consider the
type of a simple assignment expression.
gcc/testsuite/ChangeLog:
* g++.dg/template/non-dependent32.C: New test.
---
gcc/cp/tree.cc | 7 +++++++
.../g++.dg/template/non-dependent32.C | 18 ++++++++++++++++++
2 files changed, 25 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/template/non-dependent32.C
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index f1a23ffe817..0b97b789aab 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -275,6 +275,13 @@ lvalue_kind (const_tree ref)
/* We expect to see unlowered MODOP_EXPRs only during
template processing. */
gcc_assert (processing_template_decl);
+ if (TREE_CODE (TREE_OPERAND (ref, 1)) == NOP_EXPR
+ && CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0))))
+ /* As in the COND_EXPR case, but for non-dependent assignment
+ expressions created by build_x_modify_expr. */
+ goto default_;
This seems overly specific, I'd think the same thing would apply to += and
such?
We shouldn't see += etc of class type here since we already represent
those as CALL_EXPR to the selected operator=, but indeed it could
otherwise apply to +=. Like so?
OK.
-- >8 --
Subject: [PATCH] c++: lvalueness of non-dependent assignment expr [PR114994]
PR c++/114994
gcc/cp/ChangeLog:
* tree.cc (lvalue_kind) <case MODOP_EXPR>: Consider the
type of a class assignment expression.
gcc/testsuite/ChangeLog:
* g++.dg/template/non-dependent32.C: New test.
---
gcc/cp/tree.cc | 5 ++++-
.../g++.dg/template/non-dependent32.C | 18 ++++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/template/non-dependent32.C
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index f1a23ffe817..9d37d255d8d 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -275,7 +275,10 @@ lvalue_kind (const_tree ref)
/* We expect to see unlowered MODOP_EXPRs only during
template processing. */
gcc_assert (processing_template_decl);
- return clk_ordinary;
+ if (CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0))))
+ goto default_;
+ else
+ return clk_ordinary;
case MODIFY_EXPR:
case TYPEID_EXPR:
diff --git a/gcc/testsuite/g++.dg/template/non-dependent32.C
b/gcc/testsuite/g++.dg/template/non-dependent32.C
new file mode 100644
index 00000000000..54252c7dfaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent32.C
@@ -0,0 +1,18 @@
+// PR c++/114994
+// { dg-do compile { target c++11 } }
+
+struct udl_arg {
+ udl_arg operator=(int);
+};
+
+void f(udl_arg&&);
+
+template<class>
+void g() {
+ udl_arg x;
+ f(x=42); // { dg-bogus "cannot bind" }
+}
+
+int main() {
+ g<int>();
+}