[PR c++/87531] operator= lookup in templates
authorNathan Sidwell <nathan@acm.org>
Wed, 28 Nov 2018 21:25:06 +0000 (21:25 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 28 Nov 2018 21:25:06 +0000 (21:25 +0000)
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg02301.html
PR c++/87531
* class.c (finish_struct): In a template, add artificial using
decl for operator=.

* g++.dg/lookup/pr87531.C: New.

From-SVN: r266590

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/pr87531.C [new file with mode: 0644]

index 5af15e3845f3abee5efce2e8dac2e0163bc7597a..8b8a857bd3710cbb59a48d5466b5ea8534acd921 100644 (file)
@@ -1,3 +1,9 @@
+2018-11-28  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/87531
+       * class.c (finish_struct): In a template, add artificial using
+       decl for operator=.
+
 2018-11-28  Jan Hubicka  <hubicka@ucw.cz>
 
        * except.c (do_allocate_exception): Annotate __cxa_allocate_exception
index be3b4bbbe19e6828374b4543a5f20a2ba09a579f..57261511a9001c8a72b5afe688b1520e7d078664 100644 (file)
@@ -7150,6 +7150,19 @@ finish_struct (tree t, tree attributes)
        else if (DECL_DECLARES_FUNCTION_P (x))
          DECL_IN_AGGR_P (x) = false;
 
+      /* Also add a USING_DECL for operator=.  We know there'll be (at
+        least) one, but we don't know the signature(s).  We want name
+        lookup not to fail or recurse into bases.  This isn't added
+        to the template decl list so we drop this at instantiation
+        time.  */
+      tree ass_op = build_lang_decl (USING_DECL, assign_op_identifier,
+                                    NULL_TREE);
+      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;
       /* COMPLETE_TYPE_P is now true.  */
index 575c6316c89ef4c58734185fa83891e2c7e91012..740671978b8bb25a072aefa4586e4c211322f786 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-28  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/87531
+       * g++.dg/lookup/pr87531.C: New.
+
 2018-11-28  Jan Hubicka  <jh@suse.cz>
 
        * gcc.dg/predict-13.c: Update template.
diff --git a/gcc/testsuite/g++.dg/lookup/pr87531.C b/gcc/testsuite/g++.dg/lookup/pr87531.C
new file mode 100644 (file)
index 0000000..4765343
--- /dev/null
@@ -0,0 +1,73 @@
+// PR c+/87531 lookup of operator= in templates
+// { dg-do run }
+
+struct Base {
+  void operator= (Base const&);
+};
+
+void Base::operator= (Base const &)
+{
+}
+
+template <typename T>
+struct Derived : Base
+{
+  T v;
+
+  Derived() : v (0) {}
+  Derived(T v_) : v (v_) {}
+
+  T &assign1 (Derived const& rhs)
+  {
+    operator=(rhs); // erroneously bound to Base::operator=
+    return v;
+  }
+
+  T &assign2 (Derived const& rhs)
+  {
+    this->operator=(rhs); // erroneously bound to Base::operator=
+    return v;
+  }
+};
+
+template <typename T>
+struct Single
+{
+  T v;
+
+  Single () : v (0) {}
+  Single (T v_) : v (v_) {}
+
+  T &assign1 (Single const& rhs)
+  {
+    operator=(rhs); // lookup failed
+    return v;
+  }
+
+  T &assign2 (Single const& rhs)
+  {
+    this->operator=(rhs); // Marked as dependent, happened to work
+    return v;
+  }
+};
+
+int main()
+{
+  Derived<int> a, b(123);
+
+  if (a.assign1 (b) != 123)
+    return 1;
+
+  if (a.assign2 (b) != 123)
+    return 2;
+
+  Single<int> c, d(123);
+  
+  if (c.assign1 (d) != 123)
+    return 3;
+
+  if (c.assign2 (d) != 123)
+    return 4;
+
+  return 0;
+}