diff mbox series

c++: represent all class non-dep assignments as CALL_EXPR

Message ID 20240515175548.591253-1-ppalka@redhat.com
State New
Headers show
Series c++: represent all class non-dep assignments as CALL_EXPR | expand

Commit Message

Patrick Palka May 15, 2024, 5:55 p.m. UTC
Bootstrapped and regtested on x86_64-pc-linu-xgnu, does this look OK
for trunk?

-- >8 --

Non-dependent compound assignment expressions are currently represented
as CALL_EXPR to the selected operator@= overload.  Non-dependent simple
assignments on the other hand are still represented as MODOP_EXPR, which
doesn't hold on to the selected overload.

That we need to remember the selected operator@= overload ahead of time
is a correctness thing, because they can be declared at namespace scope
and we don't want to consider later-declared namespace scope overloads
at instantiation time.  This doesn't apply to simple operator= because
it can only be declared at class scope, so it's fine to repeat the name
lookup and overload resolution at instantiation time.  But it still
seems desirable for sake of QoI to also avoid this repeated name lookup
and overload resolution for simple assignments along the lines of
r12-6075-g2decd2cabe5a4f.

To that end, this patch makes us represent non-dependent simple
assignments as CALL_EXPR to the selected operator= overload rather than
as MODOP_EXPR.  In order for is_assignment_op_expr_p to recognize such
CALL_EXPR as an assignment expression, cp_get_fndecl_from_callee needs
to look through templated COMPONENT_REF callee corresponding to a member
function call, otherwise ahead of time -Wparentheses warnings stop
working (e.g. g++.dg/warn/Wparentheses-{32,33}.C).

gcc/cp/ChangeLog:

	* call.cc (build_new_op): Pass 'overload' to
	cp_build_modify_expr.
	* cp-tree.h (cp_build_modify_expr): New overload that
	takes a tree* out-parameter.
	* pt.cc (tsubst_expr) <case CALL_EXPR>: Propagate
	OPT_Wparentheses warning suppression to the result.
	* cvt.cc (cp_get_fndecl_from_callee): Use maybe_get_fns
	to extract the FUNCTION_DECL from a callee.
	* semantics.cc (is_assignment_op_expr_p): Also recognize
	templated operator expressions represented as a CALL_EXPR
	to operator=.
	* typeck.cc (cp_build_modify_expr): Add 'overload'
	out-parameter and pass it to build_new_op.
	(build_x_modify_expr): Pass 'overload' to cp_build_modify_expr.
---
 gcc/cp/call.cc   |  2 +-
 gcc/cp/cp-tree.h |  3 +++
 gcc/cp/cvt.cc    |  5 +++--
 gcc/cp/pt.cc     |  2 ++
 gcc/cp/typeck.cc | 18 ++++++++++++++----
 5 files changed, 23 insertions(+), 7 deletions(-)

Comments

Jason Merrill May 16, 2024, 1:08 p.m. UTC | #1
On 5/15/24 13:55, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linu-xgnu, does this look OK
> for trunk?

OK.

