diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 4e84e2f99874cea7ab438cdc9ff5566d8a44ea22..a6c9e68a19ee2682357a81fe17b69247e00209f1 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -9116,7 +9116,7 @@ static const char *const op_bind_attrname = "operator bindings"; void maybe_save_operator_binding (tree e) { - /* This is only useful in a generic lambda. */ + /* This is only useful in a template. */ if (!processing_template_decl) return; @@ -9124,13 +9124,12 @@ maybe_save_operator_binding (tree e) if (!cfn) return; - /* Do this for lambdas and code that will emit a CMI. In a module's - GMF we don't yet know whether there will be a CMI. */ - if (!module_has_cmi_p () && !global_purview_p () && !current_lambda_expr()) - return; - - tree fnname = ovl_op_identifier (false, TREE_CODE (e)); - if (!fnname) + tree fnname; + if(TREE_CODE (e) == MODOP_EXPR) + fnname = ovl_op_identifier (true, TREE_CODE (TREE_OPERAND (e, 1))); + else + fnname = ovl_op_identifier (false, TREE_CODE (e)); + if (!fnname || fnname == assign_op_identifier) return; tree attributes = DECL_ATTRIBUTES (cfn); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 5af47ce89a94f288b2a3dfded8f2ab6338d3767c..9002dd14faecc4bc831dfec8b660fda19c7e483e 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -7274,7 +7274,11 @@ build_x_compound_expr (location_t loc, tree op1, tree op2, { if (type_dependent_expression_p (op1) || type_dependent_expression_p (op2)) - return build_min_nt_loc (loc, COMPOUND_EXPR, op1, op2); + { + result = build_min_nt_loc (loc, COMPOUND_EXPR, op1, op2); + maybe_save_operator_binding (result); + return result; + } op1 = build_non_dependent_expr (op1); op2 = build_non_dependent_expr (op2); } @@ -8938,7 +8942,6 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, tree orig_lhs = lhs; tree orig_rhs = rhs; tree overload = NULL_TREE; - tree op = build_nt (modifycode, NULL_TREE, NULL_TREE); if (lhs == error_mark_node || rhs == error_mark_node) return cp_expr (error_mark_node, loc); @@ -8948,9 +8951,12 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, if (modifycode == NOP_EXPR || type_dependent_expression_p (lhs) || type_dependent_expression_p (rhs)) - return build_min_nt_loc (loc, MODOP_EXPR, lhs, - build_min_nt_loc (loc, modifycode, NULL_TREE, - NULL_TREE), rhs); + { + tree op = build_min_nt_loc (loc, modifycode, NULL_TREE, NULL_TREE); + tree rval = build_min_nt_loc (loc, MODOP_EXPR, lhs, op, rhs); + maybe_save_operator_binding (rval); + return rval; + } lhs = build_non_dependent_expr (lhs); rhs = build_non_dependent_expr (rhs); @@ -8958,6 +8964,7 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, if (modifycode != NOP_EXPR) { + tree op = build_nt (modifycode, NULL_TREE, NULL_TREE); tree rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, op, &overload, complain); if (rval) diff --git a/gcc/testsuite/g++.dg/lookup/operator-3.C b/gcc/testsuite/g++.dg/lookup/operator-3.C new file mode 100644 index 0000000000000000000000000000000000000000..bc5eb3d6693ebc48a367f0e8e2b851083807722c --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-3.C @@ -0,0 +1,109 @@ +// PR c++/51577 + +template <class T> void f (T x) { + +x; // { dg-error "no match" } + -x; // { dg-error "no match" } + *x; // { dg-error "no match" } + ~x; // { dg-error "no match" } + &x; + !x; // { dg-error "no match" } + ++x; // { dg-error "no match" } + --x; // { dg-error "no match" } + x++; // { dg-error "declared for postfix" } + x--; // { dg-error "declared for postfix" } + + x->*x; // { dg-error "no match" } + x / x; // { dg-error "no match" } + x * x; // { dg-error "no match" } + x + x; // { dg-error "no match" } + x - x; // { dg-error "no match" } + x % x; // { dg-error "no match" } + x & x; // { dg-error "no match" } + x | x; // { dg-error "no match" } + x ^ x; // { dg-error "no match" } + x << x; // { dg-error "no match" } + x >> x; // { dg-error "no match" } + x && x; // { dg-error "no match" } + x || x; // { dg-error "no match" } + x, x; + + x == x; // { dg-error "no match" } + x != x; // { dg-error "no match" } + x < x; // { dg-error "no match" } + x > x; // { dg-error "no match" } + x <= x; // { dg-error "no match" } + x >= x; // { dg-error "no match" } +#if __cplusplus > 201703L + x <=> x; // { dg-error "no match" "" { target c++20 } } +#endif + + x += x; // { dg-error "no match" } + x -= x; // { dg-error "no match" } + x *= x; // { dg-error "no match" } + x /= x; // { dg-error "no match" } + x %= x; // { dg-error "no match" } + x |= x; // { dg-error "no match" } + x ^= x; // { dg-error "no match" } + x <<= x; // { dg-error "no match" } + x >>= x; // { dg-error "no match" } +} + +namespace N { struct A { }; } + +void operator+(N::A); +void operator-(N::A); +void operator*(N::A); +void operator~(N::A); +#if __cplusplus >= 201103L +void operator&(N::A) = delete; +#else +void operator&(N::A); +#endif +void operator!(N::A); +void operator++(N::A); +void operator--(N::A); +void operator++(N::A, int); +void operator--(N::A, int); + +void operator->*(N::A, N::A); +void operator/(N::A, N::A); +void operator*(N::A, N::A); +void operator+(N::A, N::A); +void operator-(N::A, N::A); +void operator%(N::A, N::A); +void operator&(N::A, N::A); +void operator|(N::A, N::A); +void operator^(N::A, N::A); +void operator<<(N::A, N::A); +void operator>>(N::A, N::A); +void operator&&(N::A, N::A); +void operator||(N::A, N::A); +#if __cplusplus >= 201103L +void operator,(N::A, N::A) = delete; +#else +void operator,(N::A, N::A); +#endif + +void operator==(N::A, N::A); +void operator!=(N::A, N::A); +void operator<(N::A, N::A); +void operator>(N::A, N::A); +void operator<=(N::A, N::A); +void operator>=(N::A, N::A); +#if __cplusplus > 201703L +void operator<=>(N::A, N::A); +#endif + +void operator+=(N::A, N::A); +void operator-=(N::A, N::A); +void operator*=(N::A, N::A); +void operator/=(N::A, N::A); +void operator%=(N::A, N::A); +void operator|=(N::A, N::A); +void operator^=(N::A, N::A); +void operator<<=(N::A, N::A); +void operator>>=(N::A, N::A); + +int main() { + f(N::A()); +}