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(-) 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); -- 2.45.1.145.g83f1add914