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());
+}