> -- >8 --
> 
> Non-dependent compound assignment expressions are currently represented
> as CALL_EXPR to the selected operator@= overload.  Non-dependent simple
> assignments on the other hand are still represented as MODOP_EXPR, which
> doesn't hold on to the selected overload.
> 
> That we need to remember the selected operator@= overload ahead of time
> is a correctness thing, because they can be declared at namespace scope
> and we don't want to consider later-declared namespace scope overloads
> at instantiation time.  This doesn't apply to simple operator= because
> it can only be declared at class scope, so it's fine to repeat the name
> lookup and overload resolution at instantiation time.  But it still
> seems desirable for sake of QoI to also avoid this repeated name lookup
> and overload resolution for simple assignments along the lines of
> r12-6075-g2decd2cabe5a4f.
> 
> To that end, this patch makes us represent non-dependent simple
> assignments as CALL_EXPR to the selected operator= overload rather than
> as MODOP_EXPR.  In order for is_assignment_op_expr_p to recognize such
> CALL_EXPR as an assignment expression, cp_get_fndecl_from_callee needs
> to look through templated COMPONENT_REF callee corresponding to a member
> function call, otherwise ahead of time -Wparentheses warnings stop
> working (e.g. g++.dg/warn/Wparentheses-{32,33}.C).
> 
> gcc/cp/ChangeLog:
> 
> 	* call.cc (build_new_op): Pass 'overload' to
> 	cp_build_modify_expr.
> 	* cp-tree.h (cp_build_modify_expr): New overload that
> 	takes a tree* out-parameter.
> 	* pt.cc (tsubst_expr) <case CALL_EXPR>: Propagate
> 	OPT_Wparentheses warning suppression to the result.
> 	* cvt.cc (cp_get_fndecl_from_callee): Use maybe_get_fns
> 	to extract the FUNCTION_DECL from a callee.
> 	* semantics.cc (is_assignment_op_expr_p): Also recognize
> 	templated operator expressions represented as a CALL_EXPR
> 	to operator=.
> 	* typeck.cc (cp_build_modify_expr): Add 'overload'
> 	out-parameter and pass it to build_new_op.
> 	(build_x_modify_expr): Pass 'overload' to cp_build_modify_expr.
> ---
>   gcc/cp/call.cc   |  2 +-
>   gcc/cp/cp-tree.h |  3 +++
>   gcc/cp/cvt.cc    |  5 +++--
>   gcc/cp/pt.cc     |  2 ++
>   gcc/cp/typeck.cc | 18 ++++++++++++++----
>   5 files changed, 23 insertions(+), 7 deletions(-)
> 
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index e058da7735f..e3d4cf8949d 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -7473,7 +7473,7 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags,
>     switch (code)
>       {
>       case MODIFY_EXPR:
> -      return cp_build_modify_expr (loc, arg1, code2, arg2, complain);
> +      return cp_build_modify_expr (loc, arg1, code2, arg2, overload, complain);
>   
>       case INDIRECT_REF:
>         return cp_build_indirect_ref (loc, arg1, RO_UNARY_STAR, complain);
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 9a8c8659157..1e565086e80 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -8267,6 +8267,9 @@ extern tree cp_build_c_cast			(location_t, tree, tree,
>   extern cp_expr build_x_modify_expr		(location_t, tree,
>   						 enum tree_code, tree,
>   						 tree, tsubst_flags_t);
> +extern tree cp_build_modify_expr		(location_t, tree,
> +						 enum tree_code, tree,
> +						 tree *, tsubst_flags_t);
>   extern tree cp_build_modify_expr		(location_t, tree,
>   						 enum tree_code, tree,
>   						 tsubst_flags_t);
> diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
> index db086c017e8..2f4c0f88694 100644
> --- a/gcc/cp/cvt.cc
> +++ b/gcc/cp/cvt.cc
> @@ -1015,8 +1015,9 @@ cp_get_fndecl_from_callee (tree fn, bool fold /* = true */)
>         return f;
>       };
>   
> -  if (TREE_CODE (fn) == FUNCTION_DECL)
> -    return fn_or_local_alias (fn);
> +  if (tree f = maybe_get_fns (fn))
> +    if (TREE_CODE (f) == FUNCTION_DECL)
> +      return fn_or_local_alias (f);
>     tree type = TREE_TYPE (fn);
>     if (type == NULL_TREE || !INDIRECT_TYPE_P (type))
>       return NULL_TREE;
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 32640f8e946..d83f530ac8d 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -21093,6 +21093,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   	    if (warning_suppressed_p (t, OPT_Wpessimizing_move))
>   	      /* This also suppresses -Wredundant-move.  */
>   	      suppress_warning (ret, OPT_Wpessimizing_move);
> +	    if (warning_suppressed_p (t, OPT_Wparentheses))
> +	      suppress_warning (STRIP_REFERENCE_REF (ret), OPT_Wparentheses);
>   	  }
>   
>   	RETURN (ret);
> diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
> index 5f16994300f..75b696e32e0 100644
> --- a/gcc/cp/typeck.cc
> +++ b/gcc/cp/typeck.cc
> @@ -9421,7 +9421,7 @@ build_modify_expr (location_t location,
>   
>   tree
>   cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
> -		      tree rhs, tsubst_flags_t complain)
> +		      tree rhs, tree *overload, tsubst_flags_t complain)
>   {
>     lhs = mark_lvalue_use_nonread (lhs);
>   
> @@ -9533,7 +9533,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>   	  rhs = unshare_expr (rhs);
>   	tree op2 = TREE_OPERAND (lhs, 2);
>   	if (TREE_CODE (op2) != THROW_EXPR)
> -	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
> +	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs,
> +				      overload, complain);
>   	tree cond = build_conditional_expr (input_location,
>   					    TREE_OPERAND (lhs, 0), op1, op2,
>   					    complain);
> @@ -9620,7 +9621,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>   	      result = build_new_op (input_location, MODIFY_EXPR,
>   				     LOOKUP_NORMAL, lhs, rhs,
>   				     make_node (NOP_EXPR), NULL_TREE,
> -				     /*overload=*/NULL, complain);
> +				     overload, complain);
>   	      if (result == NULL_TREE)
>   		return error_mark_node;
>   	      goto ret;
> @@ -9828,6 +9829,14 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>     return result;
>   }
>   
> +tree
> +cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
> +		      tree rhs, tsubst_flags_t complain)
> +{
> +  return cp_build_modify_expr (loc, lhs, modifycode, rhs,
> +			       /*overload=*/nullptr, complain);
> +}
> +
>   cp_expr
>   build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>   		     tree rhs, tree lookups, tsubst_flags_t complain)
> @@ -9856,7 +9865,8 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>   
>     tree rval;
>     if (modifycode == NOP_EXPR)
> -    rval = cp_build_modify_expr (loc, lhs, modifycode, rhs, complain);
> +    rval = cp_build_modify_expr (loc, lhs, modifycode, rhs,
> +				 &overload, complain);
>     else
>       rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL,
>   			 lhs, rhs, op, lookups, &overload, complain);
diff mbox series

