[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:
parent
410902c31c
commit
d794ab85f7
4 changed files with 97 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
73
gcc/testsuite/g++.dg/lookup/pr87531.C
Normal file
73
gcc/testsuite/g++.dg/lookup/pr87531.C
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue