From: Nathan Sidwell Date: Wed, 28 Nov 2018 21:25:06 +0000 (+0000) Subject: [PR c++/87531] operator= lookup in templates X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d794ab85f7b14b546701c23f357d49bbab474d39;p=gcc.git [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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5af15e3845f..8b8a857bd37 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2018-11-28 Nathan Sidwell + + PR c++/87531 + * class.c (finish_struct): In a template, add artificial using + decl for operator=. + 2018-11-28 Jan Hubicka * except.c (do_allocate_exception): Annotate __cxa_allocate_exception diff --git a/gcc/cp/class.c b/gcc/cp/class.c index be3b4bbbe19..57261511a90 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 575c6316c89..740671978b8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-11-28 Nathan Sidwell + + PR c++/87531 + * g++.dg/lookup/pr87531.C: New. + 2018-11-28 Jan Hubicka * 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 00000000000..4765343b68a --- /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 +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 +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 a, b(123); + + if (a.assign1 (b) != 123) + return 1; + + if (a.assign2 (b) != 123) + return 2; + + Single c, d(123); + + if (c.assign1 (d) != 123) + return 3; + + if (c.assign2 (d) != 123) + return 4; + + return 0; +}