c++: using operator= [PR105223]
authorJason Merrill <jason@redhat.com>
Mon, 11 Apr 2022 21:51:43 +0000 (17:51 -0400)
committerJason Merrill <jason@redhat.com>
Tue, 12 Apr 2022 03:57:08 +0000 (23:57 -0400)
In a template class A we normally add an implicit using A::operator= as a
placeholder for the implicitly declared operator whose signature we don't
know yet.  In my patch for PR92918 I stopped doing that if the class has an
explicit operator=, but that was wrong; an operator= taking an unrelated
type doesn't prevent the implicit declaration.

When I was working on that patch, the change was necessary to avoid another
regression, but apparently it is no longer needed.

PR c++/105223
PR c++/92918

gcc/cp/ChangeLog:

* class.cc (finish_struct): Always using op=.

gcc/testsuite/ChangeLog:

* g++.dg/template/using31.C: New test.

gcc/cp/class.cc
gcc/testsuite/g++.dg/template/using31.C [new file with mode: 0644]

index 40e1714..bfda006 100644 (file)
@@ -7723,17 +7723,14 @@ finish_struct (tree t, tree attributes)
         lookup not to fail or recurse into bases.  This isn't added
         to the template decl list so we drop this at instantiation
         time.  */
-      if (!get_class_binding_direct (t, assign_op_identifier, false))
-       {
-         tree ass_op = build_lang_decl (USING_DECL, assign_op_identifier,
-                                        NULL_TREE);
-         DECL_CONTEXT (ass_op) = t;
-         USING_DECL_SCOPE (ass_op) = t;
-         DECL_DEPENDENT_P (ass_op) = true;
-         DECL_ARTIFICIAL (ass_op) = true;
-         DECL_CHAIN (ass_op) = TYPE_FIELDS (t);
-         TYPE_FIELDS (t) = ass_op;
-       }
+      tree ass_op = build_lang_decl (USING_DECL, assign_op_identifier,
+                                    NULL_TREE);
+      DECL_CONTEXT (ass_op) = t;
+      USING_DECL_SCOPE (ass_op) = t;
+      DECL_DEPENDENT_P (ass_op) = true;
+      DECL_ARTIFICIAL (ass_op) = true;
+      DECL_CHAIN (ass_op) = TYPE_FIELDS (t);
+      TYPE_FIELDS (t) = ass_op;
 
       TYPE_SIZE (t) = bitsize_zero_node;
       TYPE_SIZE_UNIT (t) = size_zero_node;
diff --git a/gcc/testsuite/g++.dg/template/using31.C b/gcc/testsuite/g++.dg/template/using31.C
new file mode 100644 (file)
index 0000000..bfeb94f
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/105223
+
+struct ServiceReferenceBase {
+  void operator=(int);
+};
+
+template<class>
+struct ServiceReference : ServiceReferenceBase {
+  void foo() { operator=(0); }
+  using ServiceReferenceBase::operator=;
+};
+
+int main() {
+  ServiceReference<int> sr;
+  sr.foo();
+}