[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
This commit is contained in:
Nathan Sidwell 2018-11-28 21:25:06 +00:00 committed by Nathan Sidwell
parent 410902c31c
commit d794ab85f7
4 changed files with 97 additions and 0 deletions

View 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

View 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. */

View 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.

View file

@ -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;
}