Patch

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index e058da7735f..e3d4cf8949d 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -7473,7 +7473,7 @@  build_new_op (const op_location_t &loc, enum tree_code code, int flags,
   switch (code)
     {
     case MODIFY_EXPR:
-      return cp_build_modify_expr (loc, arg1, code2, arg2, complain);
+      return cp_build_modify_expr (loc, arg1, code2, arg2, overload, complain);
 
     case INDIRECT_REF:
       return cp_build_indirect_ref (loc, arg1, RO_UNARY_STAR, complain);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9a8c8659157..1e565086e80 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8267,6 +8267,9 @@  extern tree cp_build_c_cast			(location_t, tree, tree,
 extern cp_expr build_x_modify_expr		(location_t, tree,
 						 enum tree_code, tree,
 						 tree, tsubst_flags_t);
+extern tree cp_build_modify_expr		(location_t, tree,
+						 enum tree_code, tree,
+						 tree *, tsubst_flags_t);
 extern tree cp_build_modify_expr		(location_t, tree,
 						 enum tree_code, tree,
 						 tsubst_flags_t);
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index db086c017e8..2f4c0f88694 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1015,8 +1015,9 @@  cp_get_fndecl_from_callee (tree fn, bool fold /* = true */)
       return f;
     };
 
-  if (TREE_CODE (fn) == FUNCTION_DECL)
-    return fn_or_local_alias (fn);
+  if (tree f = maybe_get_fns (fn))
+    if (TREE_CODE (f) == FUNCTION_DECL)
+      return fn_or_local_alias (f);
   tree type = TREE_TYPE (fn);
   if (type == NULL_TREE || !INDIRECT_TYPE_P (type))
     return NULL_TREE;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 32640f8e946..d83f530ac8d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21093,6 +21093,8 @@  tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	    if (warning_suppressed_p (t, OPT_Wpessimizing_move))
 	      /* This also suppresses -Wredundant-move.  */
 	      suppress_warning (ret, OPT_Wpessimizing_move);
+	    if (warning_suppressed_p (t, OPT_Wparentheses))
+	      suppress_warning (STRIP_REFERENCE_REF (ret), OPT_Wparentheses);
 	  }
 
 	RETURN (ret);
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 5f16994300f..75b696e32e0 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -9421,7 +9421,7 @@  build_modify_expr (location_t location,
 
 tree
 cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
-		      tree rhs, tsubst_flags_t complain)
+		      tree rhs, tree *overload, tsubst_flags_t complain)
 {
   lhs = mark_lvalue_use_nonread (lhs);
 
@@ -9533,7 +9533,8 @@  cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	  rhs = unshare_expr (rhs);
 	tree op2 = TREE_OPERAND (lhs, 2);
 	if (TREE_CODE (op2) != THROW_EXPR)
-	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
+	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs,
+				      overload, complain);
 	tree cond = build_conditional_expr (input_location,
 					    TREE_OPERAND (lhs, 0), op1, op2,
 					    complain);
@@ -9620,7 +9621,7 @@  cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	      result = build_new_op (input_location, MODIFY_EXPR,
 				     LOOKUP_NORMAL, lhs, rhs,
 				     make_node (NOP_EXPR), NULL_TREE,
-				     /*overload=*/NULL, complain);
+				     overload, complain);
 	      if (result == NULL_TREE)
 		return error_mark_node;
 	      goto ret;
@@ -9828,6 +9829,14 @@  cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
   return result;
 }
 
+tree
+cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
+		      tree rhs, tsubst_flags_t complain)
+{
+  return cp_build_modify_expr (loc, lhs, modifycode, rhs,
+			       /*overload=*/nullptr, complain);
+}
+
 cp_expr
 build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 		     tree rhs, tree lookups, tsubst_flags_t complain)
@@ -9856,7 +9865,8 @@  build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 
   tree rval;
   if (modifycode == NOP_EXPR)
-    rval = cp_build_modify_expr (loc, lhs, modifycode, rhs, complain);
+    rval = cp_build_modify_expr (loc, lhs, modifycode, rhs,
+				 &overload, complain);
   else
     rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL,
 			 lhs, rhs, op, lookups, &overload, complain);