aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2018-11-28 21:25:06 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2018-11-28 21:25:06 +0000
commitd794ab85f7b14b546701c23f357d49bbab474d39 (patch)
treeaf6a1973befb50407eadb8f349b613955ef97097
parent410902c31caa82cf414f020b5db51ddc20159f20 (diff)
downloadgcc-d794ab85f7b14b546701c23f357d49bbab474d39.zip
gcc-d794ab85f7b14b546701c23f357d49bbab474d39.tar.gz
gcc-d794ab85f7b14b546701c23f357d49bbab474d39.tar.bz2
[PR c++/87531] operator= lookup in templates
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
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/class.c13
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr87531.C73
4 files changed, 97 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5af15e3..8b8a857 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index be3b4bb..5726151 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 575c631..7406719 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..4765343
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr87531.C
@@ -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;
+}